当前位置:操作系统 > 安卓/Android >>

android 再论 Handler

一、ThreadLocal的分析:

从字面上这个Threadlocal很容易让人引起误解,认真是一个本地 thread,实际上这是一个Thread的本地信息变量,也就是说用来存储线程中不安全变量的一个机制。分析如下:

ThreadLocal类接口很简单,只有4个方法,我们先来了解一下:

void set(Object value)

设置当前线程的线程局部变量的值。

· public Object get()

该方法返回当前线程所对应的线程局部变量。

· public void remove()

将当前线程局部变量的值删除,目的是为了减少内存的占用,该方法是JDK 5.0新增的方法。需要指出的是,当线程结束后,对应该线程的局部变量将自动被垃圾回收,所以显式调用该方法清除线程的局部变量并不是必须的操作,但它可以加快内存回收的速度。

protected Object initialValue()

返回该线程局部变量的初始值,该方法是一个protected的方法,显然是为了让子类覆盖而设计的。这个方法是一个延迟调用方法,在线程第1次调用get()或set(Object)时才执行,并且仅执行1次。ThreadLocal中的缺省实现直接返回一个null。

对于每个线程,同名的变量,我们可以新建一个实例,并以Thread.currentThread为key保存到ThreadLocal中。当我们用到的时候,通过get()获取。

对于Handler,通常存的是  mLooper

 

二、Handler究竟是运行在子线程还是主线程

来看看Handler的构造函数,这里面有一个变量进行如下操作:

mLooper = Looper.myLooper();

上面的调用实际是如下操作:

public static Looper myLooper() {

        return sThreadLocal.get();

}

也就是获取当前线程的Looper,这样看来,Handler运行环境不是确定的,而是在哪个线程创建这个handler,在主线程创建就运行在主线程,否则就是子线程。

三、如何正确启动一个子线程:

//在主线程先创建一个HandlerThread

HandlerThread mHandlerThread = new HandlerThread("XXX");

//第二步,是创建一个自己的Looper

mHandlerThread.start();

创建一个继承自Handler的子类,将上面创建的Looper赋给这个子类,在创建的时候,这样,我们就是创建一个不是运行在主线程的子线程了。否则,默认的是使用启动Handler的线程的Looper。

    class myThread extends Handler {

    public myThread (Looper looper) {

    super(looper);

    }

   

    public myThread() {

    super();

    }

@Override

public void handleMessage(Message msg) {

// TODO Auto-generated method stub

super.handleMessage(msg);

switch (msg.what) {

case 1:

try {

Thread.sleep(20* 1000);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

break;

}

}

  }

//初始化

mHandlerThread = new HandlerThread("handler");

mHandlerThread.start();

//创建子线程

mHandler = new myThread(mHandlerThread.getLooper());

四、IntentService

IntentService继承自Service,它能够在后台运行不阻塞主线程主要归于它内部开启一个工作线程,也就是创建一个继承自Handler的ServiceHandler,只是这个handler的looper是新创建的,不同于主线程的Looper,因而不会阻塞主线程。

public abstract class IntentService extends Service {

}

当我们通过Intent启动一个IntentService的时候,先进入onCreate:

public void onCreate() {

        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");

        thread.start();

        mServiceLooper = thread.getLooper();

        mServiceHandler = new ServiceHandler(mServiceLooper);

}

是不是通过HandlerThread先创建一个Looper,然后将这个Looper赋给工作线程ServiceHandler

启动好IntentService之后,我们开始

    public int onStartCommand(Intent intent, int flags, int startId) {

        onStart(intent, startId);

        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;

    }

    public void onStart(Intent intent, int startId) {

        Message msg = mServiceHandler.obtainMessage();

        msg.arg1 = startId;

        msg.obj = intent;

        mServiceHandler.sendMessage(msg);

}

ServiceHandler的函数中有处理消息的机制,这里就调用onHandleIntent进行处理

    public void handleMessage(Message msg) {

        onHandleIntent((Intent)msg.obj);

        stopSelf(msg.arg1);

   }

五、如何销毁线程

1、销毁Handler:

由上面我们知道:我们开启一个子线程重要的依据在于要创建一个HandlerThread,在这里会新建一个Looper,然后通过它进行处理Message。那么在退出时如下处理:

onDestroy() {

super.onDestroy();

//将HandlerThread的looper.quit,下面应该是实例调用quit(此处不考虑语法问题)

HandlerThread.quit();

}

对于以Handler.post(Runnable)形式发送Message的方式,在上面函数中应该是:

Handler.removeCallbacks(mRunnable);

2、销毁Thread

目前是通过:设置一个全局变量,在退出时将这个变量设置为true,thread中判断到这个值为true时退出thread的循环。


作者:kakaBack
补充:移动开发 , Android ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,