zoukankan      html  css  js  c++  java
  • Android IntentService使用介绍以及源码解析

    版权声明:本文出自汪磊的博客,转载请务必注明出处。

    一、IntentService概述及使用举例

    IntentService内部实现机制用到了HandlerThread,如果对HandlerThread不了解的话建议先看上篇文章:Android HandlerThread使用介绍以及源码解析

    IntentService是神马玩意?它就是一个Service,但是我们知道在Service中不能进行耗时操作,如果要进行耗时操作的话我们就需要自己new一个子线程在里面进行耗时操作,然而这一切谷歌工程师早就替我们做好了,只需使用IntentService即可,自己会启动一个子线程做耗时操作,无需我们自己管理子线程,并且完成任务后会自动停止。这么好的玩意赶紧看下怎么使用。

    接下来我们编写一个小Demo,模拟在IntentService中进行网络通信,并且成功后通知主线程,主线程做出相应反应。Demo中通过广播接收者实现子线程与主线程的通信。

    首先我们编写IntentService,如下:

     1 public class MyIntentService extends IntentService {
     2 
     3     public static final String TAG = "WL";
     4 
     5     public MyIntentService() {
     6         //为子线程起一个名字
     7         super("IntentService");
     8         
     9     }
    10 
    11     //子线程中执行
    12     @Override
    13     protected void onHandleIntent(Intent intent) {
    14         // TODO Auto-generated method stub
    15         if(null !=intent){
    16             String action = intent.getAction();
    17             if(action.equalsIgnoreCase(MainActivity.ACTION_START)){
    18                 
    19                 String url = intent.getStringExtra(MainActivity.URL);
    20                 Log.i(TAG, "开始请求_URL:"+url);
    21                 //模拟网络请求
    22                 try {
    23                     Thread.sleep(2000);
    24                 } catch (InterruptedException e) {
    25                     // TODO Auto-generated catch block
    26                     e.printStackTrace();
    27                 }
    28                 Log.i(TAG, "请求成功");
    29                 //
    30                 handlerRequestSuccess();
    31             }
    32         }
    33     }
    34 
    35     //
    36     private void handlerRequestSuccess() {
    37         // 发送广播通知主线程请求成功
    38         Intent intent = new Intent(MainActivity.ACTION_START);
    39         intent.putExtra("msg", "请求成功");
    40         sendBroadcast(intent);
    41     }
    42     
    43 }

    主要逻辑就是继承IntentService,重写onHandleIntent方法,onHandleIntent运行在子线程可以进行耗时操作,在模拟网络请求成功的时候发送广播。

    接下来看下MainActivity逻辑:

     1 public class MainActivity extends Activity {
     2 
     3     //
     4     public static final String ACTION_START= "START_HTTP_REQUEST";
     5     public static final String URL= "URL";
     6     private MyBroadcastReceiver myBroadcastReceiver;
     7 
     8     @Override
     9     protected void onCreate(Bundle savedInstanceState) {
    10         super.onCreate(savedInstanceState);
    11         setContentView(R.layout.activity_main);
    12         //注册广播接收者
    13         myBroadcastReceiver = new MyBroadcastReceiver();
    14         IntentFilter filter = new IntentFilter();
    15         filter.addAction(ACTION_START);
    16         registerReceiver(myBroadcastReceiver, filter);
    17     }
    18     
    19     @Override
    20     protected void onResume() {
    21         //
    22         super.onResume();
    23         Intent intent = new Intent(this, MyIntentService.class);
    24        intent.setAction(ACTION_START);
    25         intent.putExtra(URL, "http://www.cnblogs.com/leipDao/");
    26        startService(intent);//必须是start方式启动服务,bind方法无效,分析源码的时候就明白了
    27     }
    28     
    29     @Override
    30     protected void onDestroy() {
    31         // TODO Auto-generated method stub
    32         super.onDestroy();
    33         unregisterReceiver(myBroadcastReceiver);
    34     }
    35     
    36     private class MyBroadcastReceiver extends BroadcastReceiver {
    37 
    38         @Override
    39         public void onReceive(Context context, Intent intent) {
    40             
    41             String action = intent.getAction();
    42             if(action.equalsIgnoreCase(ACTION_START)){
    43                 
    44                 String extra = intent.getStringExtra("msg");
    45                 Log.i(MyIntentService.TAG, "onReceive::::"+extra);
    46             }
    47         }
    48     }
    49 }

    逻辑也是比较简单,onCreate的时候注册广播接收者,用于接收IntentService中模拟网络请求成功的时候发送的广播,onResume的时候启动服务。onDestroy的时候移除广播接收者。Demo比较简单,运行程序打印如下:

    IntentService中完成耗时操作并且完成子线程与主线程的通信。

    二、IntentService源码解析

    IntentService源码比较简短,直接贴出全部源码分析:

     1 public abstract class IntentService extends Service {
     2     private volatile Looper mServiceLooper;
     3     private volatile ServiceHandler mServiceHandler;
     4     private String mName;
     5     private boolean mRedelivery;
     6 
     7     private final class ServiceHandler extends Handler {
     8         public ServiceHandler(Looper looper) {
     9             super(looper);
    10         }
    11 
    12         @Override
    13         public void handleMessage(Message msg) {
    14             onHandleIntent((Intent)msg.obj);
    15             stopSelf(msg.arg1);
    16         }
    17     }
    18 
    19     /**
    20      * Creates an IntentService.  Invoked by your subclass's constructor.
    21      *
    22      * @param name Used to name the worker thread, important only for debugging.
    23      */
    24     public IntentService(String name) {
    25         super();
    26         mName = name;
    27     }
    28 
    29     public void setIntentRedelivery(boolean enabled) {
    30         mRedelivery = enabled;
    31     }
    32 
    33     @Override
    34     public void onCreate() {
    35         // TODO: It would be nice to have an option to hold a partial wakelock
    36         // during processing, and to have a static startService(Context, Intent)
    37         // method that would launch the service & hand off a wakelock.
    38 
    39         super.onCreate();
    40         HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
    41         thread.start();
    42 
    43         mServiceLooper = thread.getLooper();
    44         mServiceHandler = new ServiceHandler(mServiceLooper);
    45     }
    46 
    47     @Override
    48     public void onStart(Intent intent, int startId) {
    49         Message msg = mServiceHandler.obtainMessage();
    50         msg.arg1 = startId;
    51         msg.obj = intent;
    52         mServiceHandler.sendMessage(msg);
    53     }
    54 
    55     /**
    56      * You should not override this method for your IntentService. Instead,
    57      * override {@link #onHandleIntent}, which the system calls when the IntentService
    58      * receives a start request.
    59      * @see android.app.Service#onStartCommand
    60      */
    61     @Override
    62     public int onStartCommand(Intent intent, int flags, int startId) {
    63         onStart(intent, startId);
    64         return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
    65     }
    66 
    67     @Override
    68     public void onDestroy() {
    69         mServiceLooper.quit();
    70     }
    71 
    72     @Override
    73     public IBinder onBind(Intent intent) {
    74         return null;
    75     }
    76 
    77     @WorkerThread
    78     protected abstract void onHandleIntent(Intent intent);
    79 }

    很简短吧,出去注释不到100行,接下来我们分析重点部分。

    24-27行,构造函数传递进来一个name,用于第40行初始化HandlerThread,就是子线程的名字。

    接下来看34-45行onCreate()的时候:主要就是初始化一个HandlerThread以及ServiceHandler,7-17行发现ServiceHandler就是一个普通的Handler而已。看过上一篇Android HandlerThread使用介绍以及源码解析应该明白,ServiceHandler运行在子线程中,这里就不仔细解释了,不明白的地方可以查看Android HandlerThread使用介绍以及源码解析

    73-75行发现onBind的时候什么也没做,就是返回null,还记得demo中注释吗必须以start方式启动服务,因为bing方式启动什么也没做。

    48-53行onStart的时候发送一个消息到ServiceHandler,第14行handleMessage的时候直接调用onHandleIntent方法,紧接着15行结束本次任务。

    到这里主要流程就完了,其本质就是利用了HandlerThread保证ServiceHandler在子线程运行机制,在我们以start方式启动服务的时候,执行到service生命周期方法onStart的时候就会发送一个消息,然后在ServiceHandler中handleMessage方法执行onHandleIntent方法,子类重写此方法实现耗时任务即可。

    好了,到此IntentService就分析完了,理解IntentService最核心的就是先理解HandlerThread。

    本篇到此为止,希望对你有用。

  • 相关阅读:
    C#和Modbus通信工程
    C#中JS和Flash中AS 3.0通信交互
    创建型-建造者模式(Builder)
    结构型-享元模式(Flyweight)
    行为型-模板方法模式(Template Method)
    创建型-原型模式(Prototype)
    行为型-状态模式(State)
    结构型-桥接模式(Bridge)
    行为型-中介者模式(Mediator)
    行为型-备忘录模式(Memento)
  • 原文地址:https://www.cnblogs.com/leipDao/p/8034018.html
Copyright © 2011-2022 走看看