Android 异步加载数据方式整理

在 Android 中,由于主线程负责维护 UI,不能被阻塞,那么在通过磁盘或者网络进行异步加载数据的时候就需要使用多线程了。以下是我整理的几种使用多线程执行异步操作的方式,如有纰漏欢迎指正。

  1. Handler

    Android 中多线程通信基本的方式是使用 Handler 机制,基本使用方式如下。

    //init handler on the original thread
    class OriginalThread extends Thread {
     public Handler mHandler;
     public void run() {
       Looper.prepare();
       mHandler = new Handler() {
         public void handleMessage(Message msg) {
             // process incoming messages here
         }
       };
       Looper.loop();
     }
    }
    //send message to the original thread
    mHandler.post(Runnable);
    mHandler.postAtTime(Runnable, long);
    mHandler.postDelayed(Runnable, long);
    mHandler.sendEmptyMessage(int);
    mHandler.sendMessage(Message);
    mHandler.sendMessageAtTime(Message, long);
    mHandler.sendMessageDelayed(Message, long);
    

    系统还内置了AsyncQueryHandler 辅助子类,方便使用 ContentResolver 进行异步查询操作。

    关于 Handler,需要注意的是,当 Handler 被声明为 Activity 的非静态内部类时, Handler 会持有外部 Activity 实例的引用,Handler 生命周期比 Activity 长时会导致 Activity 实例不能被正常释放,从而引起内存泄漏。一种解决方式是将 Handler 声明为 Activity 的静态内部类或者单独的类,在 Handler 内部使用 WeakReference/SoftReference 保存对 Activity的引用,既能访问 Activity 的 View 更新 UI,又可以避免内存泄漏。

  2. AsyncTask

    AsyncTask 方式是官方提供的用来简化手动写 Handler 的一种异步机制,其内部仍使用 Handler 实现。

    需要继承AsyncTask<Params, Progress, Result>类,重写doInBackground,onPostExecute等回调方法,使用的时候调用 execute 方法(只能在 UI 线程调用)传入参数就可以方便的执行 IO 或网络等耗时操作并在操作完成时更新 UI。

    使用 AsyncTask 同样需要注意内存泄漏问题。

  3. Activity.runOnUiThread(Runnable action)

    算是 Handler 方式的一种语法糖吧,使用了 Activity 自身维护的 一个 mHandler 实例,便于在 UI 线程执行操作,比如异步获取数据后更新 UI。

  4. Loader

    Loader 是在 Android 3.0 引入的用于在 Activity 和 Fragment 中简化异步加载数据的方式。

    系统提供了 AsyncTaskLoader<D> 和 CursorLoader 两个子类。

  5. View.post(Runnable action)/View.postDelayed(Runnable action, long delayMillis)

  6. RxJava

    使用 RxJava 可以方便地进行多线程调度,通过调用 Observable.subscribeOn 和 Observable.observeOn,并使用 Schedulers.io() 和 Schedulers.mainThread() 等工厂方法传入参数即可自由切换线程。

  7. EventBus

    使用 EventBus 可以在任意线程发布数据,并通过订阅方法的命名约定规定在何种线程执行订阅的回调方法。

    // Called in the same thread (default)
    public void onEvent(MessageEvent event) {
     log(event.message);
    }
    // Called in Android UI's main thread
    public void onEventMainThread(MessageEvent event) {
     textField.setText(event.message);
    }
    // Called in the background thread
    public void onEventBackgroundThread(MessageEvent event){
     saveToDisk(event.message);
    }
    // Called in a separate thread
    public void onEventAsync(MessageEvent event){
     backend.send(event.message);
    }
    
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 文章独家授权公众号:码个蛋更多分享:http://www.cherylgood.cn 谈到Android开发,就离...
    Angels_安杰阅读 1,650评论 0 3
  • 异步消息处理线程启动后会进入一个无限的循环体之中,每循环一次,从其内部的消息队列中取出一个消息,然后回调相应的消息...
    cxm11阅读 6,455评论 2 39
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 173,532评论 25 708
  • 你真美丽……不,你不是「美丽」,「美丽」太冰冷了;你真「美好」—— 你是美好的,因为你不但美丽,而且温暖。
    郭绿狮阅读 252评论 0 2
  • 流浪的云 相思的雨 你可懂我的思念 没关系 我会接住你 在最美的季节里
    来自俄罗斯的大油条阅读 130评论 0 0