继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

android 自定义 loader实现

慕码人3916992
关注TA
已关注
手记 112
粉丝 81
获赞 3602

android 的loader是android 3.0后的一种异步数据加载机制。
使用起来也颇为方便。
以下这块摘抄自工匠若水的博客

在Android中任何耗时的操作都不能放在UI主线程中,所以耗时的操作都需要使用异步实现。同样的,在ContentProvider中也可能存在耗时操作,这时也该使用异步操作,而3.0之后最推荐的异步操作就是Loader。它可以方便我们在Activity和Fragment中异步加载数据,而不是用线程或AsyncTask,他的优点如下:

 1.提供异步加载数据机制;
 2.对数据源变化进行监听,实时更新数据;
 3.在Activity配置发生变化(如横竖屏切换)时不用重复加载数据;
 4.适用于任何Activity和Fragment;

这位同学基本介绍了很多东西,以及源码分析,我就不重复造轮子了,我就主要写一下,自定义loader的实现:
首先我建立一个数据源类(数据源可以是本地数据库,可以是网络获取,可以是任何)
TestData:

public class TestData {
    private List<People> peopleList = new ArrayList<>();
    interface Change{
        void onChange();
    }
    public void save (People people,Change change){
        peopleList.add(people);
        if(change!=null){
            change.onChange();
        }
    }
    public List<People> getPeopleList (){
        return peopleList;
    }
}

为了清晰的理解loader的自定义用法,我对代码进行了极大的精简:
这个数据源简单的不能再简单了:
我建立了一个接口:

interface Change{
        void onChange();
    }

这个主要是为了loader可以调用,对数据进行更新。
save主要是对数据进行更新。
有了数据源,我们就可以建立自定义loader了:
MyTestLoader:

public class MyTestLoader extends AsyncTaskLoader<List<People>> implements TestData.Change {
    public MyTestLoader(Context context) {
        super(context);
    }
    TestData testData ;
    public MyTestLoader(Context context,TestData testData) {
        super(context);
        this.testData = testData;
    }
    @Override
    public List<People> loadInBackground() {
        List<People> data = testData.getPeopleList();
        List<People> data2 = new ArrayList<>();
        data2.addAll(data);
        return data2;
    }
    @Override
    protected void onReset() {
        onStopLoading();
    }
    @Override
    protected void onStartLoading() {
        super.onStartLoading();
        deliverResult(testData.getPeopleList());
        if (takeContentChanged()) {
            forceLoad();
        }
    }
    @Override
    protected void onStopLoading() {
        super.onStopLoading();
        cancelLoad();
    }
    @Override
    public void deliverResult(List<People> data) {
        if (isReset()) {
            return;
        }
        if (isStarted()) {
            super.deliverResult(data);
        }
    }

    @Override
    public void onChange() {
        if (isStarted()) {
            forceLoad();
        }
    }

}

首先构造函数中添加数据源的引用。其次重写如下方法
loadInBackground:主要是进行异步加载数据的,在其中,我将数据源的数据return出来了。
以下为一对。
onStartLoading:生命周期,在创建时成立。
onStopLoading:生命周期,在结束时调用。
onChange:就是数据源里的接口,当调用时候,进行forceLoad
deliverResult:则是真正的返回数据。

自定义的loader基本就是这样了,我们进行对这个自定义loader运用。

建立一个activity,实现如下接口LoaderManager.LoaderCallbacks<List<People>>

public class MActivity extends BaseActivity implements LoaderManager.LoaderCallbacks<List<People>>

修改如下方法:

        testData = new TestData();
        testLoader = new MyTestLoader(this,testData);
                getSupportLoaderManager().initLoader(0, null, this);
@Override
    public Loader<List<People>> onCreateLoader(int id, Bundle args) {
        return testLoader;
    }

    @Override
    public void onLoadFinished(Loader<List<People>> loader, List<People> data) {
        if (data != null) {
            Logger.i("数据为"+data.toString());
        } else {
            Logger.i("数据为null");
        }
    }

    @Override
    public void onLoaderReset(Loader<List<People>> loader) {

    }

再建立一个点击事件,进行调用

fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                People p = new People();
                p.setName("wanger");
                testData.save(p,testLoader);

            }
        });

接下来就是见证奇迹的时刻了,
日志里便打印出了详细的数据:
log如下:

数据为[People{name='wanger'}, People{name='wanger'}, People{name='wanger'}, People{name='wanger'}, People{name='wanger'}, People{name='wanger'}]

如上便是自定义loader的实现:谢谢观看,小弟才疏学浅,如有错误,帮我指出。

打开App,阅读手记
7人推荐
发表评论
随时随地看视频慕课网APP

热门评论

我不管,我就赞自己 

查看全部评论