Android四大组件之Service

来源:互联网 发布:h.323端口 编辑:程序博客网 时间:2024/05/23 16:17

一、Service是什么

相信做android开发的同学们都或多或少的接触过Service,作为Android的四大组件之一,service主要使用在处理后台任务(即不依赖于UI界面),或者去执行一个需要长期运行的任务,譬如说播放音乐,下载等都可以放在service中做。service相对于activity来说,最大了区别在于,它处于后台运行,没有UI界面,当然你也可以将他与Notification一起使用,将service从后台转到前台。

二、Service的生命周期

Service和Activity一样具有生命周期。首先我们来看看Service的使用方法。

//service需要在AndroidManifest.xml中注册public class AidlService extends Service{    public AidlService()    {    }    @Override    public IBinder onBind(Intent intent)    {        return null;    }    @Override    public void onCreate()    {        super.onCreate();    }    @Override    public int onStartCommand(Intent intent, int flags, int startId)    {        return super.onStartCommand(intent, flags, startId);    }    @Override    public void onDestroy()    {        super.onDestroy();    }    @Override    public boolean onUnbind(Intent intent)    {        return super.onUnbind(intent);    }}

在上述的代码中,我们发现了与Activity生命周期相似的函数。毫无疑问,这就是Service的生命周期。其实Service的生命周期函数没有Activity与Fragment那么多。由上面代码可知主要包括onCreate,onStartCommand,onBind,onUnbind,onDestroy。那么是不是每一次启动Service都会执行这几个周期函数呢?其实不是,这与如何启动service有关。
Context.startService()
startService的作用是启动一个service,启动后这个service与当前的调用者(Activity,BroadCast等)没有关联,调用者将不知道service的运行情况,即使当前调用者退出,service也可以一直运行下去,直到调用stopServiceS(),或者stopSelf()函数。内存不足,也将优先回收后台进程。这种情况下,生命周期的执行步骤是onCreate()–onStartCommand()–onDestroy()。但如果启动的这个Servicer已经存在了,那么将不会执行onCreate()函数,只会执行onStartCommand()。

 Intent intent=new Intent(MainActivity.this,AidlService.class); startService(intent);

startService

Context.bindService()
bindService()如它的名字来说是将调用者与服务绑定在一起,当调用者退出时,绑定的Service也将跟着销毁。因为调用者与服务绑定在一块,因此调用者可以知道服务的运行情况,并且能够与Service进行通信。这时候生命周期的执行为onCreate()–onBind()–onUnbind–onDestroy()。如果service以及存在,上述生命周期都不会再执行。
而且bindService也可以进行跨进程的通信。通过AIDL远程调用另一个进程中的Service,并得到另一个Service中的的信息。

Intent intent=new Intent(MainActivity.this,AidlService.class);//bindService()一共有三个参数,第一个为Intent,第二个是ServiceConnection,这个需要自己创建,重写他的onServiceConnected()方法和onServiceDisconnected()方法,在onServiceConnected()函数中将得到service中onBindi函数中返回的IBinder,通过这个来与Service进行通信。第三个参数为标志位。bindService(intent,mServiceConnection,BIND_AUTO_CREATE);private ServiceConnection mServiceConnection=new ServiceConnection()    {        @Override        public void onServiceConnected(ComponentName name, IBinder service)        {        }        @Override        public void onServiceDisconnected(ComponentName name)        {        }    };

注意:如果你先startService再bindService或者先bindService再startService。那么单独的调用stopService和unbindService都将不会将service销毁,只用两个同时调用才能够销毁service。

三、对Service的误解

很多时候有人会想,同样是用来执行后台任务,同样是用来执行耗时任务,那么Service与Thread是不是一样呢?什么时候选择Service,什么时候又选择Thread呢?其实Service与Thread没有关系,Service更像Activity,因为Service与Activity都是运行在主线程中的,而Thread是重新开启一个子线程。而且注意!!!在service中不能够执行耗时的操作,如果超过20秒,将会报ANR。看到ANR是不是很熟悉,没错在Activity中如果执行耗时任务也会出现ANR。因此在Service的使用时一般会结合Thread一起使用,这样只要service存在那么线程也将运行,而且service不受Activity的销毁的影响,保证了耗时任务执行成功。

四、IntentService的使用

如果每次使用Service都去新创建一个Thread执行耗时任务,这样难免有些愚蠢,并且Thread与Service的通信也需要自己来完成。Android为我们提供了一个叫IntentService的类。它继承了Service,并且在内部包含了Thread和Handler。用户可以直接使用这个类来完成耗时的操作。
如何使用IntentService

public class MyIntentService extends IntentService{    public MyIntentService()    {        super("MyIntentService");    }    @Override    public void onCreate()    {        super.onCreate();    }    @Override    public int onStartCommand(@Nullable Intent intent, int flags, int startId)    {        return super.onStartCommand(intent, flags, startId);    }    @Override    public void onDestroy()    {        super.onDestroy();    }    @Override    protected void onHandleIntent(Intent intent)    {        //执行耗时操作,该方法运行在工作线程中,而不是在主线程中。        //执行网络操作等。    }}

由上面代码可以看到比service多了一个 onHandleIntent()方法。这个方法就是用来执行耗时操作的地方。它不是运行在主线程中,所以不会造成ANR。值得注意的是IntentService在执行完onHandleIntent()函数中的代码后,intentService将自己销毁掉自己,不会像service一样需要手动结束,不会一直运行下去。

其实查看IntentService源码,你会发现里面也只是运用了Thread与Handler。

 private final class ServiceHandler extends Handler {        public ServiceHandler(Looper looper) {            super(looper);        }        @Override        public void handleMessage(Message msg) {            onHandleIntent((Intent)msg.obj);            stopSelf(msg.arg1);        }    }public void onCreate() {        super.onCreate();        //HandlerThread是一个Thread,在它的run方法中,声明了一个Looper。        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");        //线程开启        thread.start();        //将service中的looper赋值给ServiceHandler,因此ServiceHandler在发出Message后,会在    HandlerThread的run方法中取出消息。而重写的ServiceHandler的handleMessage方法,将会得到执行。而且我们发现ServiceHandler的handleMessage中有一个 onHandleIntent((Intent)msg.obj);这便是需要我们在继承IntentService时重写的。        mServiceLooper = thread.getLooper();        mServiceHandler = new ServiceHandler(mServiceLooper);    }    @Override    public void onStart(@Nullable Intent intent, int startId) {        //发送Message后,将会在HandlerThread的run方法中取出。        Message msg = mServiceHandler.obtainMessage();        msg.arg1 = startId;        msg.obj = intent;        mServiceHandler.sendMessage(msg);    }

如果不是很明白IntentService的工作方式,建议先了解一下Handler机制。

五、结语

service在android开发中十分重要,我对它的理解其实也停留在很粗浅的层面。希望读者有什么观点,或者文章有什么错误,欢迎指正。