一. 前言
1.多线程常用的主要方法
继承Thread类
实现Runable接口
AsyncTask
Handler
HnadlerThread
IntentService
2. IntentService的作用
处理异步请求 和 实现多线程
3. 使用场景
线程任务需要按顺序,在后台执行。
最常见的场景:离线下载。
4. 工作原理

若启动IntentService
多次,那么 每个耗时操作 则 以队列的方式 在 IntentService
的 onHandleIntent
回调方法中依次执行,执行完自动结束。
二. 源码分析
1. IntentService 如何单独开启一个新的工作线程
主要分析内容 = IntentService
源码中的 onCreate()
方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| @Override public void onCreate() { super.onCreate(); HandlerThread thread = new HandlerThread("IntentService[" + mName + "]"); thread.start(); mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper); }
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); }
@WorkerThread protected abstract void onHandleIntent(Intent intent);
|
2. IntentService 如何通过 onStartCommand 将 Intent 传递给服务 & 依次插入到工作队列中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
|
public int onStartCommand(Intent intent, int flags, int startId) {
onStart(intent, startId); return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY; }
public void onStart(Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage(); msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg); }
|
3. 总结
从上面源码可看出:IntentService
本质 = Handler
+ HandlerThread
:
- 通过
HandlerThread
单独开启1个工作线程:IntentService
- 创建1个内部
Handler
:ServiceHandler
- 绑定
ServiceHandler
与 IntentService
- 通过
onStartCommand()
传递服务intent
到ServiceHandler
、依次插入Intent
到工作队列中 & 逐个发送给 onHandleIntent()
- 通过
onHandleIntent()
依次处理所有Intent
对象所对应的任务
因此我们通过复写onHandleIntent()
& 在里面 根据Intent
的不同进行不同线程操作 即可

三. 注意事项
1. 工作任务队列 = 顺序执行
即 若一个任务正在IntentService
中执行,此时你再发送1个新的任务请求,这个新的任务会一直等待直到前面一个任务执行完毕后才开始执行。
若服务停止,则会清除消息队列中的消息,后续的事件不执行。
原因:
- 由于
onCreate()
只会调用一次 = 只会创建1个工作线程;
- 当多次调用
startService(Intent)
时(即 onStartCommand()
也会调用多次),其实不会创建新的工作线程,只是把消息加入消息队列中 & 等待执行。
- 所以,多次启动 IntentService 会按顺序执行事件
2. 不建议通过 bindService() 启动 IntentService
1 2 3 4 5
| @Override public IBinder onBind(Intent intent) { return null; }
|
采用 bindService()
启动 IntentService
的生命周期如下:onCreate() ->> onBind() ->> onunbind()->> onDestory()。
即,并不会调用onStart()
或 onStartcommand()
,故不会将消息发送到消息队列,那么onHandleIntent()将不会回调,即无法实现多线程的操作。
四. 实际小例子
1. 自定义一个IntentService,并注册
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| public class MyIntentService extends IntentService { public static final String TAG = MyIntentService.class.getSimpleName();
public MyIntentService() { super("MyIntentService"); }
public MyIntentService(String name) { super(name); }
@Override protected void onHandleIntent(@Nullable Intent intent) { String task_name = intent.getExtras().getString("task_name");
switch (task_name){ case "task_1": Log.d(TAG,"正在执行任务 1"); break;
case "task_2": Log.d(TAG,"正在执行任务 2"); break; } }
@Override public void onCreate() { super.onCreate();
Log.d(TAG,"onCreate"); }
@Override public int onStartCommand(@Nullable Intent intent, int flags, int startId) { Log.d(TAG,"onStartCommand");
return super.onStartCommand(intent, flags, startId); }
@Override public void onDestroy() { super.onDestroy();
Log.d(TAG,"onDestroy"); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="swu.xl.intentservice">
<application android:allowBackup="true" android:icon="@mipmap/view" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
<service android:name=".MyIntentService"/>
</application>
</manifest>
|
2. 在Activity中使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| public class MainActivity extends AppCompatActivity {
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
Intent intent = new Intent(this,MyIntentService.class); Bundle bundle = new Bundle(); bundle.putString("task_name","task_1"); intent.putExtras(bundle); startService(intent);
intent = new Intent(this,MyIntentService.class); bundle = new Bundle(); bundle.putString("task_name","task_2"); intent.putExtras(bundle); startService(intent);
} }
|
3. 运行效果
1 2 3 4 5 6
| 2020-06-03 17:18:58.952 28217-28217/swu.xl.intentservice D/MyIntentService: onCreate 2020-06-03 17:18:58.952 28217-28217/swu.xl.intentservice D/MyIntentService: onStartCommand 2020-06-03 17:18:58.953 28217-28259/swu.xl.intentservice D/MyIntentService: 正在执行任务 1 2020-06-03 17:18:58.953 28217-28217/swu.xl.intentservice D/MyIntentService: onStartCommand 2020-06-03 17:18:58.954 28217-28259/swu.xl.intentservice D/MyIntentService: 正在执行任务 2 2020-06-03 17:18:59.181 28217-28217/swu.xl.intentservice D/MyIntentService: onDestroy
|
参考文章
Android多线程:这是一份全面 & 详细的IntentService源码分析指南