| 注册
请输入搜索内容

热门搜索

Java Linux MySQL PHP JavaScript Hibernate jQuery Nginx
aqpp1310
8年前发布

Android IntentService源码分析

   <h2>简介</h2>    <p>Service 是 Android 四大组件之一,用于后台运行,但由于 Service 依然运行在主线程,所以是不能直接进行耗时操作的。如果有耗时操作,还是需要放到子线程中,可以手动开启线程,也可以使用 Android 提供的一个非常简便的类 IntentService 。这个类的源码还是很简单的,本文分析一下它的实现。</p>    <h2>HandlerThread</h2>    <p>在分析 IntentService 之前,先要了解 HandlerThread 。看名字就知道这个类是与 Handler 有关的线程类,API 是这么描述的:</p>    <p>Handy class for starting a new thread that has a looper. The looper can then be used to create handler classes. Note that start() must still be called.</p>    <p>它是为创建附带 Looper 对象的线程的帮助类。 Looper 对象可用于创建 Handler 类。 当然仍然要调用 start() 来开启线程。</p>    <p>在上篇文章 <a href="/misc/goto?guid=4959670011941923907" rel="nofollow,noindex">Android Handler的原理</a> 中,我们知道一个线程创建 Handler 的时候,必须要有 Looper 对象,利用 Looper 开启消息循环。在主线程中,系统已经帮我们做了这些工作。那么如果在其它子线程,我们该怎么创建 Looper 呢? 看看 HandlerThread 的 run() 方法:</p>    <pre>  <code class="language-java">public void run() {      mTid = Process.myTid();      Looper.prepare();      synchronized (this) {          mLooper = Looper.myLooper();          notifyAll();      }      Process.setThreadPriority(mPriority);      onLooperPrepared();      Looper.loop();      mTid = -1;  }</code></pre>    <p>在这个方法中调用了 Looper.prepare() 为线程获取 Looper 对象,并且保存这个对象。接着又调用 Looper.loop() 开启消息循环,这个方法里面有个无限循环不断从消息队列中取出消息,于是这个线程的消息系统便建立起来了。这些在上一篇文章中已经分析过。</p>    <h2>IntentService</h2>    <p>搞清楚 HandlerThread , IntentService 就很简单了。 IntentService 内部使用了 HandlerThread 。 IntentService 继承了 Service 并且是 一个抽象类。下面是它的 onCreate() 方法:</p>    <pre>  <code class="language-java"> 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 = new HandlerThread("IntentService[" + mName + "]");      thread.start();        mServiceLooper = thread.getLooper();      mServiceHandler = new ServiceHandler(mServiceLooper);  }    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);      }  }  </code></pre>    <p>这个方法里面创建了一个 HandlerThread 对象,并且获取它的 Looper ,紧接着用这个 Looper 创建了 Handler 。 IntentService 的 handleMessage 方法把接收的消息交给 onHandleIntent 处理,这个方法是一个抽象方法,也是我们使用 IntentService 时需要重写的方法。 onHandleIntent 处理完成后 IntentService 会调用 stopSelf() 自动停止。 handleMessage 将在 Looper.loop() 方法中被调用,运行在 HandlerThread 中,所以可以安全地处理耗时操作。</p>    <p>消息又是怎么传过来的呢?看一下 onStartCommand() 的源码:</p>    <pre>  <code class="language-java">public int onStartCommand(Intent intent, int flags, int startId) {      onStart(intent, startId);      return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;  }  public void onStart(Intent intent, int startId) {      Message msg = mServiceHandler.obtainMessage();      msg.arg1 = startId;      msg.obj = intent;      mServiceHandler.sendMessage(msg);  }</code></pre>    <p>很简单,把 intent 参数包装到 message 的 obj 中,然后发送消息。这里的 Intent 就是启动服务时 startService(Intent) 里的 Intent 。</p>    <p>对于 Service 而言,多次调用 startService(Intent) 时, onCreate() 方法只会调用一次,所以在这里面做一些初始化工作,而 onStartCommand 则相应地会调用多次。因此,只要 Intent 的参数不同,便可以完成不同的任务。</p>    <h2>总结</h2>    <p>从上面的分析可以看出,只要明白 Handler 的原理, IntentService 还是比较好理解的。使用 IntentService 需要注意几点:</p>    <ul>     <li> <p>不可以直接和UI做交互。为了把他执行的结果体现在UI上,需要把结果返回给Activity。</p> </li>     <li> <p>工作任务队列是顺序执行的,如果一个任务正在IntentService中执行,此时你再发送一个新的任务请求,这个新的任务会一直等待直到前面一个任务执行完毕才开始执行。</p> </li>     <li> <p>正在执行的任务无法打断。</p> </li>    </ul>    <p>来自: <a href="/misc/goto?guid=4959670012033158841" rel="nofollow">https://segmentfault.com/a/1190000004875002</a></p>    
 本文由用户 aqpp1310 自行上传分享,仅供网友学习交流。所有权归原作者,若您的权利被侵害,请联系管理员。
 转载本站原创文章,请注明出处,并保留原始链接、图片水印。
 本站是一个以用户分享为主的开源技术平台,欢迎各类分享!
 本文地址:https://www.open-open.com/lib/view/open1459931439489.html
源码分析 安卓开发 Android开发 移动开发