Android IntentService 耗时操作
上一章节我们已经知道了如何去定义和启动 Service,但如果我们直接把耗时线程放到 Service 中的 onStart()
方法中,虽然可以这样做,但是很容易
会引起 ANR 异常 ( Application Not Responding),这是因为
Service
不是一个单独的进程,它和它的应用程序在同一个进程中Service
也不是一个线程,我们应该避免在 Service 中进行耗时操作
为了解决可能需要在 Service
中进行耗时的任务,Android
提供了 IntentService
IntentService
IntentService
是继承自 Service 并用来处理异步请求的一个类
IntentService
中有一个工作线程来处理耗时操作,请求的 Intent 记录会加入队列
IntentService 的一般用法如下
-
客户端通过
startService(Intent)
来启动IntentService
-
不需要手动的去控制
IntentService
,当任务执行完后IntentService
会自动停止 -
IntentService 可以被启动多次,每个耗时操作会以工作队列的方式在
IntentService
的onHandleIntent()
回调方法中执行,并且每次只会执行一个工作线程,执行完一,再到二这样
范例
-
创建一个 空的 Android 项目
cn.twle.android.IntentService
-
创建一个耗时的
Service
类MsService.java
package cn.twle.android.intentservice; import android.app.IntentService; import android.content.Intent; import android.os.IBinder; import android.util.Log; public class MsService extends IntentService { private final String TAG = "IntentService:ms"; //必须实现父类的构造方法 public MsService() { super("MsService"); } //必须重写的核心方法 @Override protected void onHandleIntent(Intent intent) { //Intent 是从 Activity 发过来的,携带识别参数,根据参数不同执行不同的任务 String action = intent.getExtras().getString("param"); if(action.equals("s1")) Log.i(TAG,"启动service1"); else if(action.equals("s2")) Log.i(TAG,"启动service2"); else if(action.equals("s3")) Log.i(TAG,"启动service3"); //让服务休眠2秒 try{ Thread.sleep(2000); }catch(InterruptedException e){e.printStackTrace();} } //重写其他方法,用于查看方法的调用顺序 @Override public IBinder onBind(Intent intent) { Log.i(TAG,"onBind"); return super.onBind(intent); } @Override public void onCreate() { Log.i(TAG,"onCreate"); super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i(TAG,"onStartCommand"); return super.onStartCommand(intent, flags, startId); } @Override public void setIntentRedelivery(boolean enabled) { super.setIntentRedelivery(enabled); Log.i(TAG,"setIntentRedelivery"); } @Override public void onDestroy() { Log.i(TAG,"onDestroy"); super.onDestroy(); } }
-
修改
AndroidManifest.xml
注册Service
<service android:name=".MsService" android:exported="false"> <intent-filter > <action android:name="cn.twle.android.intentservice"/> </intent-filter> </service>
-
修改
MainActivity.java
启动三次服务package cn.twle.android.intentservice; import android.app.Activity; import android.content.Intent; import android.os.Bundle; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Intent it1 = new Intent(MainActivity.this,MsService.class); Bundle b1 = new Bundle(); b1.putString("param", "s1"); it1.putExtras(b1); Intent it2 = new Intent(MainActivity.this,MsService.class); Bundle b2 = new Bundle(); b2.putString("param", "s2"); it2.putExtras(b2); Intent it3 = new Intent(MainActivity.this,MsService.class); Bundle b3 = new Bundle(); b3.putString("param", "s3"); it3.putExtras(b3); //接着启动多次IntentService,每次启动,都会新建一个工作线程 //但始终只有一个IntentService实例 startService(it1); startService(it2); startService(it3); } }
运行范例,日志输出如下