Android IntentService 的深入浅出

一、问题引入

Android代码设计中耗时的IO操作会放置在Service中进行执行,但是由于Service也是运行在主线程中,因此在设计中会在Service开一个线程来完成耗时IO操作的业务部分。线程一般会放置在Service的onStartCommand函数中执行。

public class MyService extends Service {

@Override
public IBinder onBind(Intent intent) {
    return null;
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
new Thread(new Runnable() {
        @Override
        public void run() {
            // 处理具体的逻辑
        }
        }).start();
        return super.onStartCommand(intent, flags, startId);
    }
}

Service在被startService启动调用之后,需要使用stopService来停在service,否则service可能会一直运行下去。因此需要我们在线程结束的代码中添加stopself,让service自动停止下来销毁掉。

new Thread(new Runnable() {
    @Override
    public void run() {
        // 处理具体的逻辑
        stopSelf(); //补充停止服务的逻辑
    }
}).start();

由于需要自定义线程,并且需要在线程结束之后还记得写上stopSelf代码,因此《Android开发手册.pdf》并不推荐采用上述方式在service中完成耗时操作,而是建议采用IntentService来完成上述要求的业务逻辑。

二、IntentService的使用介绍

关于IntentService的介绍网上有很多,可以归纳总结为如下几点:
1.IntentService继承自Service,启动IntentService的方式和启动传统Service一样。
2.IntentService内有一个工作线程来处理耗时的操作,当任务执行完成后,IntentService会自动停止。
3.可以启动IntentService多次,每一个耗时的操作会以工作队列的方式在IntentService的onHandleIntent回调方法中执行,每次只会执行一个工作线程,执行完第一个再执行第二个,依次类推。

使用代码范例
在AndroidManifest.xml代码中添加IntentService的继承代码MyIntentService。

<service android:name=".MyIntentService"></service>

MyIntentService的代码实现

import android.app.IntentService;
import android.content.Intent;
import android.util.Log;

/**
 * Created by moxie on 2018/6/26.
 */

public class MyIntentService extends IntentService {
    public static final String TAG = MyIntentService.class.getSimpleName();

    public static final String EXTRA_KEY = "task_name";

    public MyIntentService() {
        super(TAG);
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        String value = intent.getStringExtra(EXTRA_KEY);
        if (value.contains("two")) {
            try {
                // 如果是第二个任务,则sleep三秒。
                // 发现第三个任务仍然在第二个任务之后执行,说明任务是串行执行的
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        Log.e(TAG, "thread : " + Thread.currentThread().getName() + "  " + value);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        // 服务结束时,打印Log
        Log.e(TAG, "onDestroy");
    }
}

在Activity中调用IntentService

Intent intent = new Intent(this, MyIntentService.class);
intent.putExtra(MyIntentService.EXTRA_KEY, "my task one #");
 // 发送任务1
startService(intent);
intent.putExtra(MyIntentService.EXTRA_KEY, "my task two #");
// 发送任务2
startService(intent);
intent.putExtra(MyIntentService.EXTRA_KEY, "my task three #");
// 发送任务3
startService(intent);

结果输出
这里写图片描述
从结果中可以看出通过IntentService执行的任务是依次执行的。

三、IntentService的源码解析

IntentService的源码如下

public abstract class IntentService extends Service {
    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);
        }
    }

    public IntentService(String name) {
        super();
        mName = name;
    }

    public void setIntentRedelivery(boolean enabled) {
        mRedelivery = enabled;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();

        mServiceLooper = thread.getLooper();
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }

    @Override
    public void onStart(@Nullable Intent intent, int startId) {
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
        mServiceHandler.sendMessage(msg);
    }

    @Override
    public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
        onStart(intent, startId);
        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
    }

    @Override
    public void onDestroy() {
        mServiceLooper.quit();
    }

    @Override
    @Nullable
    public IBinder onBind(Intent intent) {
        return null;
    }

    @WorkerThread
    protected abstract void onHandleIntent(@Nullable Intent intent);
}

从上面IntentService的源码中可以看到如下几点:
1.IntentService通过HandlerThread创建了一个非UI线程的Looper。
2.通过非UI线程的Looper创建了一个Handler的继承类ServiceHandler的对象。
3.在onStart函数中,将通过调用startService服务过来的intent都发送到ServiceHandler中去执行,子类会实现onHandleIntent函数,子类在该函数中完成复杂的耗时任务。
4.添加停止服务的stopself函数,保证任务结束后自行停止服务。
由于Handler内部是有一个MessageQueue队列的,因此我们能够在上述的范例中看到,IntentService会顺序执行用户调用的服务。
IntentService的逻辑流程如下:
这里写图片描述

参考链接
https://blog.csdn.net/lyj1005353553/article/details/53647121
https://www.cnblogs.com/zgqys1980/p/5478668.html
https://www.jianshu.com/p/8a3c44a9173a
https://blog.csdn.net/VNanyesheshou/article/details/75125909
https://blog.csdn.net/a740169405/article/details/50274537
https://blog.csdn.net/javazejian/article/details/52709857

猜你喜欢

转载自blog.csdn.net/polo2044/article/details/80816499