Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android Loader——裝載器

android Loader——裝載器

編輯:關於Android編程


android Loader——裝載器

一、Loader簡介: (一)、Loader的概念:

裝載器從android3.0開始引進。它使得在activity或fragment中異步加載數據變得簡單。裝載器具有如下特性:

它們對每個Activity和Fragment都有效。
他們提供了異步加載數據的能力。
它擁有一個數據改變通知機制,當數據源做出改變時會及時通知。
當Cursor 發生變化時,會自動加載數據,因此並不需要再重新進行數據查詢。
android設計Loader的初衷是想讓大家像CursorLoader的做法一樣,通過loader去維護數據,每次啟動loader時先檢查有沒有舊的數據並把舊的數據先deliver給用戶,然後再考慮要不要重新加載新的數據。

(二)、裝載器API概述:

在使用裝載器時,會涉及很多類和接口們,在下表中對它們總結一下:

Class/Interface

說明

LoaderManager

一個抽像類,關聯到一個Activity或Fragment,管理一個或多個裝載器的實例。這幫助一個應用管理那些與Activity或Fragment的生命周期相關的長時間運行的的操作。最常見的方式是與一個CursorLoader一起使用,然而應用是可以隨便寫它們自己的裝載器以加載其它類型的數據。

每個activity或fragment只有一個LoaderManager。但是一個LoaderManager可以擁有多個裝載器。

LoaderManager.LoaderCallbacks

一個用於客戶端與LoaderManager交互的回調接口。例如,你使用回調方法onCreateLoader()來創建一個新的裝載器。

Loader(裝載器)

一個執行異步數據加載的抽象類。它是加載器的基類。你可以使用典型的CursorLoader,但是你也可以實現你自己的子類。一旦裝載器被激活,它們將監視它們的數據源並且在數據改變時發送新的結果。

AsyncTaskLoader

提供一個AsyncTask來執行異步加載工作的抽象類。

CursorLoader

AsyncTaskLoader的子類,它查詢ContentResolver然後返回一個Cursor。這個類為查詢cursor以標准的方式實現了裝載器的協議,它的游標查詢是通過AsyncTaskLoader在後台線程中執行,從而不會阻塞界面。使用這個裝載器是從一個ContentProvider異步加載數據的最好方式。相比之下,通過fragment或activity的API來執行一個被管理的查詢就不行了。


(三)、類目錄結構:

1、API11中開始加入Loader:

java.lang.Object

? android.content.Loader

? android.content.AsyncTaskLoader


子類:

java.lang.Object

? android.content.Loader

? android.content.AsyncTaskLoader

? android.content.CursorLoader


2、為了兼容1.6以下版本:

java.lang.Object

? android.support.v4.content.Loader

? android.support.v4.content.AsyncTaskLoader


子類:

java.lang.Object

? android.support.v4.content.Loader

? android.support.v4.content.AsyncTaskLoader

? android.support.v4.content.CursorLoader


二、AsyncTaskLoader實例:

(一)、AsyncTaskLoader 實現數據加載的步驟:

1、窗體Activity要實現LoaderManager.LoaderCallbacks接口。至於繼承於Activity還是FragmentActivity要看是否需要支持3.0以下版本。如果需要兼容則繼承於FragmentActivity。

2、創建LoaderManager對象:通過getLoaderManager()或getSupportLoaderManager()方法來實現。如果是繼承於FragmentActivity類,則使用getSupportLoaderManager()方法來創建LoaderManger對象,否則使用前者創建即可;

