Android HandlerThread和IntentService用法和源码解析

来源:互联网 发布:儿童编程先学什么 编辑:程序博客网 时间:2024/06/11 17:46

HandlerThread

用法

public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        Log.d("LiaBin", "MainActivity onCreate tid:" + Thread.currentThread().getId());        HandlerThread handlerThread = new HandlerThread("handler-thread");        handlerThread.start();        Handler handler = new Handler(handlerThread.getLooper()) {            @Override            public void handleMessage(Message msg) {    Log.d("LiaBin", "MainActivity handler tid:" + Thread.currentThread().getId());                try {                    Thread.sleep(20000);//dosomething....//handlerThread.quit();                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        };       handler.sendEmptyMessage(0);    }}

HandlerThread显而易见的好处就是不用额外自定义Thread了,同时可以通过getLooper方法获取HandlerThread线程对应的looper,
所以handler的发送消息就发送到子线程looper对应的消息队列中去了,所以此时可以用该handler来让main线程给子线程发送消息了
此时如果打开DDMS查看这个进程,那么就会发现"handler-thread"这个线程一直存在,如果耗时操作执行完后,不做任何处理,
还是挺占用系统资源的,所以耗时操作执行完后可以执行handlerThread.quit();那么HandlerThread这个线程就会进入死亡态,不再占用系统资源

因为HandlerThread的run方法里面,最后调用的是Looper.loop(); 这是一个死循环,一直不断的取MessageQueue中的消息,所以该HandlerThread线程一直都在

源码解析

public class HandlerThread extends Thread {    ……    @Override    public void run() {        mTid = Process.myTid();        Looper.prepare(); //为该线程绑定looper        synchronized (this) {            mLooper = Looper.myLooper();            notifyAll();        }        Process.setThreadPriority(mPriority);        onLooperPrepared();        Looper.loop(); //一直开始循环取looper对应队列中的消息,所以如果不手动quit,该线程就一直存在        mTid = -1;    }        //可以获取该线程对应的looper,构造handler的时候使用这个参数,handler中处理消息就会放在该子线程中,而不是main线程    public Looper getLooper() {        if (!isAlive()) {            return null;        }                // If the thread has been started, wait until the looper has been created.        synchronized (this) {            while (isAlive() && mLooper == null) {                try {                    wait();                } catch (InterruptedException e) {                }            }        }        return mLooper;    }    //手动终止looper循环,耗时操作执行完,调用该方法可以使Looper停止不停的loop消息,从而run方法可以执行完,从而该线程终止,否则run方法一直在运行,该线程也一直在运行态    public boolean quit() {        Looper looper = getLooper();        if (looper != null) {            looper.quit();            return true;        }        return false;    }……}

说明:
1. 线程只有run()方法执行完,才会终止,同时进入死亡态,looper没有终止那么run就一直在运行


IntentService

用法

public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        Log.d("LiaBin", "MainActivity onCreate tid:" + Thread.currentThread().getId() + " tname:" + Thread.currentThread().getName());        startService(new Intent(this, MyIntentService.class));     }}public class MyIntentService extends IntentService {    public MyIntentService() {        super("MyIntentService");    }    @Override    public void onCreate() {        super.onCreate();        Log.d("LiaBin", "MyIntentService onCreate tid:" + Thread.currentThread().getId() + " tname:" + Thread.currentThread().getName());    }    @Override    protected void onHandleIntent(Intent intent) {        Log.d("LiaBin", "MyIntentService onHandleIntent tid:" + Thread.currentThread().getId() + " tname:" + Thread.currentThread().getName());        try {            Thread.sleep(5000);            //dosomething....        } catch (InterruptedException e) {            e.printStackTrace();        }    }    @Override    public void onDestroy() {        super.onDestroy();        Log.d("LiaBin", "MyService onDestroy");    }}
此时耗时的操作可以放在onHandleIntent中,因为onHandleIntent是在HandlerThread子线程中被调用,不会阻塞main线程。IntentService的优点显而易见
不用在service中手动开启线程,同时耗时操作执行完后,IntentService服务自动终止,并不会一直停留在后台。同时内部开启的HandlerThread子线程也终止
IntentService的onDestroy方法中有

    @Override    public void onDestroy() {        mServiceLooper.quit();    }
mServiceLooper.quit();//导致线程终止    

可以看到此时打印:
10-26 13:47:05.170 20397-20397/? D/LiaBin: MainActivity onCreate tid:1 tname:main
10-26 13:47:05.193 20397-20397/? D/LiaBin: MyIntentService onCreate tid:1 tname:main
10-26 13:47:05.194 20397-20429/? D/LiaBin: MyIntentService onHandleIntent tid:8233 tname:IntentService[MyIntentService]

源码解析

注意
1. IntentService继承自service,所以具有service的特性,每个服务都只会存在一个实例,只有第一次startService的时候才会调用onCreate,否则onStart
2. onHandleIntent在子线程中执行,所以不会阻塞main线程,耗时操作可以放在这里。同时onHandleIntent执行完后该service销毁调用onDestroy方法,onDestroy方法通知会导致子线程不再looper,子线程终止。从DDMS中也可以看到MyIntentService线程执行完耗时操作就终止
3. service还是运行在main线程中的,可以从onCreate,onStart方法中打印的还是main线程可以看出

private volatile Looper mServiceLooper;    private volatile ServiceHandler mServiceHandler;    private String mName;    private boolean mRedelivery;    private final class ServiceHandler extends Handler {        public ServiceHandler(Looper looper) {            super(looper);        }        @Override        public void handleMessage(Message msg) {            onHandleIntent((Intent)msg.obj);            stopSelf(msg.arg1);        }    }}

onHandleIntent在handleMessage中执行,所以执行在HandlerThread子线程中
stopSelf(msg.arg1); onHandleIntent执行完后,就会停止该service,进而调用该Service的onDestroy方法,进而mServiceLooper.quit();那么就会终止HandlerThread子线程

@Override    public void onDestroy() {        mServiceLooper.quit();    }
内部onCreate中创建了一个子线程,使用HandlerThread实现mServiceHandler使用该子线程的looper,所以handler是在该子线程中处理消息的。注意该service还是运行在main线程中的
@Override    public void onCreate() {        // TODO: It would be nice to have an option to hold a partial wakelock        // during processing, and to have a static startService(Context, Intent)        // method that would launch the service & hand off a wakelock.        super.onCreate();        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");        thread.start();        mServiceLooper = thread.getLooper();        mServiceHandler = new ServiceHandler(mServiceLooper);    }

onStart方法中使用handler发送消息到HandlerThread子线程

@Override    public void onStart(Intent intent, int startId) {        Message msg = mServiceHandler.obtainMessage();        msg.arg1 = startId;        msg.obj = intent;        mServiceHandler.sendMessage(msg);    }    /**     * You should not override this method for your IntentService. Instead,     * override {@link #onHandleIntent}, which the system calls when the IntentService     * receives a start request.     * @see android.app.Service#onStartCommand     */    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        onStart(intent, startId);        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;    }


0 0