Loaders 的使用,結合Fragments


Loader的特點和使用場所

 

  1.  Loader 可以在Activity 和Fragments 的界面下運行(本篇將結合上篇文章的Fragments的DEMO進行講述如何在Fragments 下使用Loaders)。
  2. 它可以提供類似於AysncTask一樣的異步請求數據加載的功能,實際上它就是來源於AysncTask 的擴展並增加了很多人性化的功能,例如加載進度框、更好的控制API等。
  3. 它擁有一個類似於Windows Phone 開發的MVVM一樣的數據改變通知機制,當數據源做出改變時會及時通知。
  4. 當Cursor 發生變化時,會自動加載數據,因此並不需要再重新進行數據查詢。

Loader API 使用參考

 

  1. LoaderManager
    每一個Activity 和 Fragments 只能存在一個LoaderManager,負責管理界面中的Loader。
  2. LoaderManager.LoaderCallbacks
    位於LoaderManager的子接口,提供眾多的回調接口操作Loader ,如初始化、創建、重新啟動、銷毀、結束等一系列實用接口。
  3. Loader
    與Fragments相似,是一個基礎類,可以由用戶自行擴展適合自己的類
  4. AsyncTaskLoader
    提供了一個基於AsyncTask 工作機制的Loader,查看源碼可以看到其繼承於Loader,並且子類LoadTask 繼承於AsyncTask<Void, Void, D>,並且實現了Runable 接口,功能十分強大。本DEMO就是基於AsyncTaskLoader篇寫。
  5. CursorLoader
    提供了一個基於AsyncTaskLoader工作機制的Loader,查看源碼可以看到其繼承於AsyncTaskLoader,一般繼承OnQueryTextListener,可用於查詢、更改數據源作用。

Loader 詳細使用DEMO

基於上篇的Fragments 代碼,添加Loaders功能,實現加載應用程序數據到界面上,DEMO的運行效果如下:

 

 

 核心代碼為

 應用程序的數據對象類:

public  static  class AppEntry {
         private  final AppListLoader mLoader;
         private  final ApplicationInfo mInfo;
         private  final File mApkFile;
         private String mLable;
         private Drawable mIcon;
         private  boolean mMounted;

         public AppEntry(AppListLoader loader, ApplicationInfo info) {
            mLoader = loader;
            mInfo = info;
            mApkFile =  new File(info.sourceDir);
        }

         public ApplicationInfo getApplicationInfo() {
             return mInfo;
        }

         public String getLable() {
             return mLable;
        }

         public Drawable getIcon() {
             if (mIcon ==  null) {
                 if (mApkFile.exists()) {
                    mIcon = mInfo.loadIcon(mLoader.mPm);
                     return mIcon;
                }  else {
                    mMounted =  false;
                }
            }  else  if (!mMounted) {
                 if (mApkFile.exists()) {
                    mMounted =  true;
                    mIcon = mInfo.loadIcon(mLoader.mPm);
                     return mIcon;
                }
            }  else {
                 return mIcon;
            }
             return mLoader.getContext().getResources().getDrawable(
                    android.R.drawable.sym_def_app_icon);
        }

        @Override
         public String toString() {
             //  TODO Auto-generated method stub
             return mLable.toString();
        }

         void loadLable(Context mContext) {
             if (mLable ==  null || !mMounted) {
                 if (!mApkFile.exists()) {
                    mMounted =  false;
                    mLable = mInfo.packageName;
                }  else {
                    mMounted =  true;
                    CharSequence lable = mInfo.loadLabel(mContext
                            .getPackageManager());
                    mLable = lable !=  null ? lable.toString()
                            : mInfo.packageName;
                }
            }
        }

    }

 

實現AsyncTaskLoader 加載數據

public  static  class AppListLoader  extends AsyncTaskLoader<List<AppEntry>> {

         final InterestingConfigChanges mLastConfig =  new InterestingConfigChanges();
         final PackageManager mPm;

        List<AppEntry> mApps;
        packageIntentReceiver mPackageObserver;

         public AppListLoader(Context context) {
             super(context);
             //  TODO Auto-generated constructor stub
            mPm = getContext().getPackageManager();
        }

