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
具体关于HandlerThread的介绍,请看 Android HandlerThread源码分析。
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 + " 下载完成"); } }
相关文章推荐
- Android IntentService浅谈以及源码分析
- Android IntentService的使用和源码分析
- Android多线程:IntentService用法&源码分析
- android-----IntentService源码分析
- Android IntentService浅谈以及源码分析
- Android线程IntentService源码分析
- Android IntentService的使用和源码分析
- Android面试题-IntentService源码分析
- Android之IntentService使用及源码分析
- Android开发:IntentService使用(源码分析)
- Android中IntentService源码分析及其使用
- 【Android应用源码分析】IntentService 源码分析
- Android中线程形态AsyncTask、HandlerThread和IntentService工作原理分析
- IntentService源码分析
- IntentService源码分析
- Android IntentService使用全面介绍及源码解析
- IntentService源码分析
- android Service 源码分析
- Android Service学习之IntentService 深入分析
- Android Binder机制 - defaultServiceManager()源码分析