Android之Loader

Loader在android3.0以后出現(xiàn),它可以使Activity和Fragment異步加載數(shù)據(jù)變得簡單
當(dāng)成批顯示數(shù)據(jù)時,為了使用戶的體驗更好,需要進行異步裝載,也就是說,讓未顯示數(shù)據(jù)的ListView等UI組件或控件先顯示,避免出現(xiàn)白屏的尷尬現(xiàn)象,同時在后臺下載數(shù)據(jù),等下載完成后再更新ListView組件。這樣盡管用戶不會立刻看到數(shù)據(jù),但是也不至于網(wǎng)絡(luò)速度緩慢或服務(wù)器響應(yīng)不及時而造成假死現(xiàn)象。

Loader的特性:

  • 它對每個Activity和Fragment都有效
  • 它提供了異步加載數(shù)據(jù)的能力
  • 它擁有一個數(shù)據(jù)改變通知機制,當(dāng)數(shù)據(jù)源做出改變時會及時通知。也就是可以監(jiān)聽數(shù)據(jù)源,一旦數(shù)據(jù)源發(fā)生變化,Loader會感知這些變化
  • 當(dāng)Cursor發(fā)生變化時,會自動加載數(shù)據(jù),因此不需要再重新進行數(shù)據(jù)查詢

API概述

  • LoaderManager
    一個抽像類,關(guān)聯(lián)到一個Activity或Fragment,管理一個或多個裝載器的實例。這幫助一個應(yīng)用管理那些與Activity或Fragment的生命周期相關(guān)的長時間運行的的操作。最常見的方式是與一個CursorLoader一起使用,然而應(yīng)用是可以隨便寫它們自己的裝載器以加載其它類型的數(shù)據(jù)。
    每個activity或fragment只有一個LoaderManager。但是一個LoaderManager可以擁有多個裝載器。
  • LoaderManager.LoaderCallbacks
    一個用于客戶端與LoaderManager交互的回調(diào)接口。例如,你使用回調(diào)方法onCreateLoader()來創(chuàng)建一個新的裝載器。
  • Loader(裝載器)
    一個執(zhí)行異步數(shù)據(jù)加載的抽象類。它是加載器的基類。你可以使用典型的CursorLoader,但是你也可以實現(xiàn)你自己的子類。一旦裝載器被激活,它們將監(jiān)視它們的數(shù)據(jù)源并且在數(shù)據(jù)改變時發(fā)送新的結(jié)果。
  • AsyncTaskLoader
    提供一個AsyncTask來執(zhí)行異步加載工作的抽象類。
  • CursorLoader
    AsyncTaskLoader的子類,它查詢ContentResolver然后返回一個Cursor。這個類為查詢cursor以標(biāo)準(zhǔn)的方式實現(xiàn)了裝載器的協(xié)議,它的游標(biāo)查詢是通過AsyncTaskLoader在后臺線程中執(zhí)行,從而不會阻塞界面。使用這個裝載器是從一個ContentProvider異步加載數(shù)據(jù)的最好方式。相比之下,通過fragment或activity的API來執(zhí)行一個被管理的查詢就不行

使用Loader的步驟

  • 在Activity或者Fragment中,實現(xiàn)LoaderCallBack<Cursor>接口,并且聲明加載數(shù)據(jù)結(jié)果的返回類型,重寫父類的三個方法
    Loader<Cursor> onCreateLoader(int id, Bundle args) //創(chuàng)建新的Loader,加載新的數(shù)據(jù)
    void onLoadFinished(Loader<Cursor> loader, Cursor data) //加載數(shù)據(jù)完成后執(zhí)行
    void onLoaderReset(Loader<Cursor> loader) //在Loader加載數(shù)據(jù)之前,重置之前的數(shù)據(jù)
  • 在Activity或者Fragment的初始化階段的生命周期方法中 初始化啟動Loader
    /**
    * id Loader的編號
    * args Loader加載數(shù)據(jù)的條件
    * callback Loader接口回調(diào)的方法
    */
    getLoaderManager().initLoader(id, args, callback);
  • 在LoaderCallBacks的創(chuàng)建新的Loader的方法中(onCreateLoader) 實例化CursorLoader對象
    CursorLoader loader = new CursorLoader(context, uri, projection, selection, selectionArgs, sortOrder)
    //CursorLoader 內(nèi)部使用了CotentResolver 加載ContentProvider暴露出來的數(shù)據(jù),通過URI內(nèi)置CotentObserver,監(jiān)聽數(shù)據(jù)源的變化
  • 在LoaderCallBacks的加載數(shù)據(jù)完成的方法中(onLoadefinished) 將加載完成的數(shù)據(jù)顯示在ListView中
    adapter.changeCursor(arg1);
  • 在LoaderCallBacks的重置方法中(onLoaderReset), 清除之前的舊數(shù)據(jù)
    adapter.changeCursor(null);

