Android开发之Service学习笔记

来源:互联网 发布:hadoop2.4.1源码下载 编辑:程序博客网 时间:2024/05/29 04:00

断断续续学Android也有1年多了,内心一直摇摆不定,犹豫着要不要往这方向发展下去。因为自己是C++出身的,对语言这方面内心总有那么点偏见;经过1年多的徘徊,总算认清了事实,开发你总得基于某一平台吧,而市面上基于纯C++开发的太少了(主要是自己能力不够);自己身边目标明确的同事,他们成长的速度快得惊人,看着就很是嫉妒,所以啊,我也必须找准目标,然后锲而不舍。先从Android应用开发入手,慢慢地再往系统层研究。从现在开始要养成写博客的习惯,记录学习的点滴,也见证自己的成长。

唠叨了这么多,也该进入正题了。第一篇博客,我想记录一下Android的四大组件之一Service。对于Service,一开始我以为就是一线程,只不过是Android的开发团队给它起了个响亮的别名,但事实上并不是,它依然是在主线程中执行它的生命周期;既然不是线程,也就是说不能在它的生命周期里执行耗时的操作,那它到底有什么用呢?等我们分析完就知道原因啦!

Service它有两种启动方式:

1、Started:通过调用startService()来启动Service;

2、Bound:通过调用bindService()来启动Service;bound服务提供了一个客户端/服务器接口,实现组件与服务间通讯,还可以实现进程间通讯(IPC)。多个组件可以同时与一个服务绑定,不过需要等到所有的组件都解绑了后,服务才会被销毁。


对于startService这种启动方式,第一次调用的时候会走一下onCreate,再走onStartCommand方法,之后再次startService,只会走onStartCommand,一般这种启动方式主要用来处理一些耗时的操作,如网络资源的下载;常见的写法是在onStartCommand中启动一线程来执行耗时操作:

@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {new Thread(new Runnable() {          @Override          public void run() {              // do something here        }      }).start();return super.onStartCommand(intent, flags, startId);}

服务一启动之后就一直保持运行的状态,直到stopService()stopSelf()方法被调用才消亡。无论调用多少次startService(),只要调用1次stopService()或stopSelf()方法,服务就会停止。对于这种方式启动的服务,基本与组件没什么联系了,默默地干活,默默地消亡。


为了实现组件与服务间能够通讯,需要使用bindService启动服务;这种方式我们会用到onBind()方法,获取Binder对象;

public class MyService extends Service {    private final static String TAG = "MyService";    private MyBinder mBinder = new MyBinder();    public class MyBinder extends Binder {        public void doSomething() {            new Thread(new Runnable() {                @Override                public void run() {                    // do something here                    Log.i(TAG, "doSomething");                }            }).start();        }    }    @Override    public IBinder onBind(Intent intent) {        return mBinder;    }}

这样我们就可以在组件中通过ServiceConnection的回调来实现通讯了;

private ServiceConnection mConn = new ServiceConnection() {    @Override    public void onServiceConnected(ComponentName name, IBinder service) {         ((MyService.MyBinder)service).doSomething();    }    @Override    public void onServiceDisconnected(ComponentName name) {    }};
通过以下代码启动服务:

Intent intent = new Intent(MainActivity.this, MyService.class);bindService(intent, mConn, BIND_AUTO_CREATE);
解邦也很简单:

unbindService(mConn);

以下是两种方式的生命周期流程图:

最后,我们还要在AndroidManifest.xml中添加Service的注册。

<service android:name=".MyService" />

现在我们有个疑问,Service既通过startService启动,又通过bindService绑定,这是完全有可能的,那它怎样才能销毁呢(走onDestroy()方法)?因为服务一启动或被绑定后,它就一直处于运行状态,所以必须同时调用stopService()和unbindService()方法,才能销毁该服务。


目前为止,我们都是在自己进程内进行通讯,现修改一下AndroidManifest.xml:

<service android:name=".MyService" android:process=":remote"/>

使服务在另一进程中启动,但我们会发现,执行bindService后程序会崩溃,这是因为组件和服务在不同进程,它们不能用传统的方式建立连接。这种情况下我们就需要用到AIDL(Android Interface Definition Language)来进行跨进程通讯了(IPC)。

现添加一aidl文件IMyAidlInterface.aidl:

// IMyAidlInterface.aidlpackage com.example.service;// Declare any non-default types here with import statementsinterface IMyAidlInterface {    void doSomething();}
修改一下原来MyService.java的代码,将之前自定义Binder类中的操作移到下面:

IMyAidlInterface.Stub mBinder = new IMyAidlInterface.Stub() {    @Override    public void doSomething() throws RemoteException {        // do something here        Log.i(TAG, "doSomething");    }};
在我们的onBind()方法中返回上面的mBinder对象。

我们组件中建立连接的回调接口也要修改一下:

private ServiceConnection mConn = new ServiceConnection() {    @Override    public void onServiceConnected(ComponentName name, IBinder service) {        try {            IMyAidlInterface.Stub.asInterface(service).doSomething();        } catch (RemoteException e) {            e.printStackTrace();        }    }    @Override    public void onServiceDisconnected(ComponentName name) {    }};
到这里我们的服务就可以正常的跨进程与我们的组件进行通讯了。

目前为止我们都只是在单个应用内通讯,为了实现不同应用间可以建立联系,我们可以将服务端的aidl接口(文件包名必须完全一样)提供给客户端调用,达到以上那种跨进程间通讯。


讲了那么多关于Service的知识,那么它到底有什么用呢?Service没有界面,它可以后台运行(也可以前台,通过startForeground),另一个作用就是我们上面一直在讲的跨进程通讯。

好啦!第一次写博客,就先写这么多吧!

0 0
原创粉丝点击