Android异步更新UI的几种方法

前言

 我们知道在android开发中不能在非ui线程中更新ui,但是,有的时候我们需要在代码中执行一些诸如访问网络、查询数据库等耗时操作,为了不阻塞ui线程,我们时常会开启一个新的线程(工作线程)来执行这些耗时操作,然后我们可能需要将查询到的数据渲染到ui组件上,那么这个时候我们就需要考虑异步更新ui的问题了。

android中有下列几种异步更新ui的解决办法:

  1. Activity.runOnUiThread(Runnable)
  2. View.post(Runnable)
  3. long) View.postDelayed(Runnable, long)
  4. 使用handler(线程间通讯)(推荐)
  5. AsyncTask(推荐)

对于下面这段代码:

public void onClick(View v) { 
    new Thread(new Runnable() { 
        public void run() { 
           Bitmap bitmap = loadImageFromNetwork("http://example.com/image.png"); 
           mImageView.setImageBitmap(bitmap);     
        } 
    }).start(); 
}

这段代码是一个按钮点击事件的响应方法,当点击了这个按钮后开启了一个子线程去网络上加载图片,然后在这个线程中给imageView设置了图片(更新了ui),这段代码在非ui线程中更新了ui,运行会引发错误。

1. Activity.runOnUiThread:

通常,在Activity,我们可以使用Activity的runOnUiThread方法来更新ui。

如:

public void onClick(View v) { 
    new Thread(new Runnable() { 
        public void run() { 
           Bitmap bitmap = loadImageFromNetwork("http://example.com/image.png");
           runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    mImageView.setImageBitmap(bitmap);  
                }
           });              
        } 
    }).start(); 
}

2. View.post(Runable)

View类及其子类提供了一个post(Runable)方法允许我们将我们要做的操作放到这个匿名Runable对象的run方法中,在这个方法里面我们可以直接更新ui。

如:

public void onClick(View v) { 
    new Thread(new Runnable() { 
        public void run() { 
           Bitmap bitmap = loadImageFromNetwork("http://example.com/image.png");
           imageView.post(new Runnable() {
              @Override
              public void run() {
                  mImageView.setImageBitmap(bitmap);  
              }
           });             
        } 
    }).start(); 
}

3. long) View.postDelayed(Runnable, long)

和View.post(Runable)方法一样,只是延迟第二个参数指定的时间后执行,而View.post(Runable)是立即执行。

public void onClick(View v) { 
    new Thread(new Runnable() { 
        public void run() { 
           Bitmap bitmap = loadImageFromNetwork("http://example.com/image.png");  
           imageView.postDelayed(new Runnable() {
              @Override
              public void run() {
                  mImageView.setImageBitmap(bitmap);  
              }
           },2000);          
        } 
    }).start(); 
}

4. 使用Handler(推荐)

前面说道的几种方法当这种操作过多的时候,我们的代码会显得臃肿,代码及业务都难于管理控制,所以,当这类代码多的时候我们就应该采取Handler的方式了。

如:

new Thread(new Runnable() { 
    public void run() { 
        Bitmap bitmap = loadImageFromNetwork("http://example.com/image.png");  
        Message message = mHandler.obtainMessage();
        message.what = 1;
        message.obj = bitmap;
        mHandler.sendMessage(message);        
    } 
}).start();     
Handler mHandler = new Handler(){
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what){
            case 1:
                Bitmap bitmap = (Bitmap) msg.obj;
                imageView.setImageBitmap(bitmap);
                break;
            case 2:
                // ...
                break;
            default:
                break;
        }
    }
};

5. AsyncTask(推荐)

android为我们提供了异步任务AsyncTask,我们可以使用AsyncTask轻松地实现异步加载数据及更新ui。

如:

AsyncTask<String,Void,Bitmap> asyncTask = new AsyncTask<String, Void, Bitmap>() {

    /**
     * 即将要执行耗时任务时回调,这里可以做一些初始化操作
     */
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }

    /**
     * 在后台执行耗时操作,其返回值将作为onPostExecute方法的参数
     * @param params
     * @return
     */
    @Override
    protected Bitmap doInBackground(String... params) {
        Bitmap bitmap = loadImageFromNetwork(params[0]);
        return bitmap;
    }

    /**
     * 当这个异步任务执行完成后,也就是doInBackground()方法完成后,
     * 其方法的返回结果就是这里的参数
     * @param bitmap
     */
    @Override
    protected void onPostExecute(Bitmap bitmap) {
        imageView.setImageBitmap(bitmap);
    }
};
asyncTask.execute("http://example.com/image.png");

需要知道的是doInBackground方法工作在工作线程中,所以,我们在这个方法里面执行耗时操作。同时,由于其返回结果会传递到onPostExecute方法中,而onPostExecute方法工作在UI线程,这样我们就在这个方法里面更新ui,达到了异步更新ui的目的。

事实上,对于android的异步加载数据及更新ui,我们不仅可以选择AsyncTask异步任务,还可以选择许多开源的网络框架,如xUtils,Volley,Okhttp,…,这些优秀的网络框架让我们异步更新ui变得非常简单,而且,效率和性能也非常高。

总结:

 对于上面的许多解决办法,其实它们做的都是同一件事情,即在工作线程中执行耗时任务,然后在ui线程中更新ui,只不过过程不一样,有得直接给我们封装好了,有得需要我们自己控制管理。

  • 4
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Android 异步编程是在 Android 应用中处理耗时操作的一种技术。在 Android 中,主线程(也称为 UI 线程)用于处理界面的绘制和用户交互,如果在主线程中执行耗时操作,会导致界面卡顿,影响用户体验。 为了避免在主线程中执行耗时操作,Android 提供了多种异步编程的机制,常用的有以下几种: 1. AsyncTask:AsyncTask 是一个轻量级的异步任务类,可以在后台执行耗时操作,并在主线程更新 UI。它通过重写 `doInBackground()` 方法执行后台操作,重写 `onPostExecute()` 方法更新 UI。但是 AsyncTask 已经被废弃,不再推荐使用。 2. Handler 和 Looper:Handler 和 Looper 用于在不同线程之间进行通信。通过创建 Handler 对象,可以将任务发送到主线程的消息队列中,在主线程中处理这些任务。这种方式需要手动管理消息队列和消息处理。 3. AsyncTaskLoader:AsyncTaskLoader 是 AsyncTask 的改进版,适用于加载数据并在界面上显示的情况。它提供了更好的生命周期管理和数据缓存机制。 4. RxJava:RxJava 是一个基于观察者模式的异步编程库,可以简化异步任务的处理。它使用可观察者和订阅者模式来实现异步操作,提供了丰富的操作符来处理异步任务。 5. Kotlin 协程:Kotlin 协程是一种轻量级的异步编程方式,可以在代码中使用类似同步代码的方式处理异步任务。它提供了简洁的语法和强大的并发处理能力。 以上是 Android 中常用的异步编程方式,开发者可以根据实际需求选择合适的方式来处理异步操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值