android进程间对象传递,android的Bound Service----讲述进程间通信

创建Bound Service

想要给服务提供绑定,你就要实现onBind()回调方法。这个方法返回一个IBinder的对象,它用于定义应用与service进行交互的编程接口。有三种方法可以定义这个接口:

Extending theBinder

class:如果你的服务是给你自己的应用程序去用,那么你应该继承Binder类,创建属于你自己的接口并接收onBind()方法的返回值。Activity接收Binder,然后直接可以通过公共方法使用这个Binder而不用实现Binder甚至是Service。这个服务当它在后台运行,且只给你运行的时候使用这个方法是最好的了,但是如果你的服务不是私有的,而是让其他的应用程序也会用到,那么你最好还是不要选择这个方法。因为它跨越了不同的进程。

Using a

Messenger:如果你需要你的接口要在不同的进程中使用,你就应该使用Messenger为服务创建接口。在这种方式中,service定义Hander用于解决不同类型的Message对象。Handler是Messenger的基础,它可以分享IBinder对象给client,允许类通过Message对象发送命令到service。除此之外,你可以定义属于你自己的Messenger,这样service就能把消息发送回来了。

这个方式是实现IPC最简单的一种方式,因为Messenger

quenes是一种单线程的东西而且你设计你服务的时候不用考虑线程安全问题。

Using AIDL:这个问题我们在AIDL那篇博客详细的说过,详细的内容请看那篇关于AIDL的叙述,这里就不赘述了。

(注:大部分的应用程序不应该使用AIDL创建bound

service,因为它可能需要你有多线程并发的解决能力,同时,它也会使得程序变得很复杂)

继承Binder类

如果你的服务只是使用自己的应用程序而且不需要通过进程来操作其他应用程序,那么你就可以实现你自己的Binder类,在serivce中直接让类调用它的公共方法。

(注:这个情况只能是在应用程序和服务都在一个线程之中,尤其是在前台的service操作后台的播放动作这样的音乐应用上编辑最为有效果)

你只需要做以下几个步骤:

1. 在你的service中创建一个Binder的实例化对象,或者:

·包含一个其他类可以调用的方法;

·返回当前服务的实例,这样有公共方法的类就能够调用它;

·返回一个其他类创建服务的实例,这样有公共方法的类就能够调用它;

2. 从onBind()回调方法中返回Binder类的实例化对象;

3. 在类中,接收从onServiceConntected()回调方法的Binder然后通过使用提供的方法调用bound

service;

(注:为什么非要让serivce和类都要在一个应用程序中,就是因为这样做的话类就能正确的收到传递过来的返回对象。Service和类也一定要在相同的进程中,因为这个方法不提供分发数据到其他进程的机制)

例如,下面这个方法就是通过Binder实现的与service连接

public class LocalServiceextends Service {

// Binder given to

clients

private final IBinder mBinder

= new LocalBinder();

// Random number

generator

private final Random

mGenerator = new Random();

public class LocalBinder

extends Binder {

LocalService getService() {

// Return

this instance ofLocalService so clients can call public

methods

return

LocalService.this;

}

}

@Override

public IBinder onBind(Intent

intent) {

return mBinder;

}

public int getRandomNumber()

{

return

mGenerator.nextInt(100);

}

}

LocalBinder给类提供getService()方法用于检索当前LocalService的实例。这允许类调用服务中公共的方法。例如,该类service中调用getRandomNumber()方法。

public class BindingActivityextends Activity {

LocalService mService;

boolean mBound = false;

@Override

protected void

onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

}

@Override

protected void onStart()

{

super.onStart();

// Bind to LocalService

Intent intent = new Intent(this,

LocalService.class);

bindService(intent, mConnection,

Context.BIND_AUTO_CREATE);

}

@Override

protected void onStop()

{

super.onStop();

// Unbind from the service

if (mBound) {

unbindService(mConnection);

mBound =

false;

}

}

public void

