关于intentservice和handlerthread的一点小理解

/**
 * 关于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!!!!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值