IntetntService基本使用及源碼解析

一、簡介

    IntentService is a base class for {@link Service}s that handle asynchronous
 * requests (expressed as {@link Intent}s) on demand.  Clients send requests
 * through {@link android.content.Context#startService(Intent)} calls; 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用於處理異步請求,使用工作線程(子線程)處理每個intent,工作完後停止自己

 * <p>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 {@link #onHandleIntent(Intent)}.  IntentService
 * will receive the Intents, launch a worker thread, and stop the service as
 * appropriate.
 // 使用時需要繼承IntentService 實現onHandleIntent(Intent)方法,IntentService會接收到intents啓動一個工作線程,並且會適當的停止服務

 * <p>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.
 // 所有的請求會在一個單獨的工作線程處理,在不阻塞應用主循環的前提下會盡可能長存活,但是每次只處理一個請求

二、基本使用

1、創建類繼承IntentService,並重寫onHandleIntent()方法,重寫無參構造方法

public class MyIntentService extends IntentService {
    private int progress = 0;

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

    @Override
    protected void onHandleIntent(@Nullable Intent intent) {
        try {
        // 模擬耗時操作
            Thread.sleep(1000);
            while (true) {
                progress++;
                if (progress > 100) {
                    break;
                }
                sendBroadCast();
                Thread.sleep(100);

            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private void sendBroadCast() {
        Intent mIntent = new Intent();
        mIntent.setAction("updateProgress");
        mIntent.putExtra("updateProgress", progress);
        getApplicationContext().sendBroadcast(mIntent);
    }
}

2、Activity中調用並更新UI

public class IntentServiceActivity extends Activity {


    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_intent_service);
        initBroadCastReceiver();
        initView();
    }

    private void initBroadCastReceiver() {
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction("updateProgress");
        registerReceiver(broadcastReceiver, intentFilter);
    }


    private void initView() {
        Button btnStartService = findViewById(R.id.btn_start);
        btnStartService.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent();
                intent.setClass(IntentServiceActivity.this, MyIntentService.class);
                startService(intent);
            }
        });

    }


    private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction() == "updateProgress") {
                int progress = intent.getIntExtra("updateProgress", 0);
                ProgressBar progressBar = findViewById(R.id.progressBar);
                progressBar.setProgress(progress);

                if (progress == 100) {
                    Toast.makeText(IntentServiceActivity.this, "downLoadSuccess", Toast.LENGTH_SHORT).show();
                }
            }
        }
    };

}

3、layout文件

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <Button
        android:id="@+id/btn_start"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="start_service"/>

    <ProgressBar
        android:id="@+id/progressBar"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_marginTop="20dp"
        />

</android.support.v7.widget.LinearLayoutCompat>

4、效果圖

這裏寫圖片描述

三、源碼分析

// 抽象類繼承Service,爲Service的子類
public abstract class IntentService extends Service 

構造方法

// 被子類構造調用
 /**
 * Creates an IntentService.  Invoked by your subclass's constructor.
 *
 * @param name Used to name the worker thread, important only for debugging.
 */
public IntentService(String name) {
 super();
mName = name;
    }

onCreate()

   @Override
    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();
        // 獲取線程的Looper
        mServiceLooper = thread.getLooper();
        // 使用當前線程looper創建線程
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }

ServiceHandler

   private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            // 處理消息
            onHandleIntent((Intent)msg.obj);
            // 處理完後調用stopSelf,停止當前服務
            stopSelf(msg.arg1);
        }
    }

onStartCommand()

 @Override
    public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
        // 調用onStart方法
        onStart(intent, startId);
        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
    }

onStart()

    @Override
    public void onStart(@Nullable Intent intent, int startId) {
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
        // 通過mServiceHandler發送消息
        mServiceHandler.sendMessage(msg);
    }

onDestroy()

  @Override
    public void onDestroy() {
    // 生命週期結束直接將looper關閉,所以在該service使用完後會自動關閉
        mServiceLooper.quit();
    }

總結:
intentService通過創建子線程進行耗時操作,結合handler進行線程切換操作,所以可以進行耗時操作,在onDestroy()方法中,將當前工作線程的looper關閉,同時在handleMessage中通過stopSelf(msg.arg1);關閉service,完成生命週期綁定,處理完耗時操作無需自己處理。

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