Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android IntentService使用全面介紹及源碼解析

Android IntentService使用全面介紹及源碼解析

編輯:關於Android編程

一 IntentService介紹

IntentService定義的三個基本點:是什麼?怎麼用?如何work?

官方解釋如下:

//IntentService定義的三個基本點:是什麼?怎麼用?如何work?*/

1、IntentService is a base class for Services that handle asynchronous requests (expressed as Intents) on demand. 2、Clients send requests through startService(Intent) calls; 
3、the service is started as needed, handles each Intent in turn using a worker thread, and stops itself when it runs out of work.

//解釋了IntentService的好處,以及How to use IntentService*/

This "work queue processor" pattern is commonly used to offload tasks from an application's main thread. The IntentService class exists to simplify this pattern and take care of the mechanics. To use it, extend IntentService and implement onHandleIntent(Intent). IntentService will receive the Intents, launch a worker thread, and stop the service as appropriate.

All requests are handled on a single worker thread -- they may take as long as necessary (and will not block the application's main loop), but only one request will be processed at a time.

總結IntentService的特點如下:

1、IntentService是Service類的子類,用來處理異步請求。
2、客戶端可以通過startService(Intent)方法傳遞請求給IntentService
3、IntentService在onCreate()函數中通過HandlerThread單獨開啟一個線程來處理所有Intent請求對象(通過startService的方式發送過來的)所對應的任務,這樣以免事務處理阻塞主線程。
4、執行完所一個Intent請求對象所對應的工作之後,如果沒有新的Intent請求達到,則自動停止Service;否則執行下一個Intent請求所對應的任務。
5、IntentService在處理事務時,還是采用的Handler方式,創建一個名叫ServiceHandler的內部Handler,並把它直接綁定到HandlerThread所對應的子線程。 ServiceHandler把處理一個intent所對應的事務都封裝到叫做onHandleIntent的虛函數;因此我們直接實現虛函數onHandleIntent,再在裡面根據Intent的不同進行不同的事務處理就可以了。

IntentService最重要的一個方法onHandleIntent:

This method is invoked on the worker thread with a request to process. Only one Intent is processed at a time, but the processing happens on a worker thread that runs independently from other application logic. So, if this code takes a long time, it will hold up other requests to the same IntentService, but it will not hold up anything else. When all requests have been handled, the IntentService stops itself, so you should not call stopSelf().

1、該函數用於針對Intent的不同進行不同的事務處理.執行完所一個Intent請求對象所對應的工作之後,如果沒有新的Intent請求達到,
則自動停止Service;否則ServiceHandler會取得下一個Intent請求傳人該函數來處理其所對應的任務。
2、所有請求都在一個單線程中,不會阻塞應用程序的主線程(UI Thread),但是同一時間只處理一個請求。

IntentService的特點、優點、缺點?

IntentService的特點:

1、IntentService是借助於消息隊列實現的,所以任務的執行順序就是一個queue的形式;
2、由於是單線程(一個工作線程),所以所有的任務需要排隊執行;/
3、避免了我們再去創建線程和管理service的結束工作;

基於以上,IntentService與Service比較的好處有:

第一,使用方便,代碼簡潔,不再需要我們自己像Service裡面還要去手動創建線程;
第二,當操作完成時,我們不用手動停止Service。

當然,IntentService的缺點也是顯而易見:

由於是單個的worker thread,所以任務需要排隊,不適合大多數的多任務情況;

二 DEMO實踐

DEMO場景描述:

主要由MainActivity和MyIntentService構成,在MainActivity中啟動服務,並傳遞兩個參數a和b,在MyIntentService中獲取參數,求和,並通過發送廣播的形式向UI返回結果,然後MainActivity在接收到廣播之後更新UI。

MainActivity.java主要做了三件事:

注冊/注銷廣播接收器; 創建UI和更新UI; 傳遞參數,啟動MyIntentService;

代碼如下:

public class MainActivity extends AppCompatActivity {

    private LinearLayout ll_container;
    private BroadcastReceiver forSumReceiver=new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.i("TAG","onReceive ()");
            if(intent.getAction()==Constans.ACTION_RESULT){
                int a=intent.getIntExtra(Constans.A,0);
                int result=intent.getIntExtra(Constans.RESULT,0);
                Log.i("TAG","onReceive --result:"+result);
                handleResult(a,result);
            }
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ll_container= (LinearLayout)findViewById(R.id.ll_container);
        Log.i("TEST","MainActivity:"+android.os.Process.myTid());
        registerBroadcast();
    }

    private void handleResult(int a,int result){
        TextView textView=(TextView)ll_container.findViewWithTag(a);
        String old=textView.getText().toString();
        String newText=old.replaceAll("  正在計算中...",String.valueOf(result)+"  計算Success");
        textView.setText(newText);
    }

    private void registerBroadcast(){
        IntentFilter intentFilter=new IntentFilter();
        intentFilter.addAction(Constans.ACTION_RESULT);
        registerReceiver(forSumReceiver,intentFilter);
    }

    private int a=1;
    public void addTask(View view){
        int b=new Random().nextInt(101)+1;
        MyIntentService.startMyIntentService(this,a,b);
        TextView textView=new TextView(this);
        textView.setText(a+"+"+b+"= "+ "  正在計算中...");
        textView.setTag(a);
        ll_container.addView(textView);
        a++;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(forSumReceiver);
    }
}

