Loader简单分析 AsyncTaskLoader简单使用

AsyncTaskLoader VS AsyncTask

  • 数据影响UI还是的用AsyncTask为好
  • AsyncTaskLoader主要针对的是Activity配置的变化 不会引起数据的变化 同时数据源的变化可以实现自动更新

所以 AsyncTask也不能被抛弃 不过AsyncTask在使用的时候要做好相关的配置

前面看到函数响应式编程 用RxJava系列RxAndroid来处理异步操作等等 我试着写了一个简单 但是还是不太熟悉 打算这个还是很有必要看就下 大家有兴趣可以去看看 贴两个地址

https://github.com/ReactiveX/RxAndroid
https://github.com/lzyzsd/Awesome-RxJava/blob/master/README.md

简单分析下实现过程 根据源码查看 下面是使用中的代码

    getLoaderManager().initLoader(0, null, mCallbacks);

    mCallbacks = new LoaderManager.LoaderCallbacks<List<String>>() {
            @Override
            public Loader<List<String>> onCreateLoader(int id, Bundle args) {
                if (mBaker == null) {
                    mBaker = new Baker(MainActivity.this);
                }
                return mBaker;
            }

            @Override
            public void onLoadFinished(Loader<List<String>> loader, List<String> data) {
                list.addAll(data);
                myAdpater.notifyDataSetChanged();
                //数据处理完的回调
               LogUtils.e("sell " + data.size() + " breads");
            }

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

            }
        };

查看initLoader来到LoaderManagerImpl 是LoaderManager的实现类 所有的具体实现都在这里面

  public <D> Loader<D> initLoader(int id, Bundle args, LoaderManager.LoaderCallbacks<D> callback) {
        if (mCreatingLoader) {
            throw new IllegalStateException("Called while creating a loader");
        }
        //集合中获取指定的LoaderInfo
        LoaderInfo info = mLoaders.get(id);

        if (DEBUG) Log.v(TAG, "initLoader in " + this + ": args=" + args);

        if (info == null) {
            // 不存在就创建一个LoaderInfo
            info = createAndInstallLoader(id, args,  (LoaderManager.LoaderCallbacks<Object>)callback);
            if (DEBUG) Log.v(TAG, "  Created new loader " + info);
        } else {
            if (DEBUG) Log.v(TAG, "  Re-using existing loader " + info);
            info.mCallbacks = (LoaderManager.LoaderCallbacks<Object>)callback;
        }

        if (info.mHaveData && mStarted) {
            // If the loader has already generated its data, report it now.
            info.callOnLoadFinished(info.mLoader, info.mData);
        }

        return (Loader<D>)info.mLoader;
    }

具体创建的源码createAndInstallLoader 方法

     private LoaderInfo createAndInstallLoader(int id, Bundle args,
            LoaderManager.LoaderCallbacks<Object> callback) {
        try {
            mCreatingLoader = true;
            //创建LoaderInfo
            LoaderInfo info = createLoader(id, args, callback);
          //创建后的操作 处理
            installLoader(info);
            return info;
        } finally {
            mCreatingLoader = false;
        }
    }

    void installLoader(LoaderInfo info) {
        mLoaders.put(info.mId, info);
        if (mStarted) {
            // The activity will start all existing loaders in it's onStart(),
            // so only start them here if we're past that point of the activitiy's
            // life cycle
            //LoaderInfo的start()开启
            info.start();
        }
    }

现在看看info.start(); 这个方法具体干了什么

  void start() {
            if (mRetaining && mRetainingStarted) {
                // Our owner is started, but we were being retained from a
                // previous instance in the started state...  so there is really
                // nothing to do here, since the loaders are still started.
                mStarted = true;
                return;
            }
            if (mStarted) {
                // If loader already started, don't restart.
                return;
            }
            mStarted = true;
            if (DEBUG) Log.v(TAG, "  Starting: " + this);
            if (mLoader == null && mCallbacks != null) {
                //回调操作 在Activity中或者Fragment中 这里是我们上面使用的三个回调的第一个
               mLoader = mCallbacks.onCreateLoader(mId, mArgs);
            }
            if (mLoader != null) {
                if (mLoader.getClass().isMemberClass()
                        && !Modifier.isStatic(mLoader.getClass().getModifiers())) {
                    throw new IllegalArgumentException(
                            "Object returned from onCreateLoader must not be a non-static inner member class: "
                            + mLoader);
                }
                if (!mListenerRegistered) {
                    //这里是注册 将自己给注册到Loader的提供的接口上 让Loader回调这里实现相关操作 因为后续使用AsyncTaskLoader回调的时候 可以操作LoaderInfo的Callback回调
                    mLoader.registerListener(mId, this);
                    mLoader.registerOnLoadCanceledListener(this);
                    mListenerRegistered = true;
                }
                  //loader开始载入
                mLoader.startLoading();
            }
        }

可以看看mLoader.registerListener(mId, this); 这个方法里面做了什么操作

  public void registerListener(int id, OnLoadCompleteListener<D> listener) {
        if (mListener != null) {
            throw new IllegalStateException("There is already a listener registered");
        }
        mListener = listener;
        mId = id;
    }

看看 mLoader.startLoading();因为使用的是AsyncTaskLoader我们就看我们在使用AsyncTaskLoader中的实现

     @Override
        protected void onStartLoading() {
            forceLoad();
    }

     public void forceLoad() {
        onForceLoad();
    }

     @Override
    protected void onForceLoad() {
        super.onForceLoad();
        cancelLoad();
        mTask = new LoadTask();
        if (DEBUG) Log.v(TAG, "Preparing load: mTask=" + mTask);
        //开始执行异步任务
        executePendingTask();
    }

看看LoadTask 只看一些核心代码 就是一个AsyncTask的子类 里面的逻辑和AsyncTask一样子线程完后回到UI更新

    final class LoadTask extends AsyncTask<Void, Void, D> implements Runnable {
        private final CountDownLatch mDone = new CountDownLatch(1);

        // Set to true to indicate that the task has been posted to a handler for
        // execution at a later time.  Used to throttle updates.
        boolean waiting;

        /* Runs on a worker thread */
        @Override
        protected D doInBackground(Void... params) {

                *****省略****
                D data = AsyncTaskLoader.this.onLoadInBackground();
                return data;
                *****省略****
        }

        /* Runs on the UI thread */
        @Override
        protected void onPostExecute(D data) {
            if (DEBUG) Log.v(TAG, this + " onPostExecute");
            try {
                //后台任务完成后 来到这里 这里按照我们的逻辑来看应该是执行LoaderManager的onfinish()完成的回调 
                AsyncTaskLoader.this.dispatchOnLoadComplete(this, data);
            } finally {
                mDone.countDown();
            }
        }

        /* Runs on the UI thread */
        @Override
        protected void onCancelled(D data) {
            if (DEBUG) Log.v(TAG, this + " onCancelled");
            try {
                AsyncTaskLoader.this.dispatchOnCancelled(this, data);
            } finally {
                mDone.countDown();
            }
        }
    }

看看这个里面 AsyncTaskLoader.this.dispatchOnLoadComplete(this, data);

 void dispatchOnLoadComplete(LoadTask task, D data) {
        if (mTask != task) {
            if (DEBUG) Log.v(TAG, "Load complete of old task, trying to cancel");
            dispatchOnCancelled(task, data);
        } else {
            if (isAbandoned()) {
                // This cursor has been abandoned; just cancel the new data.
                onCanceled(data);
            } else {
                commitContentChanged();
                mLastLoadCompleteTime = SystemClock.uptimeMillis();
                mTask = null;
                if (DEBUG) Log.v(TAG, "Delivering result");
                //分发结果 胜利就在眼前 
                deliverResult(data);
            }
        }
    }

     public void deliverResult(D data) {
        if (mListener != null) {
            //这里就是上面LoaderManagerImpl  注册的时候把自己注册上去的回调
            mListener.onLoadComplete(this, data);
        }
    }

//最后来到回调 mListener.onLoadComplete(this, data); 的具体实现 去掉不重要的代码

      @Override
        public void onLoadComplete(Loader<Object> loader, Object data) {

            ****省略****
            if (mData != data || !mHaveData) {
                mData = data;
                mHaveData = true;
                if (mStarted) {
                    callOnLoadFinished(loader, data);
                }
            }
            ****省略****
        }

     void callOnLoadFinished(Loader<Object> loader, Object data) {
            if (mCallbacks != null) {
                String lastBecause = null;
                if (mActivity != null) {
                    lastBecause = mActivity.mFragments.mNoTransactionsBecause;
                    mActivity.mFragments.mNoTransactionsBecause = "onLoadFinished";
                }
                try {
                    if (DEBUG) Log.v(TAG, "  onLoadFinished in " + loader + ": "
                            + loader.dataToString(data));
                    //到这里成功实现onLoadFinished 方法的回调 数据加载成功
                    mCallbacks.onLoadFinished(loader, data);
                } finally {
                    if (mActivity != null) {
                        mActivity.mFragments.mNoTransactionsBecause = lastBecause;
                    }
                }
                mDeliveredData = true;
            }
        }

