IntentService原理

IntentService的Demo程序IntentService常被用于处理异步任务,使用的步骤是,先继承IntentService,再在handleIntent方法里写业务逻辑。handleIntent是在子线程执行的,所以不必担心ANR之类的问题,可以执行IO操作,下载等操作,且当执行完后会自动销毁,很方便。先写一个简单的Demo。CountService.java:publicc…

大家好,又见面了,我是你们的朋友全栈君。

IntentService的Demo程序

IntentService常被用于处理异步任务,使用的步骤是,先继承IntentService,再在handleIntent方法里写业务逻辑。handleIntent是在子线程执行的,所以不必担心ANR之类的问题,可以执行IO操作,下载等操作,且当执行完后会自动销毁,很方便。
先写一个简单的Demo。
CountService.java:

public class CountService extends IntentService {

    public final static String EXTRA_NUMBER = "extra_number";
    public String TAG = CountService.class.getSimpleName();

    public CountService() {
        super("CountService");
    }

@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
    Log.e(TAG,"onStartCommand -->> startId : "+startId);
    return super.onStartCommand(intent, flags, startId);
}

    @Override
    protected void onHandleIntent(@Nullable Intent intent) {
// 通过intent来接收传递过来的数据,这里运行的线程为子线程,执行完后,这个Service就会销毁
        int count = intent.getIntExtra(EXTRA_NUMBER, 1);
        for (int i = 0 ; i < count ; i++ ){
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Log.e(TAG,"onHandleIntent --> counting "+i);
        }
        Log.e(TAG,"onHandleIntent count end");
    }

@Override
public void onDestroy() {
    super.onDestroy();
    Log.e(TAG,"onDestroy");
}

}

CountActivity.java:

public class CountActivity extends Activity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 这个例子中布局什么的无所谓
        setContentView(R.layout.activity_test);

        Intent intent = new Intent(this,CountService.class);
        intent.putExtra(CountService.EXTRA_NUMBER,10);
        startService(intent);

        Intent intent2 = new Intent(this,CountService.class);
        intent2.putExtra(CountService.EXTRA_NUMBER,5);
        startService(intent2);

    }
}

当我们执行完后查看log信息:
在这里插入图片描述
分析一下这个log信息,在发送两个任务过去后,发现onStartCommand方法先执行,之后一个任务执行完后(onHandleIntent count end),再执行下一个任务,所有任务执行完后,这个Service就被销毁了(onDestroy)。

Demo的运行情况就讲到这里,下面我们通过源码,来揭开IntentService的神秘面纱。

源码分析

IntentService继承于Service,是一个抽象类。代码量不太多,只有180行左右,所以读起来也不是特别复杂。
在这里插入图片描述
先看IntentService的成员变量:

  1. String mName ; 这是IntentService所在线程的名字,可在声明一个IntentService的时候,用IntentService的构造方法 IntentService(String name)从外部传入进来。
  2. boolean mRedelivery; Redelivery是重发的意思,看一看与该成员变量有关的方法 setIntentRedelivery(boolean enable):
/**
 * Sets intent redelivery preferences.  Usually called from the constructor
 * with your preferred semantics.
 *
 * <p>If enabled is true,
 * {@link #onStartCommand(Intent, int, int)} will return
 * {@link Service#START_REDELIVER_INTENT}, so if this process dies before
 * {@link #onHandleIntent(Intent)} returns, the process will be restarted
 * and the intent redelivered.  If multiple Intents have been sent, only
 * the most recent one is guaranteed to be redelivered.
 *
 * <p>If enabled is false (the default),
 * {@link #onStartCommand(Intent, int, int)} will return
 * {@link Service#START_NOT_STICKY}, and if the process dies, the Intent
 * dies along with it.
 */
public void setIntentRedelivery(boolean enabled) {
    mRedelivery = enabled;
}

大致意思是设置重发的偏好。
如果为true, onStartCommand()方法会返回START_REDELIVER_INTENT,所以这个进程如果在onHandleIntent()没有执行的时候死亡,这个进程会重新开启并且intent会重新传输。如果多个Intent已经被发出,只有最近的那个能保证被重新传输。
如果为false,onStartCommand()方法会返回START_NOT_STICKY,如果进程死了,那么这个Intent也随着一起死了。

  1. ServiceHandler mServiceHandler;
    ServiceHandler 是IntentService的内部类,继承于Handler。
private final class ServiceHandler extends Handler {
    public ServiceHandler(Looper looper) {
        super(looper);
    }

    @Override
    public void handleMessage(Message msg) {
        onHandleIntent((Intent)msg.obj);
        stopSelf(msg.arg1);
    }
} 

重点来了 ,在handleMessage()方法中,我们看到了 onHandleIntent() 这个方法,这不就是执行异步任务的那个需要重写的方法吗?执行完onHanderIntent()后,就执行stopSelf(),所以IntentService就被销毁了。

  1. Looper mServiceLooper; 这个Looper是实例化ServiceHandler时传递进去的Looper,这个Looper是子线程的。这个Looper在onCreate()方法里面被实例化。

接下来再来看它的方法,我们将通过方法将IntentService的工作流程和它的成员变量串连起来。

  1. onCreate()方法:
@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,可见这是一个子线程
    HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
    thread.start();

    // HandlerThread里面的Looper,那就是说这个mServiceLooper是子线程的Looper
    mServiceLooper = thread.getLooper();
    // 传入了子线程的Looper--mServiceLooper来实例化ServiceHandler,ServiceHandler的handleMessage方法是在子线程中进行的
    mServiceHandler = new ServiceHandler(mServiceLooper);
}

由于IntentService继承于Service,所以也同样有一样的生命周期。当实例化了一个IntentService后,后走onCreate()、onStart(),当用Intent开启一个Service时,会调用onStartCommand()。由于这里的HandlerThread是Thread的子类,它的Looper是子线程的Looper,这样ServiceHandler的构造方法传入的是子线程的Looper,所以ServerHandler的handlerMessage()方法是在子线程中进行的。

  1. onStart()方法:
@Override
public void onStart(@Nullable Intent intent, int startId) {
    Message msg = mServiceHandler.obtainMessage();
    msg.arg1 = startId;
    msg.obj = intent;
    mServiceHandler.sendMessage(msg);
}

在这里intent对象和id,被装进Message对象中,然后发送到ServiceHandler对象中。前面已经提到IntentService里面的ServiceHandler的handleMessage():

 public void handleMessage(Message msg) {
        onHandleIntent((Intent)msg.obj);
        stopSelf(msg.arg1);	// 执行完后就停止服务	
    }

从这里调用到了onHandleIntent()方法,从而执行到重写的onHandleIntent()的代码。

  1. onStartCommand()方法:
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
    onStart(intent, startId);
    return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}

Service类从这里接收到Intent对象,然后调用onStart()方法,就执行到了onHandleIntent()的代码。
来回顾一下下面的代码:

        Intent intent = new Intent(this,CountService.class);
        intent.putExtra(CountService.EXTRA_NUMBER,10);
        startService(intent);

当这段代码被执行,CountService会被实例化,走生命周期的 onCreate()方法,创建 HandlerThread对象,创建在子线程中执行的ServiceHandler,调用了startService(intent)则会执行到onStartCommand()方法,再调用onStart()方法,把intent对象通过Message传递到handleIntent()方法中。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/125828.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 简述TCP的三次握手和四次挥手过程[通俗易懂]

    简述TCP的三次握手和四次挥手过程[通俗易懂]①TCP是一种精致的,可靠的字节流协议。②在TCP编程中,三路握手一般由客户端(Client)调用Connent函数发起。③TCP3次握手后数据收发通道即打开(即建立了连接)。④简述三路握手过程:图.TCP三次握手(1)第一次握手:Client将标志位SYN置为1,随机产生一个值s…

    2022年6月2日
    32
  • 精通Dubbo——Dubbo支持的协议的详解[通俗易懂]

    精通Dubbo——Dubbo支持的协议的详解[通俗易懂]Dubbo支持dubbo、rmi、hessian、http、webservice、thrift、redis等多种协议,但是Dubbo官网是推荐我们使用Dubbo协议的。下面我们就针对Dubbo的每种协议详解讲解,以便我们在实际应用中能够正确取舍。dubbo协议缺省协议,使用基于mina1.1.7+hessian3.2.1的tbremoting交互。连接个数:单连接连接方式:长连接传输协议

    2022年6月17日
    31
  • Java 分布式解决方案

    Java 分布式解决方案文章目录一、基础知识1.CAP理论2.BASE理论一、基础知识1.CAP理论CAP是Consistency、Availability、Partitiontolerance三个词语的缩写,分别表示一致性、可用性、分区容忍性Consistency一致性一致性是指写操作后的读操作可以读取到最新的数据状态,当数据分布在多个节点上,从任意结点读取到的数据都是最新的状态。Availability可用性可用性是指任何事务操作都可以得到响应结果,且不会出现响应超时或响应错误。Partitio

    2022年5月28日
    33
  • java中类与对象的详解

    java中类与对象的详解

    2021年9月2日
    54
  • TD—SCDMA_移动TD

    TD—SCDMA_移动TD
    GSM
     globalsystemformobilecommunications全球移动通信系统
     第二代移动电话系统。
         GSM是GlobalSystemofMobilecommunication全球移动通讯系统的英文缩写,是当前应用最为广泛的移动电话标准。全球超过200个国家和地区超过10亿人正在使用GSM电话。所有用户可以在签署了”漫游协定”移动电话运营商之间自由漫游。GSM较之它以前的标准最大的不同是他的信令和语音信道都是数

    2022年10月4日
    4
  • 经典排序算法(1)——冒泡排序算法详解

    经典排序算法(1)——冒泡排序算法详解冒泡排序(BubbleSort)是一种典型的交换排序算法,通过交换数据元素的位置进行排序。一、算法基本思想(1)基本思想冒泡排序的基本思想就是:从无序序列头部开始,进行两两比较,根据大小交换位置,直到最后将最大(小)的数据元素交换到了无序队列的队尾,从而成为有序序列的一部分;下一次继续这个过程,直到所有数据元素都排好序。算法的核心在于每次通过两两比较交换位置,选出

    2022年7月8日
    23

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号