Android IntentService 异步 Service

当我们执行文件上传,文件下载等耗时任务时,为了保证 App 退回到后台而降低被系统干掉的概率,使得该任务仍然能继续执行,我们通常会将这些任务放在后台 Service 中去处理,但是,Service 是运行在主线程中(不能执行耗时操作),因此必须在 Service 中创建子线程来执行。Android SDK 提供了 IntentService 来简化了这个过程。

IntentService 特点:

  • IntentService 是继承自 Service 的抽象类,内部使用 HandlerThread + Handler 建立了异步线程来处理 后台 Service 耗时操作。
  • 当耗时任务执行完后,IntentService 会自动停止,不需要手动去停止。
  • 启动多次 IntentService ,每个耗时任务会在 onHandleIntent 中以队列形式依次执行。

IntentService 常规使用套路

  1. 继承自 IntentService 类,重写构造函数和 onHandleIntent() 方法。
  2. 在 onHandleIntent() 方法中处理耗时任务,运行于子线程中。
  3. 通过 startService() 方式启动 IntentService, 不能通过 bindService() 方式启动,因为 IntentService 中的 onBind() 方法返回 null。

以下代码,模拟每次点击按钮添加一个耗时任务到队列中,直到所有的任务执行完后,才自动停止 service。

这里写图片描述

这里写图片描述

/**
* UploadLogService.java
*/
public class UploadLogService extends IntentService {

    public static final String ACTION_UPDATE_UI = "action_update_ui";

    private static final String TAG = "UploadLogService";

    public UploadLogService() {
        super("upload-log-service");
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "onCreate: ");
    }

    @Override
    public void onStart(@Nullable Intent intent, int startId) {
        super.onStart(intent, startId);
        Log.d(TAG, "onStart: ");
    }

    @Override
    public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
        Log.d(TAG, "onStartCommand: ");
        return super.onStartCommand(intent, flags, startId);
    }


    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG, "onBind: ");
        return super.onBind(intent);
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.d(TAG, "onUnbind: ");
        return super.onUnbind(intent);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy: ");
    }

    /**
     * 运行于子线程中
     *
     * @param intent
     */
    @Override
    protected void onHandleIntent(@Nullable Intent intent) {

        if (intent != null) {
            String text = intent.getStringExtra("text");
            Log.d(TAG, "onHandleIntent: " + text);

            SystemClock.sleep(3000);   // 模拟耗时任务

            // 任务执行完成,广播通知更新 ui
            Intent updateUiIntent = new Intent();
            updateUiIntent.setAction(ACTION_UPDATE_UI);
            updateUiIntent.putExtra("text", text);
            LocalBroadcastManager.getInstance(this).sendBroadcast(updateUiIntent);
        }
    }
}
/**
* IntentServiceActivity.java
**/
public class IntentServiceActivity extends AppCompatActivity {

    private int index;

    private LinearLayout linearLayout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_intent_service);
        linearLayout = findViewById(R.id.ll_layout);

        // 注册广播
        registerBroadcastReceiver();

    }

    // 注册本地广播
    private void registerBroadcastReceiver() {
        IntentFilter filter = new IntentFilter(UploadLogService.ACTION_UPDATE_UI);
        LocalBroadcastManager.getInstance(this).registerReceiver(receiver, filter);
    }


    // 更新 UI 的本地广播
    private BroadcastReceiver receiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String text = intent.getStringExtra("text");
            TextView textView = linearLayout.findViewWithTag(text);
            textView.setText(text + ">>>>>>>> success");
        }
    };


    public void click(View view) {
        index++;
        String text = "uploading log = " + index;
        addTextView(text);

        // 开启异步任务service
        startService(text);
    }

    private void addTextView(String text) {
        TextView textView = new TextView(this);
        textView.setText(text);
        textView.setTag(text);
        linearLayout.addView(textView);
    }

    private void startService(String text) {
        Intent intent = new Intent(this, UploadLogService.class);
        intent.putExtra("text", text);
        startService(intent);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver);
    }
}

由此得出结果:

(1)多次启动 IntentService ,onCreate() 只会执行一次,而 onStart() / onStartCommond() 会执行多次,异步任务会顺序执行,直到所有的任务执行完成才会执行 onDestroy() 停止 Service。

(2)onBind() / onUnbind() 没有执行,因为启动 IntentService 是通过 startService() 方式启动的,但是我们不能通过 bindService() 方式启动 IntentService,因为 IntentService 源码中的 onBind() 方法返回 null。

(3)停止服务后,后续的事件将不会执行,因为 IntentService 中的 onDestroy() 中调用了 looper 的 quit() 方法退出轮询。

猜你喜欢

转载自blog.csdn.net/xingxtao/article/details/79953380
今日推荐