MyIntentService用於接收參數,並返回計算的結果:

public class MyIntentService extends IntentService {


    public MyIntentService() {
        //必須實現父類的構造方法
        super("MyIntentService");
    }

    @Override
    public void onCreate() {
        Log.i("TEST","onCreate()");
        super.onCreate();
    }

    @Override
    public void onStart(Intent intent, int startId) {
        Log.i("TEST","onStart()");
        super.onStart(intent, startId);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i("TEST","onStartCommand()");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.i("TEST", "onBind()");
        return super.onBind(intent);
    }

    @Override
    public void onDestroy() {
        Log.i("TEST","onDestroy()");
        super.onDestroy();
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        Log.i("TEST","onHandleIntent():"+android.os.Process.myTid());
        if (intent!=null){
            String action=intent.getAction();
            if(Constans.ACTION_FOR_SUM.equals(action)){
                int a=intent.getIntExtra(Constans.A,0);
                int b=intent.getIntExtra(Constans.B,0);
                int result=a+b;
                Log.i("TEST","result: "+result);
                handleResult(a,result);
            }
        }
    }

    private void handleResult(int a,int result){
        try{
            //模擬計算耗時
            Thread.sleep(3000);
            Intent intent=new Intent(Constans.ACTION_RESULT);
            intent.putExtra(Constans.RESULT,result);
            intent.putExtra(Constans.A,a);
            sendBroadcast(intent);
        }catch (InterruptedException e){
            e.printStackTrace();;
        }
    }

    public static void startMyIntentService(Context context,int a,int b){
        Intent intent=new Intent(context,MyIntentService.class);
        intent.setAction(Constans.ACTION_FOR_SUM);
        intent.putExtra(Constans.A,a);
        intent.putExtra(Constans.B,b);
        context.startService(intent);
    }

}

IntentService生命周期方法執行順序如下:

07-08 10:18:51.579 com.troy.intentservicedemo I/TEST: MainActivity:30060 
07-08 10:19:26.009 com.troy.intentservicedemo I/TEST: onCreate()
07-08 10:19:26.009 com.troy.intentservicedemo I/TEST: onStartCommand()
07-08 10:19:26.009 com.troy.intentservicedemo I/TEST: onStart()
07-08 10:19:26.039 com.troy.intentservicedemo I/TEST: onHandleIntent():30223
07-08 10:19:26.039 com.troy.intentservicedemo I/TEST: result: 23
07-08 10:19:29.100 com.troy.intentservicedemo I/TEST: onDestroy()
07-08 10:19:31.839 com.troy.intentservicedemo I/TEST: onCreate()
07-08 10:19:31.849 com.troy.intentservicedemo I/TEST: onStartCommand()
07-08 10:19:31.849 com.troy.intentservicedemo I/TEST: onStart()
07-08 10:19:31.869 com.troy.intentservicedemo I/TEST: onHandleIntent():30305
07-08 10:19:31.869 com.troy.intentservicedemo I/TEST: result: 52
07-08 10:19:34.899 com.troy.intentservicedemo I/TEST: onDestroy()

從上面Log中可以看出:

UI線程的線程ID=30060,而onHandleIntent()的線程ID分別是30223,30305;由此知道onHandleIntent()方法是執行在工作線程中的;

