欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android IntentService 异步 Service

程序员文章站 2022-08-13 21:04:47
当我们执行文件上传,文件下载等耗时任务时,为了保证 App 退回到后台而降低被系统干掉的概率,使得该任务仍然能继续执行,我们通常会将这些任务放在后台 Service 中去处理,但是...

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

IntentService 特点:

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

IntentService 常规使用套路

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

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

Android IntentService 异步 Service

Android IntentService 异步 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() 方法退出轮询。