IPC进程间通信:AIDL

上篇文章使用了Messenger来进行进程间通信,其本质也是使用AIDL。

这次service端模拟一个图书馆,Activity模拟一位读者,读者可以查看图书馆中的图书列表,可以添加图书,当有新图书加入时通知读者(即添加Listener)

添加新进程中的service

     <service
            android:name=".aidl.BookService"
            android:process=":remote1" />

AIDL支持的数据类型:

1.AIDL支持Java原始数据类型。

2.AIDL支持String和CharSequence。

3.实现了Parcelable接口的实例。

4.AIDL支持java.util.List和java.util.Map,但是有一些限制。集合中项的允许数据类型包括Java原始类型、String、CharSequence或是android.os.Parcelable。无需为List和Map提供import语句,但需要为Parcelable提供import语句。

5.非原始类型中,除了String和CharSequence以外,其余均需要一个方向指示符。方向指示符包括in、out、和inout。in表示由客户端设置,out表示由服务端设置,inout表示客户端和服务端都设置了该值。

Book封装类,这里需要实现Parcelable接口来实现序列化,在Android studio中可以快速生成,并且实现Parcelable中的方法

public class Book implements Parcelable {
    private int id;
    private String name;

    protected Book(Parcel in) {
        id = in.readInt();
        name = in.readString();
    }

    public Book(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public static final Creator<Book> CREATOR = new Creator<Book>() {
        @Override
        public Book createFromParcel(Parcel in) {
            return new Book(in);
        }

        @Override
        public Book[] newArray(int size) {
            return new Book[size];
        }
    };


    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(id);
        dest.writeString(name);
    }

   ...省略get/set方法
}

这里开始编写AIDL文件,android studio中可以右键新建AIDL文件。

如果AIDL中使用到了自定义的Parcelable对象,需要新建一个同名的aidl文件,声明它为Parcelable类型,并且他们的包结构是相同的。

// Book.aidl
package com.du.ipc.bean;

parcelable Book;

用来监听添加书籍的Listener的aidl代码:

// IOnBookChangeListener.aidl
package com.du.ipc;

import com.du.ipc.bean.Book;

interface IOnBookChangeListener {
     void onChangeBook(in Book book);
}

BookManager.aidl代码:

// IBookManager.aidl
package com.du.ipc;
import com.du.ipc.bean.Book;
import com.du.ipc.IOnBookChangeListener;

interface IBookManager {

    List<Book> getBookList();
    void addBook(in Book book);
    void registListener(IOnBookChangeListener listener);
    void removeListener(IOnBookChangeListener listener);
}

Activity代码如下:

public class BookActivity extends AppCompatActivity {
    private int bookId = 1;
    private IBookManager bookManager;
//    Service连接
    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
//            连接成功
            bookManager = IBookManager.Stub.asInterface(service);
            try {
//                注册书籍变化监听器
                bookManager.registListener(listener);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

//    书籍变化监听器实现
    private IOnBookChangeListener listener = new IOnBookChangeListener.Stub() {
        @Override
        public void onChangeBook(Book book) throws RemoteException {
            Log.e("tag" , "changeBook : " + book);
        }
    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_book);
//        绑定service
        Intent intent = new Intent(this , BookService.class);
        bindService(intent , connection , Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onDestroy() {
//        解绑service
        unbindService(connection);
        super.onDestroy();
    }

//    获取书籍列表
    public void getBookList(View view) throws RemoteException {
        List<Book> books = bookManager.getBookList();
        Log.e("tag" , "books : " + books);
    }
//   添加书籍
    public void addBook(View view) throws RemoteException {
        Book book = new Book(bookId , "AndroidBook" + bookId);
        bookManager.addBook(book);
        bookId++;
    }
//  移除监听器
    public void removeListener(View view) {
        try {
            bookManager.removeListener(listener);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
}

service代码:

这里有几点需要注意:

1.监听器,这里必须使用RemoteCallbackList,这是专门远程注册、移除监听器的类,如果使用常用的List,会发现无法移除监听器,大家可以试下,这里就不写出来的

2.循环监听器List时调用listeners.beginBroadcast(),并在使用结束后,调用listeners.finishBroadcast(),并且不可以直接写for (int i = 0;i<listeners.beginBroadcast();i++),调用beginBroadcast()后,不调用finishBroadcast()会抛出异常

public class BookService extends Service {
//    监听器,这里必须使用RemoteCallbackList,这是专门远程注册、移除监听器的类,如果使用常用的List,会发现无法移除监听器,大家可以试下,这里就不写出来的
    private RemoteCallbackList<IOnBookChangeListener> listeners = new RemoteCallbackList<>();
//    模拟书籍
    private List<Book> books = new ArrayList<>();
//    实现我们定义的IBookManager
    private IBinder mBinder = new IBookManager.Stub(){

        @Override
        public List<Book> getBookList() throws RemoteException {
            return books;
        }

        @Override
        public void addBook(Book book)  {
            books.add(book);
            try {
//                获取listener数量,这里一定要写出来,不可以直接写for (int i = 0;i<listeners.beginBroadcast();i++),调用beginBroadcast()后,不调用finishBroadcast()会抛出异常
                int count = listeners.beginBroadcast();
                for (int i = 0;i<count;i++){
//                    调用listener的方法
                    listeners.getBroadcastItem(i).onChangeBook(book);
                }
//                结束获取listener数量
                listeners.finishBroadcast();
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        
        @Override
        public void registListener(IOnBookChangeListener listener) throws RemoteException {
//            注册listener 相当于List.add()
            listeners.register(listener);
            Log.e("tag" , "registListener");
        }

        @Override
        public void removeListener(IOnBookChangeListener listener) throws RemoteException {
            //            移除listener 相当于List.remove()
            listeners.unregister(listener);
        }
    };

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
//        返回我们上面实现的IBookManager
        return mBinder;
    }
}

这里只是使用!!!!!!!不介绍实现!!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值