1、今天我们来分析Service中的一个小技巧:前台服务(Forground Service)

  ----------------------------------------------------------------------------------------------------------------------------------------

  【问题】:我们都知道服务是运行在后台的,如果系统出现内存不足的情况,那么此时,系统就可能回收后代的服务,那么我们如何保证服务可以一直运行?

  【解决】:在服务中,有一个前台服务的概念,调用startForground()方法。

  我们看看官网对前台服务及startForeground()的描述:

Android实用技术(5)—— Service简析(Ⅲ)

  看了官方的解释后,我们再来看看如何使用,上代码:

Java代码
  1. public class MyService extends Service{  
  2.   
  3.   ......  
  4.   
  5.   @Override  
  6.   public void onCreate() {  
  7.     super.onCreate();  
  8.     Intent intent = new Intent(getBaseContext(), MainActivity.class);  
  9.     PendingIntent pi = PendingIntent.getActivity(getBaseContext(), 0 , intent, PendingIntent.FLAG_CANCEL_CURRENT);  
  10.     Notification no = new Notification.Builder(getBaseContext())                // 启动服务后,在前台添加一个Notification  
  11.         .setWhen(System.currentTimeMillis())  
  12.         .setSmallIcon(R.mipmap.ic_launcher)  
  13.         .setTicker("Create a front desk Service!")  
  14.         .setContentTitle("This is a front desk service")  
  15.         .setContentText("A service skill!!!")  
  16.         .setContentIntent(pi)  
  17.         .setAutoCancel(true)  
  18.         .setDefaults(Notification.DEFAULT_ALL)  
  19.         .build();  
  20.     startForeground(1, no);            
  21.     Log.d(TAG, "onCreate executed");  
  22.   }  
  23. }  

  我们再看一下官方文档:

Android实用技术(5)—— Service简析(Ⅲ)

  以上的代码是在Service的创建中添加了一个Notification,调用startForground()就可以保证:只要服务一直存在,那么在前台就会一直显示这个Notification。

  如果我们在onDestroy()中调用stopForground()方法,会销毁这个Notification,但是Service还是存活的,此时Service就会面临被System干掉的风险。

  如果直接STOP SERVICE,那么Notification和Service都会销毁。

  ----------------------------------------------------------------------------------------------------------------------------------------

  2、接下来,我们再来看一个Service的另外一个小技巧:IntentService

  【问题】:我们知道服务的代码逻辑是在主线程中执行的,如果我们在主线程中需要执行一些耗时的操作,那么很有可能出现ANR(程序暂无响应)的状况。

  这个时候,我们可以采用Android的多线程编程(小编在之前的 AsyncTask 贴中讲解过多线程,可以回顾)的方式,我们来看一段代码:

Java代码
  1. public class MyService extends Service{  
  2.   @Nullable  
  3.   @Override  
  4.   public IBinder onBind(Intent intent) {  
  5.     return null;  
  6.   }  
  7.   @Override  
  8.   public int onStartCommand(Intent intent, int flags, int startId) {  
  9.     new Thread(new Runnable() {  
  10.       @Override  
  11.       public void run() {  
  12.         // 处理具体的逻辑                     // 开启一个线程处理耗时操作  
  13.       }  
  14.     }).start();  
  15.     return super.onStartCommand(intent, flags, startId);  
  16.   }  
  17. }  

  现在,服务可以启动起来了,但是如果不调用StopService()或stopSelf()方法,服务会一直运行,现在我们修改一下代码:

