Handler用法简介

Handler是androd中必须学会的内容,其实使用是非常简单的,不过有必要再啰嗦一下,算是复习:
Android的UI操作并不是线程安全,因此启动线程访问用户界面的UI组件是不被允许的,handler解决了这个问题,使用了如下手段:
1.在新启动的线程中发送消息(发送到指定的messagequeue)
2.在主线程中接收消息并处理
handler负责发送消息,looper死循环负责接收消息,并把消息回传给handler自己
如果希望handler正常工作,当前线程必须要有一个messagequeue,而messagequeue是由looper管理的,也就是当前线程必须有一个looper,要想保证有looper分为两种情况:
1.在主线程(UI线程)中
2.在非主线程中

创建Handler也就可以分为两种方法:

new Handler(); //没有指定Looper,那么默认Looper为当前线程
new Handler(Looper looper); //指定looper为参数looper

那么这两种方式使用的场景在哪里呢,根据使用经验,我认为如下:
①在主线程中创建Handler,直接new一个不带参数的Handler好像没什么问题,实现handleMessage即可。
②在子线程中创建Handler,似乎要带参数,并且指定looper。
先看看什么是Looper:

Class used to run a message loop for a thread. Threads by default do not have a message loop associated with them; to create one, call prepare() in the thread that is to run the loop, and then loop() to have it process messages until the loop is stopped.

原来Threads默认没有message loop,然而主线程是个例外,在Activity中的UI主线程中,无需使用显式的方式进行Looper的初始化以及开始循环,是因为Activity内部包含一个Looper对象,它会自动管理Looper,处理子线程中发送过来的消息。而初始化Handler的时候,在Handler的构造函数中,会把当前线程的Looper与Handler关联,所以在Activity中,无需显式使用Looper,这也就解释了我说的使用场景:主线程不带参数。

同时注意到,子线程要创建一个looper还是比较麻烦的,必须调用prepare和loop方法,谷歌文档中给出的例子是这样的:

 class LooperThread extends Thread {
      public Handler mHandler;

      public void run() {
          Looper.prepare();

          mHandler = new Handler() {
              public void handleMessage(Message msg) {
                  // process incoming messages here
              }
          };

          Looper.loop();
      }
  }

也不算很复杂,不过google官方已经为此提供了解决方案,也就是HandlerThread了,HandlerThread本质是就是一个普通的Thread,只不过内部建立了Looper,使用HandlerThread不用再去手动建立,它的使用是类似这样的:

mHandler = new Handler(mHandlerThread.getLooper()){
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    //处理消息
                 }   
         });

创建消息的时候,似乎也有两种写法:
①Message msg=new Message();
②Message msg=mHandler.obtainMessage();
这两种写法的区别是一个是自己创建的message,一个是拿系统的message直接使用。
发送消息事实上也有两种写法:
①mHandler.sendMessage();
②message.sendToTarget();也能发送消息给handler

解决新线程不能更新UI组件的问题,使用handler实现线程通信显然是一种方法,不过不是唯一的方法,也就是异步任务AsyncTask,相对来说AsyncTask更为轻量级一些,适用于简单的异步处理.例子如下:

class DownTask extends AsyncTask<URL,Integer,String>{

    protected String doInBackground(URL ... params){
        //此函数处理耗时操作
    }

    protected String onPreExcute(URL ... params){
        //在处理耗时操作前调用,可以先显示一个进度条
    }

    protected String onPreExcute(URL ... params){
        //在处理耗时操作后被调用,下载完成了,将他显示出来的操作放在这里
    }

   protected String onProgressUpdate(Integer... values){
        //在doInBackground中调用publishProgress会调到onProgressUpdate,
        //如随着下载进度的改变更新进度值
    }
}

感觉没啥思路,以上是我想到的一些。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值