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, null, this);

}

总结

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

本文转自 terry_龙 51CTO博客,原文链接:http://blog.51cto.com/terryblog/794139,如需转载请自行联系原作者

Loaders 的使用,结合Fragments相关推荐

  1. LoaderManager使用具体解释(三)---实现Loaders

    这篇文字将介绍Loader<D>类,而且介绍自己定义Loader的实现.这是本系列的第三篇文章. 一:Loaders之前世界 二:了解LoaderManager 三:实现Loaders 四 ...

  2. 顶点(vertexs) 图元(primitives) 片元(fragments片断) 像素(pixels)

    顶点(vertexs) 图元(primitives) 片元(fragments,又叫片断) 像素(pixels) 阶段1.  顶点 ->图元 几何顶点被组合为图元(点,线段或多边形),然后图元被 ...

  3. Android Fragments 详细使用详细介绍

    其它推荐: [原创]android版本飞鸽传书源码(附图) Android植物大战僵尸对战版源码 实用源码--Android屏幕锁源码 Fragments 诞生初衷 自从Android 3.0中引入f ...

  4. c#使用正则表达式获取TR中的多个TD_一个 Vue 模板可以有多个根节点(Fragments)?

    如果我们试图创建一个没有根节点的Vue模板,比如这样: <template> 我们就会收到编译或运行时错误,因为模板必须具有单个根元素. 通常,我们通过在最外层包裹一层 div 来解决这个 ...

  5. LoaderManager使用详解(三)---实现Loaders

    这篇文字将介绍Loader<D>类,并且介绍自定义Loader的实现.这是本系列的第三篇文章. 一:Loaders之前世界 二:了解LoaderManager 三:实现Loaders 四: ...

  6. webpack4.x Loaders

    在main.js中直接加require('./css/base.css'),然后打包会报错,是因为webpack不支持css文件类型,需要依赖loader. css-loader 处理css中路径引用 ...

  7. [转]使用fragments

    原帖:http://wiki.eoe.cn/page/Fragments.html 一个**碎片**在一个活动中代表一个行为或用户界面的一部分. 你可以在一个单一的活动中组合使用多个碎片以建立一个多窗 ...

  8. android Fragments详解

    android Fragments详解一:概述 android Fragments详解二:创建Fragment 转载于:https://my.oschina.net/liangzhenghui/blo ...

  9. Android Fragments 详细使用

    Fragments 诞生初衷 自从Android 3.0中引入fragments 的概念,根据词海的翻译可以译为:碎片.片段.其上的是为了解决不同屏幕分辩率的动态和灵活UI设计.大屏幕如平板小屏幕如手 ...

最新文章

  1. 利用开源社区打造微服务生态体系
  2. 学习笔记(四)——JavaScript(一)
  3. R开发(part7)--环境空间
  4. 关于exprot 和expert default的区别
  5. 《PHP程序员面试笔试宝典》——如何巧妙地回答面试官的问题?
  6. 获取所有汉字与 Unicode 的对照表
  7. alsa driver--card
  8. Object类中的wait()和notify()
  9. 人口预测模型基础介绍
  10. DroidCamX:合体手机与电脑
  11. 计算机基础5y浏览器,5y浏览器
  12. vue仿微博评论回复_vue教程2-07 微博评论功能
  13. 如何利用魔棒工具抠图_photoshop魔棒工具怎么用 ps魔棒工具抠图教程
  14. Ubuntu 20.04 Please reinstall Android Studio from scratch
  15. 推荐一些国外前端的学习网站
  16. SolidWorks打开step.文件显示模板无效的解决办法
  17. git + 移动端 web 开发
  18. k8s部署微服务项目
  19. c++中关于双循环跳出的小tips
  20. 实验七 12 小数化分数

热门文章

  1. 1、Django项目设计与搭配开发环境
  2. 宝塔面板PM2 nodejs自动化部署
  3. 第42课: Spark Broadcast内幕解密:Broadcast运行机制彻底解密、Broadcast源码解析、Broadcast最佳实践
  4. 品牌对比|斯凯奇 VS 李宁
  5. oracle数据库方案模式,Oracle数据库技术服务方案.doc
  6. c++输出中文乱码怎么办?
  7. 2017身残志坚的定西考生魏祥上清华
  8. 用户福利-ArchSummit全球架构师峰会 优惠码
  9. 面对疫情,我们普通人能做什么?
  10. 2021年中国氨纶行业发展现状及进出口状况分析:氨纶价格创十年新高 [图]