上面就是整个数据加载完成回调实现的过程 跑了一遍
然后我们一般在使用的时候会用上自定更新数据 也就是数据更新 我们会自动加载数据 其实也就是要用了观察者模式 我们可以通过广播或者Eventbus来实现

这里用广播 看看 内部原理

     static class Bakery extends BroadcastReceiver {

        final Baker mBaker;

        public static String CUSTOMER_ACTION = "com.daemon.demo" ;

        public Bakery(Baker baker) {
            mBaker = baker;
            IntentFilter filter = new IntentFilter(CUSTOMER_ACTION);
            baker.getContext().registerReceiver(this, filter);
        }

        @Override public void onReceive(Context context, Intent intent) {
            //主要是这个方法  来通知更新 
            mBaker.onContentChanged();
        }
    }

     public void onContentChanged() {
        if (mStarted) {
            // 发现和上面的Loader  onstartLoading那一步 
            forceLoad();
        } else {
            // This loader has been stopped, so we don't want to load
            // new data right now...  but keep track of it changing to
            // refresh later if we start again.
            mContentChanged = true;
        }
    }

现在来一个例子 例子是网上看着别人的 自己用在ListView显示 一个添加数据的按钮

     @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        this.lvshow = (ListView) findViewById(R.id.lv_show);
        this.btadd = (Button) findViewById(R.id.bt_add);

        mBaker = new Baker(this);
        mBakery = new Bakery(mBaker,this);

        list=new ArrayList<String>();
        myAdpater=new MyAdpater(this,list);
        lvshow.setAdapter(myAdpater);
        mCallbacks = new LoaderManager.LoaderCallbacks<List<String>>() {
            @Override
            public Loader<List<String>> onCreateLoader(int id, Bundle args) {
                if (mBaker == null) {
                    mBaker = new Baker(MainActivity.this);
                }
                return mBaker;
            }

            @Override
            public void onLoadFinished(Loader<List<String>> loader, List<String> data) {
                list.addAll(data);
                myAdpater.notifyDataSetChanged();
                //面包师完成面包烤制
               LogUtils.e("sell " + data.size() + " breads");
            }

            @Override
            public void onLoaderReset(Loader<List<String>> loader) {
            }
        };

        //面包师开始工作
        getLoaderManager().initLoader(0, null, mCallbacks);
        btadd.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(Bakery.CUSTOMER_ACTION);
                sendBroadcast(intent);
            }
        });
    }

Baker

 public class Baker  extends AsyncTaskLoader<List<String>> {
    public Baker(Context context) {
        super(context);
    }

    @Override
    public List<String> loadInBackground() {
        List<String> breads = new ArrayList<String>();
        //获得当前需要做的面包
        for (int i = 0; i < 5; i++) {
            //制作面包,耗时操作
            breads.add("123"+i);
        }
        //面包制作完成
        return breads;
    }
    @Override
    public void deliverResult(List<String> data) {
        super.deliverResult(data);
    }
    @Override
    protected void onStartLoading() {
        forceLoad();
    }
    @Override
    protected void onStopLoading() {
        cancelLoad();
    }
    @Override
    protected void onReset() {
        super.onReset();
    }
    }

Bakery

    public class Bakery extends BroadcastReceiver {
    final Baker mBaker;
    public static String CUSTOMER_ACTION = "com.daemon.demo" ;
    public Bakery(Baker baker , Context context) {
        mBaker = baker;
        IntentFilter filter = new IntentFilter(CUSTOMER_ACTION);
        context.registerReceiver(this, filter);
    }
    @Override
    public void onReceive(Context context, Intent intent) {
        mBaker.onContentChanged();
    }}

效果图
这里写图片描述
基本就是这样了 用起来也方便 还是那个有点 频幕旋转 Activity生命周期的变化等等一切影响Loader都帮你处理 你只关心加载数据就行 我平时也没用过这个 看着源码理一理还是挺好

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值