当前位置:   article > 正文

瞎聊!Android之aidl进程之间传递对象简单分析加 源码_aidl object撖寡情

aidl object撖寡情

        Android里多进程通讯的方式有许多,广播,内容提供者(ContentProvider),Socket,序列化和Binder等,今天就聊聊序列化和binder吧,也就是我们说的AIDL。

先看个例子吧!看看怎样使用AIDL在不同进程之间传递值。

我们先建三个主要的文件Book.aidl、IBookManager.aidl、Book.java

其中Book.java的内容,就一个实体类,实现了parcelable接口,使用AIDL传递的对象必须要实现该接口

我用的是as3.0.1有自动提示生成下面代码,大家也可以用插件生成

  1. public class Book implements Parcelable {
  2. public int bookId;
  3. public String bookName;
  4. public Book(int bookId, String bookName) {
  5. this.bookId = bookId;
  6. this.bookName = bookName;
  7. }
  8. public Book(Parcel in) {
  9. bookId = in.readInt();
  10. bookName = in.readString();
  11. }
  12. public static final Creator<Book> CREATOR = new Creator<Book>() {
  13. @Override
  14. public Book createFromParcel(Parcel in) {
  15. return new Book(in);
  16. }
  17. @Override
  18. public Book[] newArray(int size) {
  19. return new Book[size];
  20. }
  21. };
  22. @Override
  23. public int describeContents() {
  24. return 0;
  25. }
  26. @Override
  27. public void writeToParcel(Parcel parcel, int i) {
  28. parcel.writeInt(bookId);
  29. parcel.writeString(bookName);
  30. }
  31. }

这是Book.aidl的代码,你没有看错,就两行

  1. package com.example.zxw.playexo;
  2. parcelable Book;

这是IBookManager.aidl的代码。定义了两个方法,getBookList和addBook。这里注意,即时book跟他在同一

目录,也要import,这是aidl特殊之处

  1. package com.example.zxw.playexo;
  2. import com.example.zxw.playexo.Book;
  3. interface IBookManager {
  4. List<Book> getBookList();
  5. void addBook(in Book book);
  6. }

上面的是前戏,接下来就开始传值了,这里我说两句,首先用bind启动一个RemoteService服务(这个服务是在另一个进程里面的),那个textview点击事件是往不同进程的service传递Book对象,调用的是addBook方法,也就是我们在上面aidl文件里写的方法,并且调用getBookList方法获取不同进程service 的list,这里为了简单演示就只打印list 的size了


  1. public class MainActivity extends AppCompatActivity {
  2. private IBookManager bookManager;
  3. private int i = 10;
  4. @Override
  5. protected void onCreate(Bundle savedInstanceState) {
  6. super.onCreate(savedInstanceState);
  7. setContentView(R.layout.activity_main);
  8. bindService(new Intent(this, RemoteService.class),
  9. connection, Context.BIND_AUTO_CREATE);
  10. TextView textView = findViewById(R.id.Hello_text);
  11. textView.setOnClickListener(new View.OnClickListener() {
  12. @Override
  13. public void onClick(View view) {
  14. i++;
  15. Book book = new Book(i, "book" + i);
  16. try {
  17. bookManager.addBook(book);
  18. List<Book> bookList = bookManager.getBookList();
  19. Log.e("activity", "onClick: " +bookList.size());
  20. } catch (RemoteException e) {
  21. e.printStackTrace();
  22. }
  23. }
  24. });
  25. }
  26. ServiceConnection connection = new ServiceConnection() {
  27. @Override
  28. public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
  29. bookManager = IBookManager.Stub.asInterface(iBinder);
  30. }
  31. @Override
  32. public void onServiceDisconnected(ComponentName componentName) {
  33. }
  34. };
  35. }

好了,来看看RemoteService的代码,通过IBookManager.Stub的addBook方法获取MainActivity传递过来的book对象,这样我们就完成了从activity到service的传递了。那怎么往回传递呢?其实這里已经验证了,将传递过来的添加到list,然后点击MainAcivity的textview调用getBookList就可以获取到,这里有点绕,大家试试就清楚了

  1. public class RemoteService extends Service {
  2. private Book book;
  3. List<Book> list=new ArrayList<>();
  4. @Nullable
  5. @Override
  6. public IBinder onBind(Intent intent) {
  7. return bookManager;
  8. }
  9. IBookManager.Stub bookManager = new IBookManager.Stub() {
  10. @Override
  11. public List<Book> getBookList() throws RemoteException {
  12. list.add(book);
  13. return list;
  14. }
  15. @Override
  16. public void addBook(Book book) throws RemoteException {
  17. RemoteService.this.book=book;
  18. Log.e("RemoteService", "addBook: " + book.bookName + "------" + book.bookId);
  19. }
  20. };
  21. }


没错就是这么简单 ,究竟AIDL做了什么呢?我们可以看一下IBookManager这个类,你会发现代码有点乱,没关系,ctrl+alt+l,格式化一下代码,并且将stub的代码缩起来先,嘿嘿世界一片光明,这个IBookManager就一个接口,和两个我们写的方法,还有一个stub的静态内部类