onButtonClick(View v) {

if (mBound) {

// Call a

method from theLocalService.

//

However, if this call weresomething that might hang, then this

request should

// occur

in a separate thread toavoid slowing down the activity

performance.

int num =

mService.getRandomNumber();

Toast.makeText(this, "number:" + num,

Toast.LENGTH_SHORT).show();

}

}

private ServiceConnection

mConnection = new ServiceConnection() {

@Override

public void

onServiceConnected(ComponentNameclassName,

IBinder service) {

// We've

bound to LocalService, castthe IBinder and get LocalService

instance

LocalBinder binder = (LocalBinder)service;

mService =

binder.getService();

mBound =

true;

}

@Override

public void

onServiceDisconnected(ComponentNamearg0) {

mBound =

false;

}

};

}

上面是一个简单的例子介绍bound service的使用方法,下面将会再进行详细的讨论。

Usinga Messenger

如果你需要使用服务交流远程的进程,那么你就可以使用Messenger为服务提供这个接口,它使你最简单的实现进程间通信。

下面说一说如何使用Messenger:

·service实现了Handler类用于接收从其他类发来的回调请求;

·Handler用于创建Messenger对象;

·Messenger创建IBinder类用于接收onBind()方法中发送过来的返回值;

·某个类使用IBinder类来实例化Messenger,用于发送Message对象给service;

·service在Handler中接收每一个Message,在handleMessage()方法中;

在这种情况中,没有类调用方法给service。取而代之的是,类传递“messages”然后service用它的Handler接收。

public class MessengerServiceextends Service {

static final int

MSG_SAY_HELLO = 1;

class IncomingHandler extends

Handler {

@Override

public void handleMessage(Message msg) {

switch

(msg.what) {

case MSG_SAY_HELLO:

Toast.makeText(getApplicationContext(),"hello!",

Toast.LENGTH_SHORT).show();

break;

default:

super.handleMessage(msg);

}

}

}

final Messenger mMessenger =

new Messenger(new IncomingHandler());

@Override

public IBinder onBind(Intent

intent) {

Toast.makeText(getApplicationContext(),

"binding",Toast.LENGTH_SHORT).show();

return mMessenger.getBinder();

}

}

值得注意的是,在Handler中使用handleMessage()方法接收即将到来的Message,是使用what关键字的;

你只要在类中创建一个基于被service返回的IBinder的Messenger然后通过send()方法发送一条message。例如,下面这个例子就是绑定到service上然后给服务发送MSG_SAY_HELLO消息;

public class ActivityMessengerextendsActivity {

Messenger mService =

null;

boolean mBound;

private ServiceConnection

mConnection = new ServiceConnection() {

public void

onServiceConnected(ComponentNameclassName, IBinder service) {

// This is

called when the connectionwith the service has been

//

established, giving us the objectwe can use to

//

interact with the service. We are communicating

with the

// service

using a Messenger, so herewe get a client-side

//

representation of that from theraw IBinder object.

mService =

new Messenger(service);

mBound =

true;

}

public void

onServiceDisconnected(ComponentNameclassName) {

// This is

called when the connectionwith the service has been

//

unexpectedly disconnected -- thatis, its process crashed.

mService =

null;

mBound =

false;

}

};

public void sayHello(View v)

{

if (!mBound) return;

// Create and send a message to the service,

usinga supported 'what' value

Message msg = Message.obtain(null,

MessengerService.MSG_SAY_HELLO,0, 0);

try {

mService.send(msg);

} catch (RemoteException e) {

e.printStackTrace();

}

}

@Override

protected void

onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

}

@Override

protected void onStart()

{

super.onStart();

// Bind to the service

bindService(new Intent(this,

MessengerService.class),mConnection,

Context.BIND_AUTO_CREATE);

}

@Override

protected void onStop()

{

super.onStop();

// Unbind from the service

if (mBound) {

unbindService(mConnection);

mBound =

false;

}

}

}

值得注意的是,这个例子中没有展示service如何对类响应。如果你想让service对其进行响应,那你需要在你的类中创建一个Messenger对象,然后当该类接收到onServiceConnected()回调方法的值时,它会给service发送一条Message,这条Message包含该类的Messenger,这个Messenger的类型是send()方法中的replyTo参数。