自定義Loader

  • 定義一個類, 繼承AsyncTaskLoader<D> ,聲明返回結(jié)果的類型
  • 重寫方法 onStartLoading() , 執(zhí)行方法: forceLoader()強制執(zhí)行后臺的方法, 加載數(shù)據(jù)
  • 重寫父類的方法 loadInBackground() , 在此方法中執(zhí)行獲取數(shù)據(jù)的操作, 并將結(jié)果返回
  • 構(gòu)造方法

實例(自定義Loader加載短信內(nèi)容)

  • MainActivity.java
    public class MainActivity extends Activity implements LoaderCallbacks<Cursor> {
    private ListView lv;
    private SearchView sv;
    private SimpleCursorAdapter adapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

      lv = (ListView) findViewById(R.id.lv);
      sv = (SearchView) findViewById(R.id.sv);
      
      adapter = new SimpleCursorAdapter(this,
                                        R.layout.item_lv, 
                                        null, 
                                        new String[]{"address","body"},
                                        new int[]{R.id.address,R.id.body}, 
                                        SimpleCursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
      
      lv.setAdapter(adapter);
      
      getLoaderManager().initLoader(1, null, this);
      
      sv.setOnQueryTextListener(new OnQueryTextListener() {
          
          @Override
          public boolean onQueryTextSubmit(String query) {
              // TODO Auto-generated method stub
              return false;
          }
          
          @Override
          public boolean onQueryTextChange(String newText) {
              // TODO Auto-generated method stub
              
              Bundle bundle = new Bundle();
              bundle.putString("key", newText);
              getLoaderManager().restartLoader(1, bundle, MainActivity.this);
              
              return false;
          }
      });
    }
    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
      // TODO Auto-generated method stub
      
      MyLoader loader = new MyLoader(this,args);
      
      return loader;
    }
    
    @Override
    public void onLoadFinished(Loader<Cursor> arg0, Cursor arg1) {
      // TODO Auto-generated method stub
      adapter.changeCursor(arg1);
      
    }
    
    @Override
    public void onLoaderReset(Loader<Cursor> arg0) {
      // TODO Auto-generated method stub
      adapter.changeCursor(null);
      
    }
    }
    
  • MyLoader
    public class MyLoader extends AsyncTaskLoader<Cursor> {

    private Bundle bundle;
    private Uri uri = Uri.parse("content://sms");
    private String []colums = {"_id","address","body"};
    
    public MyLoader(Context context,Bundle bundle) {
      super(context);
      // TODO Auto-generated constructor stub
      this.bundle = bundle;
    }
    
    @Override
    protected void onStartLoading() {
      // TODO Auto-generated method stub
      super.onStartLoading();
      forceLoad();
    }
    
    @Override
    public Cursor loadInBackground() {
      // TODO Auto-generated method stub
      String selection = null;
      String[] selectionArgs = null;
      if (bundle!=null) {
          selection = "body like ? ";
          selectionArgs = new String[]{"%"+bundle.getString("key")+"%"};
      }
      
      Cursor cursor = getContext().getContentResolver().query(uri, colums, selection, selectionArgs, null);
      
      return cursor;
    }
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容