• Android菜鸟的成长笔记(20)——IntentService


    前面介绍的Service在官方文档介绍中说Service存在着如下两个问题:

    1.A Service is not a separate process. The Service object itself does not imply it is running in its own process; unless otherwise specified, it runs in the same process as the application it is part of.

    2.A Service is not a thread. It is not a means itself to do work off of the main thread (to avoid Application Not Responding errors).

    1、Service不会专门启动一条单独的进程,Service与它所在的应用在同一个进程中。

    2、Service不是专门一条新的线程,因此不能再Service中直接处理耗时任务。

    如果开发者在Service中处理耗时任务,建议在Service中另外启动一条新的线程来处理耗时的任务,可能有的朋友就会问:“既然在Service中处理耗时任务需要启动新线程,为什么我们不直接在Activity中开启一个新线程,而要使用Service呢?”

    其实这种在Activity中直接启动一个线程来实现对有些业务逻辑是非常不可靠的,比如:用户使用BroadcastReceiver来启动一个新线程,BroadcastReceiver的生命周期非常短,这样就可能存在这样的问题,在子线程还没有结束的情况下,BroadcastReceiver已经结束了,或者用户在Activity中启动一个新线程后直接退出,此时它们所在的进程就变成了空进程(没有任何活动组件的进程),系统需要内存时可能会优先终止该进程。如果宿主进程被终止,那么该进程内的所有子线程也会被终止,这样就有可能导致一些严重错误。

    IntentService是Service的子类,所以它比Service增加了额外的功能,它正好弥补了Service的上述两点不足:IntentService将会使用队列来管理请求Intent,每当客户端代码通过Intent请求启动IntentService时,IntentService会将该Intent加入队列中,然后开启一条新的worker线程来处理该Intent.对于异步的startService()请求,IntentService会按次序依次处理队列中的Intent,该线程保证同一时刻只处理一个Intent.由于IntentService使用新的worker线程处理Intent请求,因此IntentService不会阻塞主线程,所以IntentService就可以处理耗时任务。

    IntentService有如下特征:

    1、会创建单独的worker线程来处理所有的Intent请求。

    2、会创建单独的worker线程来处理onHandleIntent()方法实现的代码。

    3、所有请求处理完成后,IntentService会自动停止,因此开发者无须调用stopSelf()方法

    4、为Service的onBind()方法提供了默认的实现,默认实现的onBind()方法返回null

    5、为Service的onStartCommand()方法提供了默认实现,该实现会将请求的Intent添加到队列中。

    从上面的特点中可以看出来,扩展的IntentService实现Service无须重写onBind()方法和onStartCommand()方法,只要重写onHandleIntent()方法即可。

    下面通过一个具体例子来说明IntentService和Service的区别:

    (1)继承自Service的MyService类

    package com.example.testservice;
    
    import android.app.Service;
    import android.content.Intent;
    import android.os.IBinder;
    
    public class MyService extends Service{
    
    	@Override
    	public IBinder onBind(Intent intent) {
    		
    		return null;
    	}
    
    	@Override
    	public int onStartCommand(Intent intent, int flags, int startId) {
    		//该方法内可以执行耗时任务,比如下载文件等
    		long endTime = System.currentTimeMillis() + 20 * 1000;
    		System.out.println("onStart");
    		while(System.currentTimeMillis() < endTime){
    			synchronized (this) {
    				try {
    					wait(endTime - System.currentTimeMillis());
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    			}
    		}
    		System.out.println("--耗时任务执行完毕--");
    		return START_STICKY;
    	}
    }
    

    读者可能会注意到onStartCommand方法最后的返回值我设置成了START_STICKY,有关返回值的详细设置及含义将在下一篇文章中介绍。

    执行结果


    可以看到在Service中执行耗时任务程序的主UI会被阻塞,出现ANR异常。

    (2)继承自IntentService的MyIntentService类

    package com.example.testservice;
    
    import android.app.IntentService;
    import android.content.Intent;
    
    public class MyIntentService extends IntentService{
    
    	public MyIntentService(){
    		super("MyIntentService");
    	}
    
    	@Override
    	protected void onHandleIntent(Intent arg0) {
    		//该方法内可以执行耗时任务,比如下载文件等
    		long endTime = System.currentTimeMillis() + 20 * 1000;
    		System.out.println("onStart");
    		while(System.currentTimeMillis() < endTime){
    			synchronized (this) {
    				try {
    					wait(endTime - System.currentTimeMillis());
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    			}
    		}
    		System.out.println("--耗时任务执行完毕--");
    	}
    }
    

    执行结果:




  • 相关阅读:
    图的深度优先遍历(邻接表,递归,非递归)
    图的深度优先遍历(邻接矩阵,递归,非递归)
    【转】C语言邻接表的实现
    图的存储
    堆排序_C实现
    快排_C实现
    交换二叉树中所有结点的左右子树的位置
    二叉树层次遍历_判断结点所属层次
    二叉树_非递归先中后序_递归非递归求深度
    二叉树非递归遍历(前、中、后)
  • 原文地址:https://www.cnblogs.com/lanzhi/p/6469461.html
Copyright © 2020-2023  润新知