        @Override
         public List<AppEntry> loadInBackground() {
             //  TODO Auto-generated method stub
            List<ApplicationInfo> apps = mPm
                    .getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES
                            | PackageManager.GET_DISABLED_COMPONENTS);
             if (apps ==  null)
                apps =  new ArrayList<ApplicationInfo>();
             final Context mContext = getContext();
            List<AppEntry> entries =  new ArrayList<AppEntry>(apps.size());
             for (ApplicationInfo info : apps) {
                AppEntry entry =  new AppEntry( this, info);
                entry.loadLable(mContext);
                entries.add(entry);
            }
            Collections.sort(entries, ALPHA_COMPARATOR);
             return entries;
        }

        @Override
         public  void deliverResult(
                List<com.xuzhi.fragment.FragmentDemoActivity.AppEntry> data) {
             //  TODO Auto-generated method stub
             if (isReset()) {
                 if (data !=  null) {
                     // 釋放資源處理
                }
            }
            
            List<AppEntry> oladApps=data;
            mApps=data;
             if(isStarted()){
                 super.deliverResult(data);
            }
            
            
             if(oladApps!= null){
                 // 釋放資源
            }
        }
        
        
         protected  void onStartLoading() {
             if(mApps!= null)
                deliverResult(mApps);
            
             if(mPackageObserver== null)
                mPackageObserver= new packageIntentReceiver( this);
            
             boolean configChange=mLastConfig.applyNewConfig(getContext().getResources());
            
             if(takeContentChanged()|| mApps==  null || configChange){
                forceLoad();
            }
        };
        
        @Override
         public  void onCanceled(
                List<com.xuzhi.fragment.FragmentDemoActivity.AppEntry> data) {
             //  TODO Auto-generated method stub
             super.onCanceled(data);
            cancelLoad();
        }
        
        @Override
         protected  void onReset() {
             //  TODO Auto-generated method stub
             super.onReset();
            onStopLoading();
            
             if(mApps!= null){
                 // 釋放資源
                mApps= null;
            }
            
             if(mPackageObserver!= null){
                getContext().unregisterReceiver(mPackageObserver);
                mPackageObserver= null;
            }
        }

    }

 

實現數據源:

public  static  class AppListAdapter  extends ArrayAdapter<AppEntry>{

        
         private LayoutInflater mInflater;
         public AppListAdapter(Context context) { 
             //  TODO Auto-generated constructor stub
             super(context, android.R.layout.simple_list_item_2);
            mInflater=(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            
        }
        
        
         public  void setData(List<AppEntry> data){
            clear();
             if(data!= null){
                addAll(data);
            }
        }
        
        @Override
         public View getView( int position, View convertView, ViewGroup parent) {
             //  TODO Auto-generated method stub
            View view;
             if(convertView== null){
                view=mInflater.inflate(R.layout.list_item_icon_text, parent, false);
            } else{
                view=convertView;
            }
            
            AppEntry item=getItem(position);
            ((ImageView)view.findViewById(R.id.icon)).setImageDrawable(item.getIcon());
            ((TextView)view.findViewById(R.id.text)).setText(item.getLable());
             return view;
        }
        

    }

 

在Activity 或者Fragments 里面實現接口:
public static class DetailsFragment extends ListFragment implements OnQueryTextListener,LoaderCallbacks<List<AppEntry>>

實現接口里面的函數:

public  boolean onQueryTextChange(String newText) {
             //  TODO Auto-generated method stub
             return  false;
        }

         public  boolean onQueryTextSubmit(String query) {
             //  TODO Auto-generated method stub
             return  false;
        }

         
         public Loader<List<com.xuzhi.fragment.FragmentDemoActivity.AppEntry>> onCreateLoader(
                 int id, Bundle args) {
             //  TODO Auto-generated method stub
             return  new AppListLoader(getActivity());
        }

         /**
         * Load 完成后
         
*/
         public  void onLoadFinished(
                Loader<List<com.xuzhi.fragment.FragmentDemoActivity.AppEntry>> arg0,
                List<com.xuzhi.fragment.FragmentDemoActivity.AppEntry> arg1) {
             //  TODO Auto-generated method stub
            mAdapter.setData(arg1);
               if (isResumed()) {
                    setListShown( true);
                }  else {
                    setListShownNoAnimation( true);
                }
        }

         /**
         * Loader 重置時
         
*/
         public  void onLoaderReset(
                Loader<List<com.xuzhi.fragment.FragmentDemoActivity.AppEntry>> arg0) {
             //  TODO Auto-generated method stub
             mAdapter.setData( null);

        } 

得到LoaderManager初始化Loader,啟動加載在Fragment 的onActivityCreated回調方法上添加,本DEMO的DetailsFragment類添加:

@Override
         public  void onActivityCreated(Bundle savedInstanceState) {
             //  TODO Auto-generated method stub
             super.onActivityCreated(savedInstanceState);
            mAdapter =  new AppListAdapter(getActivity());
            setListAdapter(mAdapter);
            
             //  Start out with a progress indicator.
            setListShown( false);

             //  Prepare the loader.  Either re-connect with an existing one,
            
//  or start a new one.
            getLoaderManager().initLoader(0,  nullthis);

        } 

 

總結

Loader的使用分為以下幾個步驟:

  1.  實現自己的異步Loader ,如本篇的AsyncTaskLoader或者CursorLoader或者自己繼承Loader,第二步需要用到這個Loader
  2. 創建數據源->public static class AppListAdapter extends ArrayAdapter<AppEntry>
  3. 在Activity 或者Fragments 上實現OnQueryTextListener,LoaderManager.LoaderCallbacks接口
  4. 在onCreateLoader里面返回Loader,在onLoadfinished里面做清除動作,在onQueryTextChange或者onQueryTextSubmit改變數據源,在onCreate里面讓Loader去執行請求數據getLoaderManager().initLoader(0, null, this);

 

源碼下載:/Files/TerryBlog/FragmentLoader.zip

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM