Android之服务(五)IntentService的使用

Android之服务(五)IntentService的使用

一,简介

服务中的代码都是默认运行在主线程
当中的,如果直接在服务里去处理一些耗时的逻辑,就很容易出现 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);
}
}

但是,这种服务一旦启动之后,就会一直处于运行状态,必须调用 stopService()或者
stopSelf()方法才能让服务停止下来。所以,如果想要实现让一个服务在执行完毕后自动停止
的功能,就可以这样写:

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() {
// 处理具体的逻辑
stopSelf();
}
}).start();
return super.onStartCommand(intent, flags, startId);
}
}

虽说这种写法并不复杂, 但是总会有一些程序员忘记开启线程, 或者忘记调用 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>

现在重新运行一下程序,界面如图所示。


点击 Start IntentService 按钮后,观察 LogCat 中的打印日志,如图所示。


可以看到, 不仅 MyIntentService 和 MainActivity 所在的线程 id 不一样, 而且 onDestroy()
方法也得到了执行, 说明 MyIntentService 在运行完毕后确实自动停止了。 集开启线程和自动
停止于一身,IntentService 还是博得了不少程序员的喜爱。





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值