转载请注明出处:http://blog.csdn.net/yianemail/article/details/51713399
Service 是Android系统中实现程序后台运行的解决方案,非常适合那些不需要跟用户直接交互并且长期运行的任务。
Service运行于UiThread,因此若想要在Service 执行耗时操作,就需要在Service中创建线程成完成耗时任务。
IntentService 是继承于Service的并处理异步请求的一个类,二者的启动方式并没有什么差别。区别是IntentService 会自动运行在子线程中,并且执行完毕会自我stop。
区别总结:如果必须在Service (IntentService) 中执行耗时任务,在Service 中我们必须要采用开启新线程的方式,(比如new Thread().start()),且执行完毕要手动退出。而在IntentService中则可以直接执行,也不必手动干预退出。
一:模拟耗时任务,执行完毕更新界面ui
首先看下效果图
点击耗时任务,启动IntentService模拟耗时任务执行,执行完毕通过广播更新界面ui,(也可以采用handler)
二:代码实现
IntentService
package com.huanjulu.intentservice;/* * Copyright (C) 2016, * Author: huanjulu on 16/6/17 * to: */
import android.app.IntentService;
import android.content.Intent;
public class TaskIntentService extends IntentService {
public TaskIntentService() {
super("TaskIntentService-Thread");
}
public TaskIntentService(String name) {
super(name);
}
@Override
protected void onHandleIntent(Intent intent) {
//直接在此执行耗时任务
if (null != intent) {
onTashHandler();
}
}
/** * 模拟耗时任务 如果采用serivce 你就需new Thread 处理 */
private void onTashHandler() {
try {
Thread.sleep(3000);
Intent intent = new Intent();
intent.setAction(MainActivity.TNTENT_SERVICE);
sendBroadcast(intent);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public void onDestroy() {
super.onDestroy();
}
}
继承IntentService的类至少要实现两个函数:构造函数和onHandleIntent()函数。要覆盖IntentService的其它函数时,注意要通过super调用父类的对应的函数。
此处注意一下IntentService 的生命周期。我们在onHandleIntent()中模拟耗时任务(Thread.sleep(3000):模拟执行时间为3秒)执行完毕,发送广播,通知主界面更新ui。
Activity 代码实现
package com.huanjulu.intentservice;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends Activity {
public static final String TNTENT_SERVICE = "com.huanjulu.intentservice.TaskIntentService";
TextView textView;
private BroadcastReceiver uploadImgReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.d("TAG","onReceive");
if (intent.getAction() .equals(TNTENT_SERVICE)) {
Log.d("TAG","intent.getAction()");
textView.setText("耗时任务执行完毕!");
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.message_tv);
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(TNTENT_SERVICE);
registerReceiver(uploadImgReceiver, intentFilter);
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
textView.setText("正在执行任务...");
Intent intent = new Intent(MainActivity.this, TaskIntentService.class);
startService(intent);
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(uploadImgReceiver);
}
}
在onCreate()中我们注册广播,在onDestroy()中注销,点击事件去开启IntentService 执行任务。
Service 为四大组件之一,所以必须在AndroidMainfest.xml中声明。
通过IntentService 的执行生命周期,第一次执行是要走onCreat()
@Override
public void onCreate() {
super.onCreate();
}
super.onCreate(); 调用 父类(也就是IntentService) 的onCreat()函数。
分析一下IntentService 的onCreat() 做了什么
@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);
}
可以看到主要做了两件事,一是开启了一个HandlerThread 线程(有关HandlerThread 我稍后的博文会分析,这里只要知道HandlerThread 继承了Thread, 重点分析run()方法),二是通过mServiceLooper 实例化了ServiceHandler 对象。
分析 thread.start() ,
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
我们看到了什么? 没错!实例化mq ,开启消息循环..依旧是采用了android中的异步消息机制。
Looper.prepare();
Looper.loop();
通过 thread.getLooper();得到 实例化的looper 并作为参数实例化ServiceHandler()
private volatile Looper mServiceLooper;
private volatile ServiceHandler mServiceHandler;
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
//这里就是我们IntnetService 中覆写onHandleIntent 的逻辑
//执行完毕调用stopSelf()自动退出
onHandleIntent((Intent)msg.obj);
stopSelf(msg.arg1);
}
}
有了looper,实例化了handler ,总得有个sendMessage吧。
在onStart中
@Override
public void onStart(Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
流程总结
就是每次调用onStartCommand的时候 ,onStartCommand继续调用onStart ,通过mServiceHandler发送一个消息,消息中包含我们的intent。然后在该mServiceHandler的handleMessage中去回调onHandleIntent(intent);