Java代码
  1. public class MyService extends Service{  
  2.   @Nullable  
  3.   @Override  
  4.   public IBinder onBind(Intent intent) {  
  5.     return null;  
  6.   }  
  7.   @Override  
  8.   public int onStartCommand(Intent intent, int flags, int startId) {  
  9.     new Thread(new Runnable() {  
  10.       @Override  
  11.       public void run() {  
  12.         // 处理具体的逻辑                     // 开启一个线程处理耗时操作  
  13.         stopSelf();                         // 让服务执行完逻辑后自行停止  
  14.       }  
  15.     }).start();  
  16.     return super.onStartCommand(intent, flags, startId);  
  17.   }  
  18. }  

  上面的代码就是一个标准的Service的书写形式,主要包含两个知识点:Thread子线程的创建和stopSelf()方法的调用。

  其实,在一般的使用过程中,一部分程序员很容易忘记以上两个要点,存在遗忘,那么有没有更好的办法能够实现上面两个需求呢?

  【解决】:在Android中,专门提供了一个IntentService类(android.app.IntentService),这个类就能很好的满足我们的需求!我们直接通过代码来看:

  (1)新建一个MyIntentService类继承自IntentService,代码:

Java代码
  1. public class MyIntentService extends IntentService{  
  2.   
  3.   public MyIntentService() {  
  4.     super("MyIntentService");  
  5.   }  
  6.   
  7.   @Override  
  8.   protected void onHandleIntent(Intent intent) {  
  9.     Log.d("MyIntentService""MyIntentServiceThread id is " + Thread.currentThread().getId());  
  10.   }  
  11.   
  12.   @Override  
  13.   public void onDestroy() {  
  14.     super.onDestroy();  
  15.     Log.d("MyIntentService""onDestroy executed");  
  16.   }  
  17. }  

  以上代码做了几件事:

  1、提供了一个无参的构造方法,并且调用了父类的有参构造函数(这个就不需要我说为什么了吧);

  2、子类实现父类的onHandleIntent()抽象方法,这个方法好就好在,它是一个已经运行在子线程中的方法。也就是说,服务调用了它,那么执行的逻辑就如同Thread子线程。

  onHandleIntent = Thread().start() + stopSelf()

  3、onHandleIntent()执行完后会销毁服务?会selfStop()?接着往下看代码。

  ----------------------------------------------------------------------------------------------------------------------------------------

  (2)在xml文件中,创建一个MyIntentService服务按钮:

XML/HTML代码
  1. <Button  
  2.   android:id="@+id/start_intent_service"  
  3.   android:layout_width="match_parent"  
  4.   android:layout_height="wrap_content"  
  5.   android:text="@string/intent_service"/>  

  (3)接下来,修改MainActivity中的代码:

Java代码
  1. public class MainActivity extends Activity {  
  2.   
  3.   @Override  
  4.   protected void onCreate(Bundle savedInstanceState) {  
  5.   
  6.     super.onCreate(savedInstanceState);  
  7.     setContentView(R.layout.activity_main);  
  8.     Button startIntentService = (Button) super.findViewById(R.id.start_intent_service);  
  9.     startIntentService.setOnClickListener(new View.OnClickListener() {  
  10.   
  11.       @Override  
  12.       public void onClick(View v) {  
  13.         Log.d("MyIntentService""MainActivity Thread id is " + Thread.currentThread().getId());            // 查看主线程的id  
  14.         Intent intentService = new Intent(getBaseContext(), MyIntentService.class);                     
  15.         startService(intentService);  
  16.       }  
  17.     });  
  18.   }  
  19. }  

  (4)最后,在AndroidMainfest中注册服务:

XML/HTML代码
  1. <service android:name=".MyIntentService" />  

  【结果】:直接看一下代码执行的效果。

Android实用技术(5)—— Service简析(Ⅲ)

  从打出的LOG可以看出:

  (1)MyIntentService和MainActivity所在进程的id是不一样的;

  (2)onHandleIntent()方法在执行完逻辑后确实销毁了服务,效果等同于stopSelf()。

  从上面的分析可以看出onHandleIntent()方法确实相当的好用!

本文发布:Android开发网
本文地址:http://www.teaching4real.com/android/course/702.html
2017年8月11日
发布:鸡啄米 分类:Android开发教程 浏览: 注册送白菜网:0