/**
* 关于IntentService的一点理解
*
* 废话不多说,IntentService就是用来处理耗时操作的service,
* 我们平常用的service里面如果需要处理耗时操作需要在service里面
* 开启一条thread来处理耗时操作,而IntentService直接帮助我们封装了这些处理。非常方便。
*
* 需要注意的是 IntentService能处理多次请求,但是每次它只处理一次,一次完成后处理下一次。
* 看源码分析
*
*/
import android.content.Intent;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Process;
public abstract class IntentService extends Service {
// Looper对象,这个对象是拿个HandlerThread用的
private volatile Looper mServiceLooper;
// 这个Handler继承了Handler
private volatile ServiceHandler mServiceHandler;
// HandlerThread线程名字
private String mName;
// 这个玩意儿是给外界用的,不同的boolean值代表了service die了后执行不同的处理,请移步后面查看分析
private boolean mRedelivery;
// 其实这个东东就是运行在HandlerThread里面的,为什么呢?废话,用的是HandlerThread的looper
private final class ServiceHandler extends Handler {
// 这个地方肯定要传入HandlerThread的looper呀,对不对?对不对?肯定
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
// 下面这个方法不用说,肯定是外界覆写这个方法,然后在里面做耗时操作
onHandleIntent((Intent)msg.obj);
// 这是神码?它不同与stopself()方法,这个方法不会真正停止服务,除非是最后已经处理完了所有
// 请求,它只是停掉特定id的service
// 如何一个 service 被调用很多次,即 onStartCommand() 响应过很多个请求,
// 那么会相应的产生很多个 startId,比如:1,2,3 三个
// 那么,stopSelfResult(int startId) 只会在参数为 3 的时候才会真正地停止这个服务
// 另外,stopSelf() 是stopSelfResult()的老版本,推荐使用新版本
stopSelf(msg.arg1);
}
}
/**
* 创建一个IntentSerivce,肯定被子类创建啊
*/
public IntentService(String name) {
super();
mName = name;
}
/**
* 看看就好,设置为true,重传Intent。使用这个返回值时,如果在执行完onStartCommand后,
* 服务被异常kill掉,系统会自动重启该服务,并将Intent的值传入,返回START_REDELIVER_INTENT
*
* 反之返回START_NOT_STICKY,“非粘性的”。使用这个返回值时,如果在执行完onStartCommand后,
* 服务被异常kill掉,系统不会自动重启该服务。
*/
public void setIntentRedelivery(boolean enabled) {
mRedelivery = enabled;
}
@Override
public void onCreate() {
// 调用父类Service的Oncreate方法
super.onCreate();
// new出一个HandlerThread,这玩意相当于内部新开了线程
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
// 必须先让线程跑起来,才能拿到这条线程内部的looper,原理后续分析
thread.start();
// 获得HandlerThread的looper对象
mServiceLooper = thread.getLooper();
// 把HandlerThread的looper对象赋值给ServiceHandler,这样ServiceHandler接收的就是
// HandlerThread里面的looper里面的消息了。也就是这个handler的handMessage方法运行在
// HandlerThread中
mServiceHandler = new ServiceHandler(mServiceLooper);
}
@Override
public void onStart(Intent intent, int startId) {
// 这个方法直接给2.x以前版本用的啦,也就是你调用startService后调用这个
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
/**
* 这个是新版的调用的方法,也就是调用上面的那2.x的方法啦,发送消息而已
*/
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
onStart(intent, startId);
// 看到没?这个变量就是起这个作用的
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
@Override
public void onDestroy() {
// service die后,取消这个looper
mServiceLooper.quit();
}
/**
* 默认不处理bind操作
*/
@Override
public IBinder onBind(Intent intent) {
return null;
}
/**
* 这个方法就是用户需要覆写的方法,这里面做long time的操作
*/
protected abstract void onHandleIntent(Intent intent);
}
/**
* 在分析下IntentService里面用的HandlerThread原理吧,还是挺重要的,也不难
*
* 首先我们要知道。默认handler处理消息都是在主线程中进行的,大家都知道
* 要在单独一个Thread里面用handler,肯定得手动构造looper对象,并调用
* Looper.loop来开启消息循环,对吧,不过,android系统已经为我们考虑到了。那就是这个
* HandlerThread类
*
*/
// 看到没?其实就是一条线程
public class HandlerThread extends Thread {
// 线程优先级
int mPriority;
// 线程id
int mTid = -1;
// 内部looper对象
Looper mLooper;
public HandlerThread(String name) {
// 线程名字
super(name);
// 线程默认优先级
// 此处注意:大家看intentserivce里面构造这个HandlerThread就是用的这个方法
// 此处有一个问题:就是默认构造的线程优先级是default,这是不对的。
// Android要求我们后台开启的线程优先级都最好是后台优先级,这样才不会block UI
// 线程的执行。所以,很多人用intentserivce还是发现UI不是很顺畅,这就是原因。
// 所以做法应该是,把intentserivce源码抽出来,重写构造方法,传入我们的优先级就好了。
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}
/**
*没什么,就是构造罢了
*/
public HandlerThread(String name, int priority) {
super(name);
mPriority = priority;
}
/**
* 假如你想在looper。loop之前需要预先做一些操作,覆写这个方法吧
*/
protected void onLooperPrepared() {
}
// 大家看intentservice里面用HandlerThread的时候,需要先调用start方法,原因在下面
public void run() {
// 获得当前的tid
mTid = Process.myTid();
// Looper准备
Looper.prepare();
// 为什么ssynchronized呢,因为后面getLooper可以调用,但是有可能looper对象还没实例化出来
synchronized (this) {
// 实例化looper对象
mLooper = Looper.myLooper();
// 当looper对象有了后,就notifyall,其实就是此时的getLooper方法能拿到一个有效值了
notifyAll();
}
// 设置当前线程的优先级
Process.setThreadPriority(mPriority);
// 需要做些额外的准备操作,覆写这个方法吧,一般没有
onLooperPrepared();
// Looper开始 running
Looper.loop();
mTid = -1;
}
/**
* 拿到和这条thread相关的looper对象
*/
public Looper getLooper() {
if (!isAlive()) {
return null;
}
// If the thread has been started, wait until the looper has been created.
synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
/**
* 取消当前的looper
*/
public boolean quit() {
Looper looper = getLooper();
if (looper != null) {
looper.quit();
return true;
}
return false;
}
/**
* 获得线程的tid
*/
public int getThreadId() {
return mTid;
}
}
/**
* HandlerThread小例子
*/
public class AndroidHandlerThread extends Activity{
private static final int MESSAGE_FOR_START_LONG_TIME_WORK = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//打印了当前线程的ID
System.out.println("Activity-->" + Thread.currentThread().getId());
//生成一个HandlerThread对象,实现了使用Looper来处理消息队列的功能,这个类由Android应用程序框架提供
HandlerThread handlerThread = new HandlerThread("handler_thread");
//在使用HandlerThread的getLooper()方法之前,必须先调用该类的start();
handlerThread.start();
//获取处理器
MyHandler myHandler = new MyHandler(handlerThread.getLooper());
//获取信息,此处用于获得一个handler的msg对象
Message msg = myHandler.obtainMessage();
msg.what = MESSAGE_FOR_START_LONG_TIME_WORK;
//设置数据
//此处将bundle数据发到handler,并执行handlemessage
msg.sendToTarget();
}
/**
* 继承Handler类
*
* @author longgangbai
*
*/
class MyHandler extends Handler{
public MyHandler(){
}
public MyHandler(Looper looper){
super(looper);
}
/**
* 更改界面的方法 (其实handlemessage就是你想这个线程做的事情)
*/
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_FOR_START_LONG_TIME_WORK:
// 你在这里面做你要做的事情啦
break;
default:
break;
}
}
}
}
/**
* IntentService的小例子
*
*/
public class MyIntentService extends IntentService {
private static int i = 0;
public MyIntentService() {
super("fuck code --wql");
}
@Override
protected void onHandleIntent(Intent intent) {
// 这里面做耗时的操作
Log.e("test","test " + (i++));
}
}
public class ServiceDemoActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 连续启动两次IntentService,可以看到log连续打印两次
startService(new Intent(this,MyIntentService.class));
startService(new Intent(this,MyIntentService.class));
}
}
ending!!!!!!
关于intentservice和handlerthread的一点小理解
最新推荐文章于 2020-07-10 14:40:51 发布