欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

详解android异步更新UI的几种方法

程序员文章站 2023-08-13 14:06:12
前言 我们知道在android开发中不能在非ui线程中更新ui,但是,有的时候我们需要在代码中执行一些诸如访问网络、查询数据库等耗时操作,为了不阻塞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,只不过过程不一样,有得直接给我们封装好了,有得需要我们自己控制管理。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。