大家好,又见面了,我是你们的朋友全栈君。
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的成员变量:
- String mName ; 这是IntentService所在线程的名字,可在声明一个IntentService的时候,用IntentService的构造方法 IntentService(String name)从外部传入进来。
- 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也随着一起死了。
- 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就被销毁了。
- Looper mServiceLooper; 这个Looper是实例化ServiceHandler时传递进去的Looper,这个Looper是子线程的。这个Looper在onCreate()方法里面被实例化。
接下来再来看它的方法,我们将通过方法将IntentService的工作流程和它的成员变量串连起来。
- 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()方法是在子线程中进行的。
- 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()的代码。
- 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()方法中。
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/125828.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...