3、初始化LoaderManager對象:調用initLoader()方法來初始化;

  • initLoader()方法有以下參數:
    • 一個唯一ID來標志裝載器;
    • 可選的參數,用於裝載器初始化時;
    • 一個LoaderManager.LoaderCallbacks的實現。被LoaderManager調用以報告裝載器的事件。一般窗體都實現了這個接口,所以傳的是它自己:this; initLoader()保證一個裝載器被初始化並激活.它具有兩種可能的結果:
      • 如果ID所指的裝載器已經存在,那麼這個裝載器將被重用;
      • 如果裝載器不存在,initLoader()就觸發LoaderManager.LoaderCallbacks中的回調方法onCreateLoader()。這是實例化並返回一個新Loader的地方。
        4、操作ListView控件對象:先findViewById(),然後setAdapter(); 【備注:】此時必須使用SimpleCursorAdater適配器,而構建適配器的時候,第三個參數Cursor設置為null,最後一個參數:flags必須是:CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER。


        5、自定義Loader,作為onCreateLoader()的返回值(也就是說onCreateLoader()方法必須返回自定義Loader的實例);

          • 自定義Loader要繼承於AsyncTaskLoader
          • 必須要有構造方法;
          • 必須重寫onStartLoading()、loadInBackground() 、deliverResult()。而且要在onStartLoading中調用forceLoad()才能依次調用下一個即將執行的方法。
            • 在loadInBackground()方法中執行數據庫查詢,返回Cursor;
            • 在deliverResult()方法中執行跟適配器交換數據的操作。adapter.swapCursor(data)。

              【知識回顧:】SimpleCursorAdapter構造方法的參數講解。 方法原型:new SimpleCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to , int flags) ;
              參數: 1)、Context context, 這個與 SimpleListItemFactory 相關的 ListView 所處運行上下文(context)。 也就是這個 ListView 所在的 Activity。 2)、int layout, 顯示 list item 的 布局文件。這個 layout 文件中至少要包含在 "to" 參數中命名的 views。 3)、Cursor c, 數據庫的光標( Cursor )。如果 cursor 無效,則該參數可以為 null 4)、String[] from, 指定 column 中的哪些列的數據將綁定(顯示)到 UI 中。如果 cursor 無效, 則該參數可為 null。 5)、int[] to, 指定用於顯示 "from" 參數指定的數據列表的 views。 這些 views 必須都是 TextViews。 "from" 參數的前 N 個值(valus)和 "to" 參數的前 N 個 views 是一一對應的關系。如果 cursor 無效,則該參數可為 null。 6)、flags,用於定義適配器行為的標志位。

              Flags used to determine the behavior of the adapter; may be any combination of FLAG_AUTO_REQUERY and FLAG_REGISTER_CONTENT_OBSERVER。
              FLAG_AUTO_REQUERY(常量值:1 )從 API11 開始已經廢棄。因為他會在應用程序的 UI 線程中執行游標查詢操作, 導致響應緩慢甚至應用程序無響應(ANR)的錯誤。作為替代方案,請使用 LoaderManager 和 AsyncTaskLoader、CursorLoader。
              如果設置FLAG_REGISTER_CONTENT_OBSERVER(常量值:2),適配器會在Cursor上注冊一個內容觀測器,當通知到達時會調用 onContentChanged() 方法。
              (二)、LoaderManager.LoaderCallbacks主要回調方法:
              1、onCreateLoader() :初始化並返回一個新的Loader; 當你試圖去操作一個裝載器時(比如,通過initLoader()),會檢查是否指定ID的裝載器已經存在.如果它不存在,將會觸發LoaderManager.LoaderCallbacks 的方法onCreateLoader();
              2、onLoadFinished():當一個裝載器完成了它的裝載過程後被調用; 這個方法是在前面已創建的裝載器已經完成其加載過程後被調用.這個方法保證會在應用到裝載器上的數據被釋放之前被調用;
              3、onLoaderReset() :當一個裝載器被重置而其數據無效時被調用。

              當一個已創建的裝載器被重置從而使其數據無效時,此方法被調用.此回調使你能發現什麼時候數據將被釋放。你可以釋放對它的引用。



              (四)、AsyncTaskLoader中各個方法的執行順序:
              04-01 04:00:25.477: MainActivity: ==onCreate
              
              04-01 04:00:25.701: LoaderCallbacks: ==onCreateLoader
              
              04-01 04:00:25.705: AsyncTaskLoader: ==onStartLoading
              
              04-01 04:00:25.709: AsyncTaskLoader: ==loadInBackground
              
              04-01 04:00:25.721: AsyncTaskLoader: ==deliverResult
              
              04-01 04:00:25.721: LoaderCallbacks: ==onLoadFinished
              
              04-01 04:00:25.749: MainActivity: ==onStart
              
              04-01 04:00:25.749: MainActivity: ==onResume
              
              04-01 04:00:25.973: MainActivity: ==onCreateOptionsMenu
              
              
              

              (五)、當另一個app修改了同一個數據源(如:共同使用的SDCard上的數據庫)後 AsyncTaskLoader中各個方法的執行順序:

              04-01 04:01:06.693: MainActivity: ==onPause
              
              04-01 04:01:08.413: MainActivity: ==onStop
              
              04-01 04:01:15.721: AsyncTaskLoader: ==onStartLoading
              
              04-01 04:01:15.721: AsyncTaskLoader: ==loadInBackground
              
              04-01 04:01:15.721: AsyncTaskLoader: ==deliverResult
              
              04-01 04:01:15.721: LoaderCallbacks: ==onLoadFinished
              
              04-01 04:01:15.757: MainActivity: ==onStart
              
              04-01 04:01:15.757: MainActivity: ==onResume
              
              
              

              (三)、示例代碼:


              public class MainActivity extends FragmentActivity implements LoaderManager.LoaderCallbacks{
              
                      private ListView listView_main;
              
                      private LoaderManager manager;
              
                      private static SimpleCursorAdapter adapter;
              
              
              
              @Override
              
                      protected void onCreate(Bundle arg0) {
              
                              super.onCreate(arg0);
              
                              setContentView(R.layout.activity_main);
              
              
              
                              listView_main = (ListView) findViewById(R.id.listView_main);
              

                              manager = getSupportLoaderManager();
              
                              manager.initLoader(0, null, this);
              

                              adapter = new SimpleCursorAdapter(this, R.layout.item_listview_main,
              
                                              null, new String[] { "_id", "title" }, new int[] {
              
              R.id.text_item_title, R.id.text_item_content }, 2);
              
                     
              
               listView_main.setAdapter(adapter);
              
                   }
              
              
              
                      @Override
              
                      public Loader onCreateLoader(int arg0, Bundle arg1) {
              
                          Log.i ("Activity", "===onCreateLoader");
              
                          return new MyLoader(this);
              
                      }
              

                      @Override
              
                      public void onLoadFinished(Loader arg0, Cursor arg1) {
              
                          Log.i ("Activity", "===onLoaderFinished");
              
                          adapter.swapCursor(arg1);
              
                      }
              

                     @Override
              
                      public void onLoaderReset(Loader arg0) {
              
                          Log.i ("Activity", "===onLoaderReset");
              
                      }
              

                      static class MyLoader extends AsyncTaskLoader {
              
                              private Context context;
              
                              public MyLoader(Context context) {
              
                                      super(context);
              
                                      this.context = context;
              
                              }
              

                     @Override
              
                              protected void onStartLoading() {
              
                                      super.onStartLoading();
              
                              Log.i ("MyLoader", "===onStartLoading");
              
                                      forceLoad();
              
                              }
              

                             @Override
              
                              public Cursor loadInBackground() {
              
                                      Log.i ("MyLoader", "===loadInBackground");
              
                                      MySQLiteDatabaseHelper dbHelper = new MySQLiteDatabaseHelper();
              
                                      Cursor cursor = dbHelper.selectCursor("select id as _id , title from android_info limit 0,20",
              
              null);
              
              
              
                                      deliverResult(cursor);
              
                                      return cursor;
              
                              }
              

                             @Override
              
                              public void deliverResult(Cursor data) {
              
                                      Log.i ("MyLoader", "===deliverResult");
              
                                      super.deliverResult(data);
              
                                      adapter.swapCursor(data);
              
                              }
              
                      }
              
              }
              

              三、CursorLoader實例:

              (一)、CursorLoader 實現數據加載的步驟:

              1、窗體Activity要實現LoaderManager.LoaderCallbacks接口。至於繼承於Activity還是FragmentActivity要看是否需要支持3.0以下版本。如果需要兼容則繼承於FragmentActivity。

              2、創建LoaderManager對象:通過getLoaderManager()或getSupportLoaderManager()方法來實現。如果是繼承於FragmentActivity類,則使用getSupportLoaderManager()方法來創建LoaderManger對象,否則使用前者創建即可;

              3、初始化LoaderManager對象:調用initLoader()方法來初始化;

              - initLoader()方法有以下參數: - 一個唯一ID來標志裝載器 - 可選的參數,用於裝載器初始化時 - 一個LoaderManager.LoaderCallbacks的實現。被LoaderManager調用以報告裝載器的事件。一般窗體都實現了這個接口,所以傳的是它自己:this;
              - initLoader()保證一個裝載器被初始化並激活.它具有兩種可能的結果: - 如果ID所指的裝載器已經存在,那麼這個裝載器將被重用; - 如果裝載器不存在,initLoader()就觸發LoaderManager.LoaderCallbacks中的回調方法
              onCreateLoader()。這是實例化並返回一個新Loader的地方。
              4、操作ListView控件對象:先findViewById(),然後setAdapter(); 【備注:】此時必須使用SimpleCursorAdater適配器,而構建適配器的時候,第三個參數Cursor設置為null,最後一個參數:flags必須是:CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER。
              5、重寫onCreateLoader()方法。返回CursorLoader的構造方法。 例如: return new CursorLoader(this, uri, null, null, null, null);

              【備注:】new CursorLoader()的參數:

              1、 uri —要獲取的內容的URI;

              2、projection —要返回的列組成的數組。傳入null 將會返回所有的列,但這樣會導致低效;

              3、selection —表明哪些行將被返回,相當於SQL語句中的WHERE條件 (不包括WHERE關鍵詞)。傳入null 將返回所有的行;

              4、selectionArgs —Where語句中的'?’組成的數組。

              5、sortOrder —如何排序,相當於SQL語句中的 ORDER BY 語句(不包括ORDER BY關鍵詞)。傳入null將使用默認順序。


              (二)、示例代碼:


              public class MainActivity extends Activity implements LoaderCallbacks {
              
                      private ListView listView_main;
              
                      private Uri uri = Uri.parse ("content://com.steven.mywordsprovider/tb_words");
              
                      private SimpleCursorAdapter adapter = null;
              

                     @Override
              
                      protected void onCreate(Bundle savedInstanceState) {
              
                              super.onCreate(savedInstanceState);
              
                              setContentView(R.layout.activity_main);
              
                              Log.i ("MainActivity", "==onCreate");
              

                              listView_main = (ListView) findViewById(R.id.listView_main);
              
                              adapter = new SimpleCursorAdapter(this, R.layout.item_listview, null,
              
                                              new String[] { "words", "detail" }, new int[] {
              
                                                           R.id.text_item_listview_id, R.id.text_item_listview_title },
              
                                           CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
              

                              listView_main.setAdapter(adapter);
              

                              LoaderManager loaderManager = getLoaderManager();
              
                              loaderManager.initLoader(2, null, this);
              
                      }
              

                     @Override
              
                      public Loader onCreateLoader(int id, Bundle args) {
              
                              Log.i ("Callbacks", "==onCreateLoader");
              
                              return new CursorLoader(this, uri, null, null, null, null);
              
                      }
              

                      @Override
              
                      public void onLoadFinished(Loader loader, Cursor data) {
              
                              Log.i ("Callbacks", "==onLoadFinished");
              
                              adapter.swapCursor(data);
              
                      }
              

                     @Override
              
                      public void onLoaderReset(Loader loader) {
              
                      Log.i ("Callbacks", "==onLoaderReset");
              
                              adapter.swapCursor(null);
              
                      }
              
              }
              


              四、CursorLoader結合ActionBar上的SearchView實現過濾搜索:

              (一)、主窗體布局核心代碼:


              
              
              
              
              
              
              
              
              
              
              
              
                  android:layout_width="fill_parent"
              
                  android:layout_height="fill_parent"
              
                  android:orientation="vertical" >
              

                  
              
              
              
              
              
              
              
              
              
              
              
                      android:id="@+id/listView_main"
              
                      android:layout_width="match_parent"
              
                      android:layout_height="match_parent" >
              
                  
              

                  
              
              
              
              
              
              
              
              
              
              
              
                      android:id="@+id/text_emptyinfo"
              
                      android:gravity="center"
              
                      android:textSize="24sp"
              
                      android:layout_width="match_parent"
              
                      android:layout_height="match_parent"
              
                      android:text="沒有該詞匯!" />
              
              
              
              
              


              (二)、Menu菜單的xml:

                 
              
                  
              
              
              
              
              
              
              
              
              
              
              
                      android:id="@+id/searchView_actionBar"
              
                      android:showAsAction="always"
              
                      android:actionViewClass="android.widget.SearchView"
              
                      android:title="搜索"/>
              
              
              

              (三)、主窗體Java核心代碼:


              public class MainActivity extends Activity implements LoaderCallbacks {
              
                      private ListView listView_main;
              
                      private TextView text_emptyinfo;
              
                      private SimpleCursorAdapter adapter = null;
              
                      private String uri_path;
              

                      @Override
              
                      protected void onCreate(Bundle savedInstanceState) {
              
                              super.onCreate(savedInstanceState);
              
                              setContentView(R.layout.activity_main);
              
                              Log.i ("MainActivity", "==onCreate");
              

                              listView_main = (ListView) findViewById(R.id.listView_main);
              
                              text_emptyinfo = (TextView) findViewById(R.id.text_emptyinfo);
              

                              adapter = new SimpleCursorAdapter(this, R.layout.item_listview, null,
              
                                              new String[] { "words", "detail" }, new int[] {R.id.text_item_listview_id,
              
                                              R.id.text_item_listview_title },CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
              

                              listView_main.setAdapter(adapter);
              
                              listView_main.setEmptyView(text_emptyinfo);
              

                              LoaderManager loaderManager = getLoaderManager();
              
                              loaderManager.initLoader(2, null, this);
              
                      }
              

                      @Override
              
                      public Loader onCreateLoader(int id, Bundle args) {
              
                              Log.i ("Callbacks", "==onCreateLoader");
              
                              Uri baseUri = Uri.parse ("content://com.steven.mywordsprovider/tb_words");
              

                              if (uri_path != null) {
              
                                      baseUri = Uri.withAppendedPath (baseUri, uri_path);
              
                              }
              
                              return new CursorLoader(this, baseUri, null, null, null, null);
              
                      }
              

                      @Override
              
                      public void onLoadFinished(Loader loader, Cursor data) {
              
                          Log.i ("Callbacks", "==onLoadFinished");
              
                              adapter.swapCursor(data);
              
                      }
              

                      @Override
              
                      public void onLoaderReset(Loader loader) {
              
                              Log.i ("Callbacks", "==onLoaderReset");
              
                              adapter.swapCursor(null);
              
                      }
              

                     @Override
              
                      public boolean onCreateOptionsMenu(Menu menu) {
              
                              getMenuInflater().inflate(R.menu.main, menu);
              
                              SearchView searchView_actionBar = (SearchView) menu.findItem(
              
                                              R.id.searchView_actionBar).getActionView();
              

                              searchView_actionBar.setOnQueryTextListener(new OnQueryTextListener() {
              
                                     @Override
              
                                      public boolean onQueryTextSubmit(String query) {
              
                                             return false;
              
                                      }
              

                                     @Override
              
                                      public boolean onQueryTextChange(String newText) {
              
                                              if (newText == null) {
              
                                                      uri_path = null;
              
                                              } else {
              
                                                      uri_path = newText;
              
                                              }
              
              
              
                                              // 更新搜索過濾,重新啟動Loader進行新的查詢.
              
                                              getLoaderManager().restartLoader(0, null, MainActivity.this);
              
                                              return true;
              
                                      }
              
                              });
              
                         return true;
              
                      }
              
              }
              


              (四)、ContentProvider中的核心代碼:


              public class MyProvider extends ContentProvider {
              
                      private MySQLiteOpenHelper dbHelper = null;
              
                      private SQLiteDatabase db = null;
              
                      private static UriMatcher matcher = null;
              
                      private static String AUTHORITY = "com.steven.mywordsprovider";
              

              static {
              
                              matcher = new UriMatcher(UriMatcher.NO_MATCH);
              
                              matcher.addURI(AUTHORITY, "tb_words", 1);
              
                              matcher.addURI(AUTHORITY, "tb_words/*", 2);
              
                              matcher.addURI(AUTHORITY, "tb_words/#", 3);
              
                      }
              

                     @Override
              
                      public boolean onCreate() {
              
                              dbHelper = new MySQLiteOpenHelper(getContext());
              
                              db = dbHelper.getReadableDatabase();
              
                              return true;
              
                      }
              

              @Override
              
                      public Cursor query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder) {
              
                              switch (matcher.match(uri)) {
              
                              case 1:
              
                                      Cursor cursor = db.query("tb_words", projection, selection,selectionArgs, null, null, sortOrder)
              
                                      return cursor;
              
                              case 2:
              
                                      String search_str = uri.getPathSegments().get(1);
              
                                      if (selection == null) {
              
                                              selection = "words like '" + search_str + "%'";
              
                                      } else {
              
                                              selection += " and words like '" + search_str + "'%";
              
                                      }
              
              
              
                                      Cursor cursor2 = db.query("tb_words", projection, selection,
              
              selectionArgs, null, null, sortOrder);
              
                                      return cursor2;
              
                              default:
              
                                 break;
              
                              }
              
                         return null;
              
                      }
              

                      @Override
              
                      public String getType(Uri uri) {
              
                              return null;
              
                      }
              

                      @Override
              
                      public Uri insert(Uri uri, ContentValues values) {
              
                      return null;
              
                      }
              

                     @Override
              
                      public int delete(Uri uri, String selection, String[] selectionArgs) {
              
                              return 0;
              
                      }
              

                     @Override
              
                      public int update(Uri uri, ContentValues values, String selection,String[] selectionArgs) {
              
                             return 0;
              
                      }
              
              }
              

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved