内容简介:同一个进程内实现接口回掉很简单,这里不做叙述,本文主要讲的是跨进程的接口回掉实现方式。有一种跨进程通信的方式就是使用AIDL,但是单纯的AIDL通信只可以实现客户端访问服务端主动获取Binder对象,如果服务端有变化无法及时通知客户端。现在可以通过跨进程的接口回掉来解决服务端发生变化通知客户端的问题。可以使用使用RemoteCallbackList来实现对创建Service,并且在service中定义RemoteCallbackList集合,实现ITestInterface.Stub,在registerCa
同一个进程内实现接口回掉很简单,这里不做叙述,本文主要讲的是跨进程的接口回掉实现方式。有一种跨进程通信的方式就是使用AIDL,但是单纯的AIDL通信只可以实现客户端访问服务端主动获取Binder对象,如果服务端有变化无法及时通知客户端。现在可以通过跨进程的接口回掉来解决服务端发生变化通知客户端的问题。
可以使用使用RemoteCallbackList来实现对 IInterface 的管理。 public class RemoteCallbackList<E extends IInterface>
首先定义两个AIDL文件:
-
ITestCallBack.aidl
interface ITestCallBack { /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ void onTagValid(in String tag); } 复制代码 -
ITestInterface.aidl 在注册和反祖册方法中,需要传入ITestCallBack的对象
interface ITestInterface { /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ boolean isTagValid(in String tag); void registerCallback(in String tag, in ITestCallBack callback); void unRegisterCallback(in String tag, in ITestCallBack callback); }复制代码
服务端:
创建Service,并且在service中定义RemoteCallbackList集合,实现ITestInterface.Stub,在registerCallback,和unRegisterCallback中,分别将ITestCallBack对象注册和反注册进RemoteCallbackList中。 RemoteCallbackList提供了获取注册进去的IInterface对象方法。
//其实RemoteCallbackList类似于 java 中{@link java.util.Observable},用来批量处理接口回调对象, //其实如果确保只有一个客户端会bind到这个服务,只需要保存一个IMyAidlInterfaceCallback即可。 //但是如果有多个,强烈推荐使用其实RemoteCallbackList public void callBack() { if (mCallBacks == null) { return; } int num = mCallBacks.beginBroadcast(); for (int i = 0; i < num; i++) { try { mCallBacks.getBroadcastItem(i).onTagValid("congratulation callback success " + tag); } catch (RemoteException e) { e.printStackTrace(); } } //结束后一定要使用finsh,否则下次执行beginBroadcast会抛出IllegalStateException异常 mCallBacks.finishBroadcast(); }复制代码
在isTagValid中可以调用callBack方法去遍历注册的接口对象, 也可以当服务端有变化时主动调用callBack方法去通知客户端,这样就实现了服务端变化主动通知客户端 。可根据实际方法修改。
在service的onBind方法中,返回ITestInterface.Stub的对象即可,等待客户端绑定服务端。
下面是服务端Service的代码:
public class TestService extends Service {
private RemoteCallbackList<ITestCallBack> mCallBacks = new RemoteCallbackList<>();
private String tag = "hy";
public TestService() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
return iTestInterface;
}
@Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
ITestInterface.Stub iTestInterface = new ITestInterface.Stub() {
@Override
public boolean isTagValid(String tag) throws RemoteException {
if (tag.equals(TestService.this.tag)) {
callBack();
return true;
}
return false;
}
@Override
public void registerCallback(String tag, ITestCallBack callback) throws RemoteException {
if (null != mCallBacks && null != callback) {
mCallBacks.register(callback);
}
}
@Override
public void unRegisterCallback(String tag, ITestCallBack callback) throws RemoteException {
if (null != mCallBacks && null != callback) {
mCallBacks.unregister(callback);
}
}
};
public void callBack() {
if (mCallBacks == null) {
return;
}
int num = mCallBacks.beginBroadcast();
for (int i = 0; i < num; i++) {
try {
mCallBacks.getBroadcastItem(i).onTagValid("congratulation callback success " + tag);
} catch (RemoteException e) {
e.printStackTrace();
}
}
mCallBacks.finishBroadcast();
}
}复制代码
客户端:
客户端首先要做的是绑定服务端,实现AIDL的通信,在客户端创建绑定按钮,解绑按钮,和主动获取信息的通信按钮。在主动获取信息的通信按钮中实现iTestInterface对象的isTagValid方法可以主动去获取服务端的信息(服务端在isTagValid方法中调用了callBack方法)。
客户端代码:
public class MainActivity extends AppCompatActivity {
private String tag = "hy";
private ITestInterface iTestInterface;
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
iTestInterface = ITestInterface.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
iTestInterface = null;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bindService();
((Button) findViewById(R.id.buttonregister)).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
iTestInterface.registerCallback(tag, new ITestCallBack.Stub() {
@Override
public void onTagValid(String tag) throws RemoteException {
Log.e("test", "registerCallback: " + tag);
}
});
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
((Button) findViewById(R.id.buttonunregister)).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
iTestInterface.unRegisterCallback(tag, new ITestCallBack.Stub() {
@Override
public void onTagValid(String tag) throws RemoteException {
}
});
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
((Button) findViewById(R.id.buttonisvalid)).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
iTestInterface.isTagValid(tag);
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
}
private void bindService() {
Intent intent = new Intent();
intent.setAction("com.example.heyang.myapplication.TestService");
intent.setPackage("com.example.heyang.myapplication");
boolean success = bindService(intent, connection, Context.BIND_AUTO_CREATE);
if (success) {
Log.e("test ", "bindService OK");
} else {
Log.e("test ", "bindService Fail");
}
}
@Override
protected void onDestroy() {
super.onDestroy();
unBindeService();
}
private void unBindeService() {
try {
unbindService(connection);
} catch (Exception e) {
e.printStackTrace();
}
}
}
复制代码
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 关于 RemoteViews 跨进程资源访问的勘误
- Shadow的跨进程设计与插件Service原理
- wukongqueue:轻量且易于使用的跨进程队列服务
- 如何在 macOS 中使用 XPC 实现跨进程通讯?
- 接口测试及常用接口测试工具
- Java中的Comparable接口和Comparator接口
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Kafka权威指南
Neha Narkhede、Gwen Shapira、Todd Palino / 薛命灯 / 人民邮电出版社 / 2017-12-26 / 69.00元
每个应用程序都会产生数据,包括日志消息、度量指标、用户活动记录、响应消息等。如何移动数据,几乎变得与数据本身一样重要。如果你是架构师、开发者或者产品工程师,同时也是Apache Kafka新手,那么这本实践指南将会帮助你成为流式平台上处理实时数据的专家。 本书由出身于LinkedIn的Kafka核心作者和一线技术人员共同执笔,详细介绍了如何部署Kafka集群、开发可靠的基于事件驱动的微服务,......一起来看看 《Kafka权威指南》 这本书的介绍吧!