並且IntentService的所有請求如果是在一個生命周期中完成的話,則所有請求是在一個工作線程中順序執行的。否則,是在不同的工作線程中完成。

同時驗證了:執行完所一個Intent請求對象所對應的工作之後,如果沒有新的Intent請求達到,則自動停止Service;

運行效果如圖:

這裡寫圖片描述

三 IntentService源碼簡單解析

IntentService是Service的子類,擁有Service的所有生命周期方法;同時還有自己的ServiceHandler;

ServiceHandler相關源碼如下:

public abstract class IntentService extends Service {
    private volatile Looper mServiceLooper;//volatile關鍵字保證同步,保證可見性
    private volatile ServiceHandler mServiceHandler;
    private String mName;
    private boolean mRedelivery;

    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);
        }
    }


    public IntentService(String name) {//構造方法
        super();
        mName = name;
    }

IntentService 實際上是Looper,Handler,Service 的集合體,他不僅有服務的功能,還有處理和循環消息的功能。

onCreate()的源碼:創建了一個HandlerThread

 @Override 
        public void onCreate() { 
                super.onCreate(); 

                HandlerThread thread = new HandlerThread("IntentService[" + mName + "]"); 
                thread.start(); 

                mServiceLooper = thread.getLooper(); 
                mServiceHandler = new ServiceHandler(mServiceLooper); 
        }

IntentService創建時就會創建Handler線程(HandlerThread)並且啟動,然後再得到當前線程的Looper對象來初始化IntentService的mServiceLooper,接著創建mServicehandler對象。

下面是onStart()的源碼: 調用mServiceHandler

@Override 
        public void onStart(Intent intent, int startId) { 
                Message msg = mServiceHandler.obtainMessage(); 
                msg.arg1 = startId; 
                msg.obj = intent; 

                mServiceHandler.sendMessage(msg); 
        }

當你啟動IntentService的時候,就會產生一條附帶startId和Intent的 Message並發送到MessageQueue中,接下來Looper發現MessageQueue中有Message的時候,就會停止Handler 處理消息。

handleMessage處理的代碼如下:

 @Override 
        public void handleMessage(Message msg) { 
                        onHandleIntent((Intent)msg.obj); 
                        stopSelf(msg.arg1); 
        }

接著調用 onHandleIntent((Intent)msg.obj),這是一個抽象的方法,其實就是我們要重寫實現的方法,我們可以在這個方法裡面處理我們的工作.當任務完成時就會調用stopSelf(msg.arg1)這個方法來結束指定的工作。

stopSelf(msg.arg1):

注意下:回調完成後回調用 stopSelf(msg.arg1),注意這個msg.arg1是個int值,相當於一個請求的唯一標識。每發送一個請求,會生成一個唯一的標識,然後將請求放入隊列,當全部執行完成(最後一個請求也就相當於getLastStartId == startId),或者當前發送的標識是最近發出的那一個(getLastStartId == startId),則會銷毀我們的Service.如果傳入的是-1則直接銷毀。

當所有的工作執行完後:就會執行onDestroy方法。

onDestroy源碼如下:

 @Override 
        public void onDestroy() { 
                mServiceLooper.quit(); 
        }

服務結束後調用這個方法 mServiceLooper.quit()使looper停下來。

最後總結一下上述的分析:

1、 IntentService是一個基於消息的服務,每次啟動該服務並不是馬上處理你的工作,而是首先會創建對應的Looper,Handler並且在MessageQueue中添 加的附帶客戶Intent的Message對象, 當Looper發現有Message的時候接著得到Intent對象通過在 onHandleIntent((Intent)msg.obj)中調用你的處理程序. 處理完後即會停止自己的服務. 意思是Intent的生命周期跟你的 處理的任務是一致的. 所以這個類用下載任務中非常好,下載任務結束後服務自身就會結束退出。
2、IntentService是不適合用於bindService()這樣的啟動方式的。其次我們通過startService多次啟動Service時,相當於在MessageQueue中添加了多個任務,就可以實現多任務按照順序執行。
3、只有在onHandleIntent()方法中執行的代碼才是在工作線程中運行的。IntentService的停止不是因為在handleMessage() 中執行了stopSelf(msg.arg1);而是系統自己停止的。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved