Android跨进程通信,rxjava面试题 icode9
作者:互联网
Messager
底层也有利用封装AIDL来建立的,所以选用icode9的方法和AIDL基本类似。
1.在服务端进程Service中建立Messenger icode9对象,用来发送用户端发来的Message数据,和获得用户端Messenger对象,并给用户端发Message数据。 2.创建客户端Messenger对象,用来接收服务端数据。 3.客户端绑定服务端服务,并获取服务端Messenger对象,用来给服务端发Message数据。 4.通过服务端Messenger发消息,将用户端Messenger对象,添加到Message.replyTo。
public class MsgerService extends Service { private Messenger mServerMessenger = new Messenger(new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg);
// 接收客户端发回来的消息 switch (msg.what) { case 1000:
Toast.makeText(getBaseContext(), “” + msg.arg1, Toast.LENGTH_SHORT).show();
Message cMsg = Message.obtain(); cMsg.what = msg.what; Bundle bundle = new Bundle(); bundle.putString(“name”, “Jim”); cMsg.obj = bundle;
// 获取客户端的Messenger对象,需要用户端在接收消息时设置 Messenger cMsger = msg.replyTo; try { // 给客户端发送消息 cMsger.send(cMsg); } catch (RemoteException e) { e.printStackTrace(); } break; } } }); @Nullable @Override public IBinder onBind(Intent intent) { return mServerMessenger.getBinder(); } }
public class ClientActivity extends Activity { private TextView mNameTxt;
/**
客户端Messenger对象,用来接收 icode9 服务端数据 */ private Messenger mClientMessenger = new Messenger(new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { case 1000: // 接收服务端数据 Bundle bundle = (Bundle) msg.obj; mNameTxt.setText(bundle.getString(“name”)); break; } } });
/**
服务端Messenger对象,建立连接时获得,用来给服务端发消息 */ private Messenger mServerMessenger; private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { // 获取服务端Messenger对象 mServerMessenger = new Messenger(service); }
@Override public void onServiceDisconnected(ComponentName name) { mServerMessenger = null; } };
@Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.fragment_common);
mNameTxt = (TextView) findViewById(R.id.name);
// 绑定远端服务 Intent intent = new Intent(this, MsgerService.class); bindService(intent, mConnection, BIND_AUTO_CREATE);
findViewById(R.id.bind).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) {
int number = (int) (Math.random() * 100); Message msg = Message.obtain(); msg.what = 1000; msg.arg1 = number; msg.replyTo = mClientMessenger;
// 给服务端发送消息 if (mServer
《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
Messenger != null) { try { mServerMessenger.send(msg); } catch (RemoteException e) { e.printStackTrace(); } } } }); } }
AIDL
AIDL(Android Interface Definition Language)指的就是接口定义语言,通过它可以让用户端与服务端在进程间使用一同认可的编程接口来进行传输AIDL使用的方法相对较差,主要总结为三个几乎步骤:
创建AIDL接口 根据AIDL创建远程Service服务 绑定远程Service服务
(1)创建AIDL接口 定义aidl接口程序 在Android Studio icode9中尚未集成好了这个文件的创建模式,直接右击工程,点击New -> AIDL -> AIDL File,然后输入端口的名称就好,将会在src/main目录下构建一个与java目录平级,且上面的包名与java目录里的包名一致,后缀为.aidl的文件
// Declare any non-default types here with import statements
interface IMyAidlTest { /**
Demonstrates some basic types that you can use as parameters and return values in AIDL. */ void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString); }
上面这个文件是Android Studio自动构建的模板文件,里面的basicTypes方法不需要使用到可以删掉。 AIDL对数据方式的鼓励以及Java中的全部几乎数据方式,还有String、CharSequence、List、Map。
自定义AIDL的数据方式
在AIDL提供的默认数据方式能够迎合需求的状况下,就必须自定义数据方式了,比如我们有个Product类,需要用于释放数据,那么这个类需要要建立Parcelable接口,并在AIDL中新建一个相同类名的aidl文件进行声明,并且这个aidl文件所在的模式需要要和java文件里的实体类路径保持一致,如下面文件Product.aidl
package demo..zhuwentao.bean;
parcelable Product;
然后在IMyAidlTest.aidl中使用import导入进来,除了AIDL默认支持的数据方式外,其它自定义的类别都必须利用此方式导入进来,包名模式必须精确到类名。
interface IMyAidlTest { void addProduct(in Product person); List getProductList(); }
这里的方式只成为接口声明的意义,以上定义的接口最终会在Service服务里建立详细的操作逻辑。
根据aidl文件生成java接口文件
这个过程Android Studio已经帮我们集成好了,只想要点击 Build -> Make Project,或者点击AS上的那个小锤子图标就可以,构建完后还会自动按照我们定义的IMyAidlTest.aidl文件生成IMyAidlTest.java接口类,可以在build/generated/source/aidl/debug/路径下找到这个类。
(2)根据AIDL创建远程Service服务
上一步中创建好的IMyAidlTest.java接口文件,需要使用Service来进行绑定,这里就必须我们新建一个Service服务。
/**
根据AIDL创建远程Service服务端 */ public class MyAidlService extends Service {
private List mProducts; public MyAidlService() { }
private IBinder mIBinder = new IMyAidlTest.Stub() {
@Override public void addProduct(Product product) throws RemoteException { mProducts.add(product); }
@Override public List getProductList() throws RemoteException { return mProducts; } };
@Nullable @Override public IBinder onBind(Intent intent) { mProducts = new ArrayList<>(); return mIBinder; } }
mIBinder对象方法化了IMyAidlTest.Stub,并在回调接口中建立了最后的处理类比 当与用户端绑定时,会触发onBind()方法,并返回一个Binder对象给客户端使用,客户端就可以利用这个类调用服务里建立好的接口模式 记得要在配置文件中加入声明,并使用android:process属性指定其运行在新的进程中。