此外,你还需要好好看看MessengerService.java和MessengerServiceActivities.java两个类

Binding to aService

类可以通过调用bindService()方法绑定到service上,然后android系统调用service的onBind()方法,返回一个IBinder类的实例化对象用于与服务交互。

这个绑定是异步的。bindService()会立刻返回而且不会把IBinder返回给类。为了接收这个IBinder,类必须创建一个ServiceConnection的实例化对象然后把它传递给bindService()。然后ServiceConnection包含了一个系统调用传送IBinder的回调方法。

(注:只有activites、services、content

providers可以绑定服务,你不能使用contentprovider绑定服务)

所以,你的类要想绑定service,你一定要:

1. 实现ServiceConnection

你实现的时候一定要重载以下两个回调方法:

OnServiceConnected():系统调用这个方法来传递被服务的onBind()方法返回的IBinder

onServiceDisconnected():当正在连接的服务发生异常时系统调用这个方法

2. 调用bindService()方法,传递Serviceconnection的实现实例

3. 当系统调用你的onServiceConnected()回调方法,你可以使用你定义的接口的方法开始调用服务了。

4. 断开与service的连接,调用unbindService()方法。

例如,下面这段代码就是通过继承了Binder类把该类与服务连接,所以你必须要传递一个IBinder的返回值给LocalService类然后实例化LocalService

LocalServicemService;

private ServiceConnection mConnection = new ServiceConnection()

{

// Called when the connection

with the service is established

public void

onServiceConnected(ComponentName className, IBinderservice) {

// Because we have bound to an explicit

// service that is running in our own process,

wecan

// cast its IBinder to a concrete class

anddirectly access it.

LocalBinder binder = (LocalBinder)

service;

mService = binder.getService();

mBound = true;

}

// Called when the connection

with the service disconnectsunexpectedly

public void

onServiceDisconnected(ComponentName className) {

Log.e(TAG, "onServiceDisconnected");

mBound = false;

}

};

使用Serviceconnection,类可以绑定到服务上通过bindService,例如:

Intent intent = newIntent(this, LocalService.class);

bindService(intent, mConnection, Context.BIND_AUTO_CREATE);

·bindService的第一个参数是一个intent

·第二个参数时Serviceconnection对象

·第三个参数是一个声明,通常是BIND_AUTO_CREATE,为了创建不存在的serivce。

额外的一些注意事项

·你可能经常遇到DeadObjectException,就是当远程连接时发生中断会出现的异常

·多个进程,对象都被当成了引用

·如果你想要你的activity接受回应当它在后台停止的时候,那么你就绑定onCreate()而在onDestory()中释放绑定,这就意味着你的activity需要在整个运行期一直使用服务,所以如果service在另一个进程中,你就会增加进程的负重从而出现被系统杀掉的风险;

(注:你不应该经常绑定和取消绑定在你activty调用onResume()和onPause()方法)

管理Bound Service的生命周期:

当service没有绑定时,系统就会销毁它。这样,如果service纯粹是一个纯粹的Bound

Service,你不必管理服务的生命周期。

然而,如果你选择实现onStartCommand()回调方法,然后你必须明确的停止service,因为这个服务被认为已经开启了。在这种情况下,service会一直运行直到service停止自己或者调用stopService(),不管它是否绑定到了任何类。

除此之外,如果你的service已经开启了并且接受binging,然后当系统调用你的onUnbind()方法,你就可以返回true如果想要接受onRebind()的调用。OnRebind()返回void,但是类依然接收IBinder在它的onServiceConnected()回调方法。上面可能说的有点乱,下面看看这个图吧:

a4c26d1e5885305701be709a3d33442f.png

笔者个人理解:通过对bound

Service的学习,这样就会发现,我们完全可以通过里面的Messenger去实现,接下来会做一个通过Bound

Service

实现的Demo。本人个人翻译能力有限,如有不足,欢迎斧正。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值