1. 生命周期 常用方法
- 官方说明图
在Service的生命周期里,常用的有:
4个手动调用的方法
手动调用方法 作用
startService() 启动服务
stopService() 关闭服务
bindService() 绑定服务
unbindService() 解绑服务
内部自动调用的方法 作用
onCreat() 创建服务
onStartCommand() 开始服务
onDestroy() 销毁服务
onBind() 绑定服务
onUnbind() 解绑服务
使用
- startService
public class MyService extends Service {
/**
* 创建参数
*/
int count;
@Override
public void onCreate() {
super.onCreate();
Log.w("TAG", "---onCreate");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
/** 创建一个线程,每秒计数器加一,并在控制台进行Log输出 */
//耗时操作 不用再单独的开启线程
new Thread(new Runnable() {
public void run() {
while (true) {
try {
Thread.sleep(1000);
count++;
Log.w("TAG", "Count is" + count);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.w("TAG", "---onDestroy");
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
Intent intent = new Intent(MainActivity.this, MyService.class);
startService(intent);
在需要停止的時候調用stopService
- bindService (一定要记着这个是要获得,链接的对象) 可用于和Activity之間的通訊,BindService可以在Activity里面获得Service的实例,绑定获取实例是异步的过程
bindService启动流程
context.bindService() ——> onCreate() ——> onBind() ——> Service running ——> onUnbind() ——> onDestroy() ——> Service stop
onBind()将返回给 客户端一个IBind接口实例,IBind允许客户端回调服务的方法,比如得到Service的实例、运行状态或其他操作。这个时候把调用者 (Context,例如Activity)会和Service绑定在一起,Context退出了,Srevice就会调用 onUnbind->onDestroy相应退出。
所以调用bindService的生命周期为:onCreate --> onBind(只一次,不可多次绑定) --> onUnbind --> onDestory。
在Service每一次的开启关闭过程中,只有onStart可被多次调用(通过多次startService调用),其他onCreate,onBind,onUnbind,onDestory在一个生命周期中只能被调用一次。
/** 通过bindService和unBindSerivce的方式启动和结束服务 */
public class MyBindService extends Service {
/**
* 进度条的最大值
*/
public static final int MAX_PROGRESS = 100;
/**
* 进度条的进度值
*/
private int progress = 0;
/**
* 更新进度的回调接口
*/
private OnProgressListener onProgressListener;
public interface OnProgressListener {
void onProgress(int progress);
}
/**
* 注册回调接口的方法,供外部调用
*
* @param onProgressListener
*/
public void setOnProgressListener(OnProgressListener onProgressListener) {
this.onProgressListener = onProgressListener;
}
/**
* 增加get()方法,供Activity调用
*
* @return 下载进度
*/
public int getProgress() {
return progress;
}
/**
* 模拟下载任务,每秒钟更新一次
*/
public void startDownLoad() {
new Thread(new Runnable() {
@Override
public void run() {
while (progress < MAX_PROGRESS) {
progress += 5;
//进度发生变化通知调用方,需要和切换到主线程
if (onProgressListener != null) {
Log.w("TAG", "---thread"+Thread.currentThread().getName());
onProgressListener.onProgress(progress);
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
/**
* 返回一个Binder对象
*/
@Override
public IBinder onBind(Intent intent) {
Log.w("TAG", "---onBind");
return new MsgBinder();
}
//此方法是为了可以在Acitity中获得服务的实例
public class MsgBinder extends Binder {
/**
* 获取当前Service的实例
*
* @return
*/
public MyBindService getService() {
return MyBindService.this;
}
}
@Override
public void onCreate() {
super.onCreate();
Log.w("TAG", "---onCreate");
}
@Override
public void onDestroy() {
super.onDestroy();
/** 服务停止时 */
Log.w("TAG", "---onDestroy");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.w("TAG", "---onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
}
在Activity使用
/** 进入Activity开始服务 */
Intent intent = new Intent(MainActivity.this, MyBindService.class);
bindService(intent, conn, Context.BIND_AUTO_CREATE);
ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.w("TAG", "onServiceConnected---------");
//返回一个MsgService对象
msgService = ((MyBindService.MsgBinder) service).getService();
// 绑定成功后获取到服務开始下载
msgService.startDownLoad();
//注册回调接口来接收下载进度的变化
msgService.setOnProgressListener(new MyBindService.OnProgressListener() {
@Override
public void onProgress(int progress) {
Log.w("TAG", "progress---------" + progress);
Log.w("TAG", "---thread----" + Thread.currentThread().getName());
}
});
}
};
protected void onDestroy() {
super.onDestroy();
this.unbindService(conn);
Log.v("MainStadyServics", "out");
}
IntentService
public class MyIntentService extends IntentService {
private static final String TAG = "TAG";
public MyIntentService() {
super("MyIntentService");
Log.d(TAG, "MyIntentService: " + Thread.currentThread().getName());
}
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand: ");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onStart(@Nullable Intent intent, int startId) {
Log.d(TAG, "onStart: ");
super.onStart(intent, startId);
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
//耗时操作 不用再单独的开启线程
Log.d(TAG, "MyIntentService: " + Thread.currentThread().getName());
String path = intent.getStringExtra("path");
downloadTask(path);
}
private void downloadTask(String path) {
Log.d(TAG, "downloadTask: ");
try {
Thread.sleep(3 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* 当某个请求需要处理时,这个方法会在工作者线程被调用
* 一次仅仅会有一个请求被处理,但是处理过程会运行在工作者线程(独立于其他应用程序逻辑运行)。
* 因此,如果某段代码需要执行很长时间,它会阻塞住其他提交到该IntentService的请求
* ,但是不会阻塞住其他任何东西。当所有的请求被处理完成之后,IntentService会停止它自身,
* 因此你不应该手动调用stopSelf()方法。
*/
@Override
public void onDestroy() {
Log.d(TAG, "onDestroy: ");
super.onDestroy();
}
}
使用
Intent intent = new Intent(MainActivity.this, MyIntentService.class);
intent.putExtra("path", "http://www:xxx.xxx");
startService(intent);
startService(intent);
startService(intent);
//执行结果
D/TAG: MyIntentService: main
D/TAG: onStartCommand:
D/TAG: onStart:
D/TAG: MyIntentService: IntentService[MyIntentService
D/TAG: downloadTask:
D/TAG: onStartCommand:
D/TAG: onStart:
D/TAG: onStartCommand:
D/TAG: onStart:
D/TAG: MyIntentService: IntentService[MyIntentService
D/TAG: downloadTask:
D/TAG: MyIntentService: IntentService[MyIntentService
D/TAG: downloadTask:
D/TAG: onDestroy:
若启动IntentService 多次,那么 每个耗时操作 则 以队列的方式 在 IntentService的 onHandleIntent回调方法中依次执行,所有任务执行完自动结束回调onDestroy
IntentService的onHandleIntent方法是一个抽象方法,所以我们在创建IntentService时必须实现该方法,
通过上面一系列的分析可知,onHandleIntent方法也是一个异步方法。这里要注意的是如果后台任务只有一个的 话,onHandleIntent执行完,服务就会销毁,但如果后台任务有多个的话,onHandleIntent执行完最后一个任务时,服务才销毁。最后我们要知道每次执行一个后台任务就必须启动一次IntentService,而IntentService内部则是通过消息的方式发送给HandlerThread的,然后由Handler中的Looper来处理消息,而Looper是按顺序从消息队列中取任务的,也就是说IntentService的后台任务时顺序执行的,当有多个后台任务同时存在时,这些后台任务会按外部调用的顺序排队执行,我们前面的使用案例也很好说明了这点。
接下来,我们将通过 源码分析 解决以下问题:
- IntentService 如何单独开启1个新的工作线程
主要分析内容 = IntentService源码中的 onCreate()方法
@Override
public void onCreate() {
super.onCreate();
// 1. 通过实例化andlerThread新建线程 & 启动;故 使用IntentService时,不需额外新建线程
// HandlerThread继承自Thread,内部封装了 Looper
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
// 2. 获得工作线程的 Looper & 维护自己的工作队列
mServiceLooper = thread.getLooper();
// 3. 新建mServiceHandler & 绑定上述获得Looper
// 新建的Handler 属于工作线程 ->>分析1
mServiceHandler = new ServiceHandler(mServiceLooper);
}
/**
* 分析1:ServiceHandler源码分析
**/
private final class ServiceHandler extends Handler {
// 构造函数
public ServiceHandler(Looper looper) {
super(looper);
}
// IntentService的handleMessage()把接收的消息交给onHandleIntent()处理
@Override
public void handleMessage(Message msg) {
// onHandleIntent 方法在工作线程中执行
// onHandleIntent() = 抽象方法,使用时需重写 ->>分析2
onHandleIntent((Intent)msg.obj);
// 执行完调用 stopSelf() 结束服务
stopSelf(msg.arg1);
}
}
/**
* 分析2: onHandleIntent()源码分析
* onHandleIntent() = 抽象方法,使用时需重写
**/
@WorkerThread
protected abstract void onHandleIntent(Intent intent);
- IntentService 如何通过onStartCommand() 将Intent 传递给服务 & 依次插入到工作队列中
/**
* onStartCommand()源码分析
* onHandleIntent() = 抽象方法,使用时需重写
**/
public int onStartCommand(Intent intent, int flags, int startId) {
// 调用onStart()->>分析1
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
/**
* 分析1:onStart(intent, startId)
**/
public void onStart(Intent intent, int startId) {
// 1. 获得ServiceHandler消息的引用
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
// 2. 把 Intent参数 包装到 message 的 obj 发送消息中,
//这里的Intent = 启动服务时startService(Intent) 里传入的 Intent
msg.obj = intent;
// 3. 发送消息,即 添加到消息队列里
mServiceHandler.sendMessage(msg);
}
总结
从上面源码可看出:IntentService本质 = Handler + HandlerThread:
1、 onCreate()方法,通过HandlerThread 单独开启1个工作线程:IntentService
创建1个内部 Handler :ServiceHandler
2,通过 onStartCommand() 传递服务intent 到ServiceHandler 、依次插入Intent到工作队列中 & 逐个发送给 onHandleIntent()
若一个任务正在IntentService中执行,此时你再发送1个新的任务请求,这个新的任务会一直等待直到前面一个任务执行完毕后才开始执行、
原因:
- 由于onCreate()只会调用一次 = 只会创建1个工作线程;
- 当多次调用 startService(Intent)时(即 onStartCommand()也会调用多次),其实不会创建新的工
- 作线程,只是把消息加入消息队列中 & 等待执行。
所以,多次启动 IntentService 会按顺序执行事件