IntentService 原理详解

您所在的位置:网站首页 service和intentservice的区别 IntentService 原理详解

IntentService 原理详解

2024-06-13 23:19| 来源: 网络整理| 查看: 265

1 简单介绍 IntentService是一个继承自Service的抽象类,是一种特殊的Service。所以两者的基本配置和启动方式都是一样的,区别是IntentService创建了自己的特有方法onHandleIntent(),可以用来处理异步请求,实现多线程,因此用来执行后台耗时操作任务,而每一个耗时操作都会以工作队列的方式在IntentService的onHandleIntent回调方法中执行,并且,每次只会执行一个工作线程,执行完第一个再执行第二个。

2 使用方式步骤 ① 定义IntentService的子类:传入线程名称、复写onHandleIntent()方法 ② 在Manifest.xml中注册服务 ③ 在Activity中开启Service服务

public class MyIntentService extends IntentService { private static final String TAG = MyIntentService.class.getSimpleName(); /** Java基础知识 * 为什么必须要重写? 父类只有带参数的构造器(无参构造器没有),则子类必须有相同参数的构造方法,并且还需要调用super(参数),如果父类中含有无参构造函数,则super可以省略不写 * 调用父类的构造函数 * 构造函数参数=工作线程的名字 */ public MyIntentService() { super("MyIntentService"); } @Override public void onCreate() { super.onCreate(); Log.i(TAG, "onCreate: "); } /** * 执行耗时操作 必须判断intent是否为空 * @param intent */ @Override protected void onHandleIntent(Intent intent) { if (intent != null) { String tag = intent.getStringExtra("task"); switch (tag) { case "task1": Log.i(TAG, "onHandleIntent: " + "正在执行task1"); break; case "task2": Log.i(TAG, "onHandleIntent: " + "task1已执行完毕 开始执行task2"); break; } } } @Override public int onStartCommand(@Nullable Intent intent, int flags, int startId) { Log.i(TAG, "onStartCommand: "); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { super.onDestroy(); Log.i(TAG, "onDestroy: "); } } //同一服务只会开启一个工作线程 //在onHandleIntent函数里依次处理intent请求。 Intent i = new Intent("com.adnonstop.myintentservice"); i.putExtra("task", "task1"); i.setPackage(getPackageName()); startService(i); Intent i2 = new Intent("com.adnonstop.myintentservice"); i2.putExtra("task", "task2"); i2.setPackage(getPackageName()); startService(i2); //多次启动 for (int j = 0; j startService(i); } else { startService(i2); } }

打印数据发现会永远按照队列的方式按照顺序来执行耗时操作

onHandleIntent: 正在执行task1 onHandleIntent: task1已执行完毕 开始执行task2

3 .为什么在onHandleIntent 中可以进行耗时操作,内部原理是如何实现的?

private volatile Looper mServiceLooper; private volatile ServiceHandler mServiceHandler; private String mName; IntentService里面的onCreate()方法 @Override public void onCreate() { super.onCreate(); HandlerThread thread = new HandlerThread("IntentService[" + mName + "]"); thread.start(); mServiceLooper = thread.getLooper(); mServiceHandler = new ServiceHandler(mServiceLooper); }

分析1; HandlerThread 继承自Thread,首先开启了一个名为mName的子线程thread ,然后获取子线程中的looper赋值给mServiceLooper,再创建一个handler并且与mServiceHandler绑定,所以现在的mServiceHandler属于工作线程的

HandlerThread 中是如何维护了一个looper?

HandlerThread 里面重写的run方法 @Override public void run() { //这个是在子线程中创建handler的完成部分 Looper.prepare(); synchronized (this) { mLooper = Looper.myLooper(); notifyAll(); } Process.setThreadPriority(mPriority); onLooperPrepared(); Looper.loop(); mTid = -1; }

分析2: 我们在分析handler的原理时,分析过在子线程中创建handler的过程 首先要创建一个Looper ,即调用Looper.prepare();,然后将创建的looper赋值给本地维护的mLooper ,加了一个同步锁,这也就保证了我们在多线程操作时保证执行的顺序

获取和子线程绑定的looper的方法 public Looper getLooper() { //如果线程没有启动或者时因为某些原因,线程杀掉 返回为null if (!isAlive()) { return null; } //如果线程已经启动,则会一直等到创建looper为止 synchronized (this) { while (isAlive() && mLooper == null) { try { wait(); } catch (InterruptedException e) { } } } return mLooper; }

分析3 创建mServiceHandler之后,就是发送消息了

多次启动同一个service,只会多次执行onStartCommand方法,只会执行一次oncreate方法, 保证只创建了一个mServiceHandler,所有的发送消息和处理消息都会交给他处理 @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 onStart(@Nullable Intent intent, int startId) { Message msg = mServiceHandler.obtainMessage(); msg.arg1 = startId; msg.obj = intent; mServiceHandler.sendMessage(msg); } 处理消息的方法 private final class ServiceHandler extends Handler { public ServiceHandler(Looper looper) { super(looper); } @Override public void handleMessage(Message msg) { //抽象方法 onHandleIntent ,所以我们重写即可 //protected abstract void onHandleIntent(@Nullable Intent intent); onHandleIntent((Intent)msg.obj); //onHandleIntent 处理完成后 IntentService会调用 stopSelf() 自动停止。 stopSelf(msg.arg1); } }

工作队列中的任务是顺序执行的。因为onCreate() 方法只会调用一次,所以只会创建一个工作线程,多次开启服务只会多次执行onStartCommand方法,不会创建更多的线程,只是将消息添加到消息队列的等待执行。 但如果服务停止的话,会清空队列里的消息,不再执行。

Handler 对象在哪个线程下构建(Handler的构造函数在哪个线程下调用),那么Handler 就会持有这个线程的Looper引用和这个线程的消息队列的引用。因为持有这个线程的消息队列的引用,意味着这个Handler对象可以在任意其他线程给该线程的消息队列添加消息,也意味着Handler的handleMessage 肯定也是在该线程执行的。handler对象所绑定的线程其实并不取决于该handler对象由哪个线程构建,而是取决于该handler对象所绑定的Looper属于哪个线程。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3