您的位置:首页 > 移动开发 > Android开发

Android IntentService源码分析

2017-11-16 22:36 393 查看
大家知道,普通Service服务是运行在UI线程上的,这就意味着如果我们需要通过Service执行一些耗时的操作,我们必须要通过创建一个工作线程来完成,否则应用可能会出现ANR异常。

IntentService就是为了解决这个问题而出现的。IntentService是Service的一个子类,该类的作用就是可以让服务在工作线程中执行任务,而不需要自行创建工作线程。

IntentService的主要作用(优点):

1. 在IntentService中会默认创建工作线程用于执行传递的Intent,这样在执行耗时操作时不需要手动去创建线程了

2. 在IntentService中创建工作队列,用于将 Intent 逐一传递给 onHandleIntent() 实现,这样就永远不必担心多线程问题。

3. 在处理完所有启动请求后停止服务,因此您永远不必调用 stopSelf()。

4. IntentService的onBind方法默认返回null

IntentService源码分析

在IntentService中,主要使用到了HandlerThread。HandlerThread是Thread的一个子类,在该类中可以使用Handler。其实HandlerThread的实现原理非常简单,就是在run方法中通过Looper.prepare()来创建消息队列,然后通过Looper.loop()方法开启消息循环,整个实现流程如同ActivityThread.main()方法中MainLooper的初始化过程。

具体关于HandlerThread的介绍,请看 Android HandlerThread源码分析

IntentServcie源码分析

public abstract class IntentService extends Service {

/**
* 1、在IntentServcie被首次创建时,会执行onCreate方法
*/
@Override
public void onCreate() {
super.onCreate();
// 1、创建一个HandlerThread,用于接收消息
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();

// 2、获取上面HandlerThread的实例的looper
mServiceLooper = thread.getLooper();

// 3、通过HandlerThread的looper,创建一个handler对象mServiceHandler,这样通过mServiceHandler发送的对象都会在HandlerThread中被处理
mServiceHandler = new ServiceHandler(mServiceLooper);
}

/**
* 2、每次启动IntentServcie, onStartCommand方法会被调用,该方法内部主要调用onStart方法
*/
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}

/**
* 3、在onStrat方法中主要是通过mServiceHandler发送了一条消息。
* <p>
* 在mServiceHandler发送的消息中,intent对象会作为发送消息的参数(这里的intent和通过startServcie方法传递的intent是同一个对象)
* <p>
* 同时,消息中会被携带一个startId的参数,该参数主要用于判断服务是否结束
*/
@Override
public void onStart(Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}

/**
* 4、ServiceHandler,该handler对象是通过HandlerThread的looper创建的,所以通过ServiceHandler
* 发送的消息都会被发送到HandlerThread中执行,由于HandlerThread是一个Thread类,这样就实现了在IntentService
* 无需创建一个Thread来执行后台耗时任务。
* <p>
* 同时,由于ServiceHandler内部的消息队列是通过looper维护的,这样就保证了消息队列是顺序执行的,所以IntentService也是
* 顺序执行任务的。
*/
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}

@Override
public void handleMessage(Message msg) {
/*
* 1、抽象方法,需要在子类中实现具体后台任务的实现
*/
onHandleIntent((Intent) msg.obj);

/*
* 2、在任务执行完成,自动停止服务。
*
* msg.arg1 就是在startId,这是为每一消息生成的唯一标识。每通过IntentService处理一个请求时,
* 都会有一个消息被放入到消息队列中,只有当最后一个消息执行完成即msg.arg1等于最后一个放入到消息队列的startId,
* 服务才会被停止,否者IntentService不会被停止
*
* 这样做的好处就是:保证消息队列中的所有消息都被处理,服务才会被停止。
*
*/
stopSelf(msg.arg1);
}
}

/**
* 5、抽象方法,该方法需要在IntentService的子类中实现,也是IntentService中唯一一个需要实现的方法
*
* @param intent
*/
protected abstract void onHandleIntent(Intent intent);

@Override
public void onDestroy() {
// 退出消息队列循环
mServiceLooper.quit();
}

@Override
@Nullable
public IBinder onBind(Intent intent) {
// 默认返回null
return null;
}

}


IntentService的简单使用

这里通过IntentService模拟一个简单的下载任务。

public class IntentServcieActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_intent_servcie);

Button button = findViewById(R.id.btn);
button.setOnClickListener(new View.OnClickListener() {
private int urlid;
@Override
public void onClick(View v) {
Intent intent = new Intent(IntentServcieActivity.this, DownloadService.class);
intent.putExtra(DownloadService.DOWN_URL, "url" + ++urlid);
startService(intent);
}
});
}
}

/**
* 通过IntentService完成下载任务
*/
public class DownloadService extends IntentService {
public static final String DOWN_URL = "down_url";
public DownloadService() {
super("DownloadService");
}

@Override
protected void onHandleIntent(Intent intent) {
String url = intent.getStringExtra(DOWN_URL);
downlaod(url);
}

/**
* 模拟下载任务
*/
private void downlaod(String url) {
Log.e("zhangke", "url = " + url + "  正在下载中...");
SystemClock.sleep(3000);
Log.e("zhangke", "url = " + url + "  下载完成");
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: