安卓intentService源碼

IntentService是handlerThread與Service的結合,因爲實質是串行的執行,所以該service不適合執行頻繁的網絡請求類型的操作,但是他是一個用完自動停止的service,並且減輕主線程looper的壓力,所以非常 適合做一些非及時性的耗時操作,如後臺數據統計等.

用法
創建一個intentService,模擬一個耗時操作,發送一個廣播到ui

public class MyIntentService extends IntentService {

    public MyIntentService() {
        super("MyIntentService");
    }

    /**
     * 這是子線程,不需要再開一個線程了
     *
     * @param intent
     */
    @Override
    protected void onHandleIntent(Intent intent) {
        for (int i = 0; i < 10; i++) {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //創建Intent
            Intent intent1 = new Intent();
            intent1.setAction("myintentService.reciver");
            intent1.putExtra("string", i + "次刷新");
            //發送廣播
            sendBroadcast(intent1);
        }
    }
}

ui開啓服務,接受廣播

public class MainActivity extends AppCompatActivity {

    private TextView text;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        text = findViewById(R.id.tv);
        MyReciver myReciver = new MyReciver();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction("myintentService.reciver");
        registerReceiver(myReciver, intentFilter);
        Intent intent = new Intent(this, MyIntentService.class);
        startService(intent);

    }

    private class MyReciver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            String string = intent.getStringExtra("string");
            MainActivity.this.text.setText(string);
        }
    }
}

用完之後該service就停止了,當多次啓動會多次執行onHandleIntent,因爲原理是handler,looper來實現的,所以是串行,啓動之後實則是發送一個消息.

源碼
intentService的源碼很簡單,只有一百多行代碼

  public IntentService(String name) {
        super();
        mName = name;
    }

先看構造函數,這裏穿了一個線程的名字

    @Override
    public void onCreate() {
        super.onCreate();
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();
        mServiceLooper = thread.getLooper();
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }

再看onCreat()方法,在這裏呢創建了一個handlerThread線程,並且開始執行,然後獲取該線程的looper,然後賦值給handler,handler的執行型線程取決與該looper的線程,

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

再看這個onStart方法,這裏啓動的時候默認發送了一個消息,將intent複製給msg

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

再看這個handler做了什麼,handler接受到消息的時候調用onHandleIntent去執行,然後調用stopSelf去停止服務

   public final void stopSelf(int startId) {
        if (mActivityManager == null) {
            return;
        }
        try {
            mActivityManager.stopServiceToken(
                    new ComponentName(this, mClassName), mToken, startId);
        } catch (RemoteException ex) {
        }
    }

再看stopSelf,該方法通過stopServiceToken停止掉了service,但是service沒有被馬上殺死,所以就形成了一個串行的執行,這裏的startId是AMS爲starService創建的一個id號,默認是遞增的一個數,所以每次startService的時候都會+1,也可以認爲是啓動的次數,每次handler執行完消息的時候都會調用一次stopSelf,stopSelf的本身其實是根據startId來關閉服務的,只有startId是最後一起啓動時候的startId纔會去停掉,這也就解釋了爲什麼多次啓動IntentService會多次執行handlerIntent

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

mServiceLooper.quit(),該方法是將隊列中的所有消息移除,並且停止循環

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章