IntentService从源码解析

来源:互联网 发布:我的父亲母亲知乎 编辑:程序博客网 时间:2024/05/17 21:40

子线程的生命周期就是run方法结束了就结束了,这个我要说的一点就是HandlThread类,这里是由于quene.next()一直监听着消息队列,处于堵塞状态,所以这个线程是创建了就一直存在的。案例说安卓的主线程run方法执行完了也就该退出,由于安卓的主线程是一个特殊的线程所以一直存在。
这里写图片描述
这里写图片描述
下面我们看下曾经写过的一个主线程给子线程的发送的案例
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();
handler = new Handler(){
@Override
public void handleMessage(Message msg) {
Toast.makeText(MainActivity.this,msg.toString(), Toast.LENGTH_LONG).show();
}
};
Looper.loop();

        }    });    thread.start();}public void click(View view){    handler.obtainMessage(2, "主线程给子线程发送消息").sendToTarget();}

这里的子线程就是通过looper. loop()一直一直监听消息队列处于堵塞状态,所以这个线程也是一直存在的,所以导致内存泄漏的问题,一般来说,我们不不能够这样子用的,除非我们需要某个线程一直存在从消息队列里拿东西,那样我们会使用这种做法,有个HandlerThread类大概就是使用了这一原理。

下面我们来通过源码追究一下HandlerThread是个什么东西?
HanlderThread其实就是一个Thread,继承了Thread的一个类,一般线程都是run方法执行结束的话就应该结束了,但是HandlerThread内部通过创建Looper.Prepared()创建消息队列,通过Looper.Loop()开启消息循环,由于消息循环是一个堵塞的死循环,所以这个消息队列一直存在着,可以执行耗时的任务,由于这是个无限循环的,所以我们明确的想要关闭的话,可以使用quit,或者quitSafely();
下面我们追源码看看这个quit都做了什么?
public boolean quit() {
Looper looper = getLooper();
if (looper != null) {
looper.quit();
return true;
}
return false;
}
追进去发现
quit方法
public void quit() {
mQueue.quit(false);
}
quitSafely方法
public void quitSafely() {
mQueue.quit(true);
}
以上两个方法都是调用了 MessageQueue 的quit方法,下面我们看下MessageQueen中的两个方法差别在哪?
void quit(boolean safe) {
if (!mQuitAllowed) {
throw new RuntimeException(“Main thread not allowed to quit.”);
}
synchronized (this) {
if (mQuiting) {
return;
}
mQuiting = true;
if (safe) {
removeAllFutureMessagesLocked();//清空延迟消息,将消息池中的非延迟消息派发出去由handler处理
} else {
removeAllMessagesLocked();//清空里面所有的消息,不论延迟还是非延迟的
}
}
nativeWake(mPtr);
}
quitSafely相比quit方法的安全之处在于在清空消息之前会派发所有的非延迟消息。
无论是调用了quit方法还是quitSafely方法只会,Looper就不再接收新的消息。即在调用了Looper的quit或quitSafely方法之后,消息循环就终结了,这时候再通过Handler调用sendMessage或post等方法发送消息时均返回false,表示消息没有成功放入消息队列MessageQueue中,因为消息队列已经退出了。

这么就是说在调用quit方法之后消息队列关闭了,所以这样就不存在消息堵塞机制了,那么线程的run方法就可以结束啦。

当我们开启一个Intentservice的时候会传入一个intent值。
}
public void click3(View v){

    Intent service=new Intent(this, Myintentservice.class);    service.putExtra("a", "第三次开启intentService");    startService(service);}

其实intentService的核心就是在于在他的Oncreate()方法中我们创建了一个HandlerHtread,然后把这个Thread传进一个ServiceHandler 构造方法里面,这样这个ServiceHandler 发送的消息都是在这个Handler中执行的。onstart()方法恰恰就是把开启service传进来的intent值发送到ServiceHandler中

IntentService内部类
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);
}
}
IntentService是把onHandleIntent抽象出去让子类去实现的
protected abstract void onHandleIntent(Intent intent);

看到这个stopSelf方法了吗,这个就是当onHandleIntent方法执行完了以后IntentService会通过stopSelf(int id)终止服务,为什么用stopSelf()是因为这个是立刻终止服务,而带参数的这个是待消息执行完才终止服务。

我们看看oncreate,onstart
@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);
}
@Override
public void onStart(Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}

由于Handler中Loop中的MessageQueen中的任务都是按照顺序执行的,所以intentService中的任务也是按照顺序执行的。

0 0
原创粉丝点击