9.5.2 使用 IntentServiceandroid
话说回来,在本章一开始的时候咱们就已经知道,服务中的代码都是默认运行在主线程 当中的,若是直接在服务里去处理一些耗时的逻辑,就很容易出现 ANR(Application Not Responding)的状况。
因此这个时候就须要用到 Android 多线程编程的技术了,咱们应该在服务的每一个具体的 方法里开启一个子线程,而后在这里去处理那些耗时的逻辑。所以,一个比较标准的服务就 能够写成以下形式:程序员
public class MyService extends Service {编程
@Override
public IBinder onBind(Intent intent) {
return null;
}多线程
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
new Thread(new Runnable() {
@Override
public void run() {
// 处理具体的逻辑
}
}).start();
return super.onStartCommand(intent, flags, startId);
}app
}
可是,这种服务一旦启动以后,就会一直处于运行状态,必须调用 stopService()或者 stopSelf()方法才能让服务中止下来。因此,若是想要实现让一个服务在执行完毕后自动中止 的功能,就能够这样写:异步
public class MyService extends Service {ide
@Override
public IBinder onBind(Intent intent) {
return null;
}
函数
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
new Thread(new Runnable() {
@Override
public void run() {
// 处理具体的逻辑
stopSelf();
}
}).start();
return super.onStartCommand(intent, flags, startId);
}this
}
虽然说这种写法并不复杂,可是总会有一些程序员忘记开启线程,或者忘记调用 stopSelf() 方法。为了能够简单地建立一个异步的、会自动中止的服务,Android 专门提供了一个 IntentService 类,这个类就很好地解决了前面所提到的两种尴尬,下面咱们就来看一下它的 用法。
新建一个 MyIntentService 类继承自 IntentService,代码以下所示:线程
public class MyIntentService extends IntentService {
public MyIntentService() {
super("MyIntentService"); // 调用父类的有参构造函数
}
@Override
protected void onHandleIntent(Intent intent) {
// 打印当前线程的id
Log.d("MyIntentService", "Thread id is " + Thread.currentThread(). getId());
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d("MyIntentService", "onDestroy executed");
}
}
这里首先是要提供一个无参的构造函数,而且必须在其内部调用父类的有参构造函数。
而后要在子类中去实现 onHandleIntent()这个抽象方法,在这个方法中能够去处理一些具体的 逻辑,并且不用担忧 ANR 的问题,由于这个方法已是在子线程中运行的了。这里为了证 实一下,咱们在 onHandleIntent()方法中打印了当前线程的 id。另外根据 IntentService 的特性, 这个服务在运行结束后应该是会自动中止的,因此咱们又重写了 onDestroy()方法,在这里也 打印了一行日志,以证明服务是否是中止掉了。
接下来修改 activity_main.xml 中的代码,加入一个用于启动 MyIntentService 这个服务的 按钮,以下所示:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"
android:orientation="vertical" >
……
<Button android:id="@+id/start_intent_service" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Start IntentService" />
</LinearLayout>
而后修改 MainActivity 中的代码,以下所示:
public class MainActivity extends Activity implements OnClickListener {
……
private Button startIntentService;
@Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
……
startIntentService = (Button) findViewById(R.id.start_intent_service);
startIntentService.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
……
case R.id.start_intent_service:
// 打印主线程的id
Log.d("MainActivity", "Thread id is " + Thread.currentThread().
getId());
Intent intentService = new Intent(this, MyIntentService.class);
startService(intentService);
break;
default:
break;
}
}
}
能够看到,咱们在 Start IntentService 按钮的点击事件里面去启动 MyIntentService 这个服 务,并在这里打印了一下主线程的 id,稍后用于和 IntentService 进行比对。你会发现,其实 IntentService 的用法和普通的服务没什么两样。
最后仍然不要忘记,服务都是须要在 AndroidManifest.xml 里注册的,以下所示:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.servicetest"
android:versionCode="1"
android:versionName="1.0" >
……
<application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" >
……
<service android:name=".MyIntentService"></service>
</application>
</manifest>
如今从新运行一下程序,界面如图 9.13 所示。
图 9.13
点击 Start IntentService 按钮后,观察 LogCat 中的打印日志,如图 9.14 所示。
图 9.14
能够看到,不只 MyIntentService 和 MainActivity 所在的线程 id 不同,并且 onDestroy() 方法也获得了执行,说明 MyIntentService 在运行完毕后确实自动中止了。集开启线程和自动 中止于一身,IntentService 仍是博得了很多程序员的喜好。