IntentService,可以看做是Service和HandlerThread的结合体,在完成了使命之后会自动停止,适合需要在工作线程处理UI无关任务的场景。
IntentService 是继承自 Service 并处理异步请求的一个类,在 IntentService 内有一个工作线程来处理耗时操作。
当任务执行完后,IntentService 会自动停止,不需要我们去手动结束。
如果启动 IntentService 多次,那么每一个耗时操作会以工作队列的方式在 IntentService 的 onHandleIntent 回调方法中执行,依次去执行,使用串行的方式,执行完自动结束。
下面是一个例子,点击开始启动一个IntentService去更新进度条,更新完毕IntentService会自动结束。如果多次点击开始,就会执行多遍,多遍执行完之后IntentService才会执行onDestroy方法。
package com.jay.services; import android.app.IntentService; import android.content.Intent; import android.util.Log; import androidx.annotation.Nullable; import androidx.localbroadcastmanager.content.LocalBroadcastManager; import com.jay.myandroidtestapp.IntentServiceActivity; /** * 启动之后会先执行构造方法,然后执行onCreate方法,再到onHandleIntent方法。 * 在onHandleIntent让进度自增,每次自增睡眠50ms并向Activity发送广播并传递进度的数据。 * */ public class MyIntentService extends IntentService { private static final String TAG = "MyIntentService"; /** * Creates an IntentService. Invoked by your subclass's constructor. * * @param name Used to name the worker thread, important only for debugging. */ public MyIntentService(String name) { super(name); } public MyIntentService() { super(TAG); } /** * 是否正在运行 */ private boolean isRunning; /** * 进度 */ private int count; /** * 广播 */ private LocalBroadcastManager mLocalBroadcastManager; @Override public void onCreate() { super.onCreate(); Log.i(TAG, "onCreate"); mLocalBroadcastManager = LocalBroadcastManager.getInstance(this); } @Override protected void onHandleIntent(@Nullable Intent intent) { Log.i(TAG, "onHandleIntent"); try { Log.d(TAG, "onHandleIntent 线程运行中..."); Thread.sleep(1000); isRunning = true; count = 0; while (isRunning) { count++; if (count >= 100) { isRunning = false; } Thread.sleep(50); Log.d(TAG, "onHandleIntent 线程运行中..."); sendThreadStatus("线程运行中...", count); } } catch (Exception e) { e.printStackTrace(); } } /** * 发送进度消息 */ private void sendThreadStatus(String status, int progress) { Intent intent = new Intent(IntentServiceActivity.ACTION_TYPE_THREAD); intent.putExtra("status", status); intent.putExtra("progress", progress); mLocalBroadcastManager.sendBroadcast(intent); } @Override public void onDestroy() { super.onDestroy(); Log.i(TAG, "线程结束运行..." + count); } }
启动之后会先执行构造方法,然后执行onCreate方法,再到onHandleIntent方法。在onHandleIntent让进度自增,每次自增睡眠50ms并向Activity发送广播并传递进度的数据。
IntentServiceActivity
package com.jay.myandroidtestapp; import androidx.appcompat.app.AppCompatActivity; import androidx.localbroadcastmanager.content.LocalBroadcastManager; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.ProgressBar; import android.widget.TextView; import com.jay.services.MyIntentService; import com.jay.utils.MyBroadcastReceiver; public class IntentServiceActivity extends AppCompatActivity { private String TAG = "IntentServiceActivity"; /** * 状态文字 */ private TextView tv_status; /** * 进度文字 */ private TextView tv_progress; /** * 进度条 */ private ProgressBar progressbar; private Button btn_start; private LocalBroadcastManager mLocalBroadcastManager; private MyBroadcastReceiver mBroadcastReceiver; public final static String ACTION_TYPE_THREAD = "action.type.thread"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_intent_service); tv_progress = findViewById(R.id.tv_progress); tv_status = findViewById(R.id.tv_status); progressbar = findViewById(R.id.progressbar); btn_start = findViewById(R.id.btn_start); btn_start.setOnClickListener(myOnClickListener); //注册广播 mLocalBroadcastManager = LocalBroadcastManager.getInstance(this); mBroadcastReceiver = new MyBroadcastReceiver(tv_status, tv_progress, progressbar,this); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(ACTION_TYPE_THREAD); mLocalBroadcastManager.registerReceiver(mBroadcastReceiver, intentFilter); initView(); } public void initView() { tv_status.setText("线程状态:未运行"); progressbar.setMax(100); progressbar.setProgress(0); tv_progress.setText("0%"); } @Override protected void onDestroy() { super.onDestroy(); //注销广播 mLocalBroadcastManager.unregisterReceiver(mBroadcastReceiver); } public View.OnClickListener myOnClickListener = new View.OnClickListener() { @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn_start: Log.d(TAG, "onHandleIntent 线程运行中..."); Intent intent = new Intent(IntentServiceActivity.this, MyIntentService.class); startService(intent); break; } } }; }
点击开始按钮,会启动MyIntentService。mLocalBroadcastManager.registerReceiver(mBroadcastReceiver, intentFilter)注册广播,接收广播消息和数据,并时刻更改进度条进度。
自定义广播
package com.jay.utils; import android.app.Activity; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.widget.ProgressBar; import android.widget.TextView; import com.jay.myandroidtestapp.IntentServiceActivity; /** * 自定义广播接收器 * */ public class MyBroadcastReceiver extends BroadcastReceiver { public static final String TAG = "MyBroadcastReceiver";/** * 状态文字 */ private TextView tv_status; /** * 进度文字 */ private TextView tv_progress; /** * 进度条 */ private ProgressBar progressbar; private Activity curActivity; public MyBroadcastReceiver(){} public MyBroadcastReceiver(TextView tv_status, TextView tv_progress, ProgressBar progressbar,Activity curActivity){ this.progressbar = progressbar; this.tv_progress = tv_progress; this.tv_status = tv_status; this.curActivity = curActivity; } @Override public void onReceive(Context context, Intent intent) {switch (intent.getAction()) { case IntentServiceActivity.ACTION_TYPE_THREAD: curActivity.runOnUiThread(new Runnable() { @Override public void run() { //更改UI int progress = intent.getIntExtra("progress", 0); tv_status.setText("线程状态:" + intent.getStringExtra("status")); progressbar.setProgress(progress); tv_progress.setText(progress + "%"); if (progress >= 100) { tv_status.setText("线程结束"); } } }); break; } } }
注册MyIntentService
<service android:name="com.jay.services.MyIntentService" tools:ignore="Instantiatable"></service>
IntentService继承自Service,内部有一个HandlerThread对象。
在onCreate的时候会创建一个HandlerThread对象,并启动线程。紧接着创建ServiceHandler对象,ServiceHandler继承自Handler,用来处理消息。ServiceHandler将获取HandlerThread的Looper就可以开始正常工作了。
每启动一次onStart方法,就会把数消息和数据发给mServiceHandler,相当于发送了一次Message消息给HandlerThread的消息队列。mServiceHandler会把数据传个onHandleIntent方法,onHandleIntent是个抽象方法,需要在IntentService实现,所以每次onStart方法之后都会调用我们自己写的onHandleIntent方法去处理。处理完毕使用stopSelf通知HandlerThread已经处理完毕,HandlerThread继续观察消息队列,如果还有未执行玩的message则继续执行,否则结束。
IntentService内部的HandlerThread 继承自 Thread,内部封装了 Looper,在这里新建线程并启动,所以启动 IntentService 不需要新建线程。
IntentService 中使用的 Handler、Looper、MessageQueue 机制把消息发送到线程中去执行的,所以多次启动 IntentService 不会重新创建新的服务和新的线程,只是把消息加入消息队列中等待执行,而如果服务停止,会清除消息队列中的消息,后续的事件得不到执行。
来源:https://blog.csdn.net/b1480521874/article/details/94987641/