服务的基本用法-3

我们都知道,服务一般都是在后台运行的,一直以来都是默默的在后台工作着。但是有一个问题,就是由于服务的系统优先级比较低,当手机的系统出现内存不足的情况时,就有可能回收掉正在后台运行的服务。此时如果你想让你的服务能够一直保持运行状态的话,我们就可以来使用一种叫做前台服务的东东。
前台服务和普通服务(后台服务)的最大区别在于它有一个正在运行的图标在系统的状态栏显示,下拉状态栏后可以看到详细的信息,类似于通知的效果。那么接下来我们就来看一下如何实现前台服务的效果。

首先,我们在前两节所学服务的基础上,继续编辑MyService服务的代码(如果忘记了,可以复习一下前面讲的服务内容),如下所示:

@Override
public void onCreate(){
    super.onCreate();
    Log.d("MyService", "onCreate executed");
    Intent intent = new Intent(this, MainActivity.class);
    PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 0);
    Notification notification = new NotificationCompat.Builder(this)
            .setContentTitle("前台服务")
            .setContentText("不会因为系统内存不足被回收")
            .setWhen(System.currentTimeMillis())
            .setSmallIcon(R.mipmap.ic_launcher)
            .setLargeIcon(BitmapFactory.decodeResource(getResources(),
                    R.mipmap.ic_launcher))
            .setContentIntent(pi)
            .build();
    startForeground(1,notification); //显示通知栏
}


在这里,我们只是在onCreate()方法里面加了一段代码,这段代码和创建通知的方法非常相似(关于通知的内容,后面会讲述),只不过我们时通过startForeground()方法来把通知显示出来的。而通知栏的只是点则是通过NotificationManager来显示的。现在重新运行一下程序,点击Start Service(开启服务)或者Bind Service(绑定服务)按钮,就会以前台服务的模式启动了,并且在系统通知栏会显示一个图标和信息。如下图:

在这个图里面,我们点击图中按钮,发现手机顶部的状态栏出现了一个安卓小图标,没错!这就代表着MyService服务以前台服务的方式创建了,接着下拉状态栏,我们会看到具体的信息,如下图。





这样,我们成功创建并启动了前台服务,服务也就不会因为系统内存不足而被回收了。前台服务的用法其实很简单,只要我们掌握了通知的用法就可以了。

但是一直以来有一个问题,不知道各位是否还记得。服务中的代码都是默认运行在主线程当中的,如果直接在服务里去处理一些耗时的逻辑,就很容易出现ANR(应用无响应)的情况。那么怎么避免这个问题呢?不要着急,这个时候就到了Android多线程编程大展身手的时候了。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的情况,因为这个方法已经在子线程中运行了。最后我们重写了onDestroy()方法,用来在服务结束运行后自动停止。接下来,我们来编辑一下布局文件。
<Button
    android:id="@+id/start_intent_service"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="Start IntentService"
    android:textAllCaps="false" />

就是加了一个点击按钮,用来启动MyIntentService这个服务。然后我们再编辑一下MainActivity中的代码逻辑,如下所示:

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;

如上说是,我们首先还是获取按钮的实例,并且为按钮添加一个点击事件,这里不再阐述。然后在点击事件里面,我们显示打印了一下线程ID,用来判断主线程中的运行情况。然后去启动MyIntentService这个服务。最后不要忘了在AndroidManifest.xml中注册这个服务。现在运行程序,点击Start IntentService按钮后,观察logcat中打印的日志,如图所示:





我们看到,MainActivity和MyIntentService所在的线程ID不一样,并且onDestroy()方法也得到了制定,说明在MyIntentService服务运行结束后确实自动停止了。这样,集开启线程和自动停止于一身,IntentService的功能在这里发挥到了最大。

好了,到这里,关于服务的基本用法,就讲的差不多了。后面大家可以再通过具体的练习,来巩固理解。

























  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值