好了,打开内部类看看,我擦,还有个内部类Proxy,这不是代理吗?先不看他

我们先是调用了asInterface方法,很简单,判断是否同一进程,是的话玩毛线,不是的话返回这个代理类

再来看看这个代理类,直接实现了最外层的接口IBookManager,重写了我们的两个方法,里面完成了读和写。而外面的onTransact则完成相反的写和读(这里我是猜的)

  1. public static abstract class Stub extends android.os.Binder implements com.example.zxw.playexo.IBookManager {
  2. private static final java.lang.String DESCRIPTOR = "com.example.zxw.playexo.IBookManager";
  3. /**
  4. * Construct the stub at attach it to the interface.
  5. */
  6. public Stub() {
  7. this.attachInterface(this, DESCRIPTOR);
  8. }
  9. /**
  10. * Cast an IBinder object into an com.example.zxw.playexo.IBookManager interface,
  11. * generating a proxy if needed.
  12. */
  13. public static com.example.zxw.playexo.IBookManager asInterface(android.os.IBinder obj) {
  14. if ((obj == null)) {
  15. return null;
  16. }
  17. android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
  18. if (((iin != null) && (iin instanceof com.example.zxw.playexo.IBookManager))) {
  19. return ((com.example.zxw.playexo.IBookManager) iin);
  20. }
  21. return new com.example.zxw.playexo.IBookManager.Stub.Proxy(obj);
  22. }
  23. @Override
  24. public android.os.IBinder asBinder() {
  25. return this;
  26. }
  27. @Override
  28. public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
  29. switch (code) {
  30. case INTERFACE_TRANSACTION: {
  31. reply.writeString(DESCRIPTOR);
  32. return true;
  33. }
  34. case TRANSACTION_getBookList: {
  35. data.enforceInterface(DESCRIPTOR);
  36. java.util.List<com.example.zxw.playexo.Book> _result = this.getBookList();
  37. reply.writeNoException();
  38. reply.writeTypedList(_result);
  39. return true;
  40. }
  41. case TRANSACTION_addBook: {
  42. data.enforceInterface(DESCRIPTOR);
  43. com.example.zxw.playexo.Book _arg0;
  44. if ((0 != data.readInt())) {
  45. _arg0 = com.example.zxw.playexo.Book.CREATOR.createFromParcel(data);
  46. } else {
  47. _arg0 = null;
  48. }
  49. this.addBook(_arg0);
  50. reply.writeNoException();
  51. return true;
  52. }
  53. }
  54. return super.onTransact(code, data, reply, flags);
  55. }
  56. private static class Proxy implements com.example.zxw.playexo.IBookManager {
  57. private android.os.IBinder mRemote;
  58. Proxy(android.os.IBinder remote) {
  59. mRemote = remote;
  60. }
  61. @Override
  62. public android.os.IBinder asBinder() {
  63. return mRemote;
  64. }
  65. public java.lang.String getInterfaceDescriptor() {
  66. return DESCRIPTOR;
  67. }
  68. @Override
  69. public java.util.List<com.example.zxw.playexo.Book> getBookList() throws android.os.RemoteException {
  70. android.os.Parcel _data = android.os.Parcel.obtain();
  71. android.os.Parcel _reply = android.os.Parcel.obtain();
  72. java.util.List<com.example.zxw.playexo.Book> _result;
  73. try {
  74. _data.writeInterfaceToken(DESCRIPTOR);
  75. mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0);
  76. _reply.readException();
  77. _result = _reply.createTypedArrayList(com.example.zxw.playexo.Book.CREATOR);
  78. } finally {
  79. _reply.recycle();
  80. _data.recycle();
  81. }
  82. return _result;
  83. }
  84. @Override
  85. public void addBook(com.example.zxw.playexo.Book book) throws android.os.RemoteException {
  86. android.os.Parcel _data = android.os.Parcel.obtain();
  87. android.os.Parcel _reply = android.os.Parcel.obtain();
  88. try {
  89. _data.writeInterfaceToken(DESCRIPTOR);
  90. if ((book != null)) {
  91. _data.writeInt(1);
  92. book.writeToParcel(_data, 0);
  93. } else {
  94. _data.writeInt(0);
  95. }
  96. mRemote.transact(Stub.TRANSACTION_addBook, _data, _reply, 0);
  97. _reply.readException();
  98. } finally {
  99. _reply.recycle();
  100. _data.recycle();
  101. }
  102. }
  103. }
  104. static final int TRANSACTION_getBookList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
  105. static final int TRANSACTION_addBook = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
  106. }

其实AIDL没有什么神秘的,只是帮我们构建了这个类,这个类我们完全可以自己写(随便说说,别当真)AIDL本质只是系统帮我们构建Binder的工具仅此而已!好了,就这样吧!能力有限,有不对的地方望各位大佬指点

感谢参考博客:http://blog.csdn.net/feiduclear_up/article/details/51385868

最后源码传送门:https://github.com/WoBuShuo/PlayExo


声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/245311
推荐阅读
相关标签
  

闽ICP备14008679号