实际验证AndroidBinder本⾝⽀持传输Serializable类型的数据传输
参考⽂章: 《Android 艺术探索》
注意这⾥说的是 Binder 本⾝,即⼿动实现 Binder,⽽不是基于 AIDL(Android 接⼝定义语⾔)。
在 AIDL ⽂件中,只⽀持以下⼏种类型:
1、基本数据类型
2、 String 和 CharSequence
3、只⽀持 ArrayList,且⾥⾯的元素也要被 AIDL ⽀持
4、只⽀持 HashMap,且⾥⾯的元素也要被 AIDL ⽀持,包括 key 和 value
5、实现了 Parcelable 的对象
6、AIDL:所有 AIDL 接⼝本⾝也可以在 AIDL ⽂件中使⽤(⽆法使⽤普通接⼝)
⽽⽆法直接⽀持 Serializable 类型的数据,这是因为使⽤ AIDL 的时候,我们只需要定义相应的 AIDL ⽂件。
然后会由系统⽣成对应的与 Binder 相关的内容,⽽由系统⽣成对应内容的时候,对于序列化对象是基于 Parcelable 接⼝来处理的,因此此时并不直接⽀持 Serializable 类型的数据。学校党建工作计划
但是有个折中的⽅法,因为 AIDL ⽀持 Parcelable 类型的对象,因此可以在 Parcelable 类型的对象⾥⾯添加 Serializable 类型的成员变量。 因为 Parcel 提供了对于 Serializable 类型数据的⽀持。
@Override
public void writeToParcel(Parcel dest,int flags){
dest.writeSerializable(data);
}
实现了 Parcelable 接⼝的对象,要重写 writeToParcel() ⽅法。
但是,对于 Binder 机制本⾝,是可以⽀持 Serializable 类型的对象的传输的。
虐心爱情故事从理论上来说,Serializable 也是序列化的⼀种⽅式,跨进程传输时对于该序列化⽅法应该是要⽀持的。
另外,从实际情景中来推测,也是成⽴的,如 AIDL 中,对于 Parcelable 对象⾥⾯的 Serilizable 类型的成员变量是⽀持的。⽽ AIDL 的底层实现就是 Binder。
下⾯,也将⽤实际的代码去验证。即⼿动的去实现 Binder。
1、定义 Binder 接⼝与实体类
public interface IBookManager2 extends IInterface {
static final String DESCRIPTOR ="application.aidl.IBookManager2";
static final int TRANSACTION_getBookList = IBinder.FIRST_CALL_TRANSACTION +0;
static final int TRANSACTION_addBokk = IBinder.FIRST_CALL_TRANSACTION +1;
public List<Book2>getBookList()throws RemoteException;
public void addBook(Book2 book)throws RemoteException;
}
其中实体类是实现了 Serializable 接⼝的,⽽⾮ Parcelable。
public class Book2 implements Serializable {
public int bookId;
public String bookName;
public Book2(){
}
public Book2(int id, String name){
bookId = id;
bookName = name;
}
public static Book2 createFromParcel(Parcel parcel){
Book2 book2 =new Book2();
book2.bookId = adInt();
book2.bookName = adString();
return book2;
}
public void writeToParcel(Parcel dest,int flags){
dest.writeInt(bookId);
dest.writeString(bookName);
}
@Override
public String toString(){
return String.format("[bookId:%s, bookName:%s]", bookId, bookName);
}
}
2、⼿动实现 Binder 对象类
public class BookManagerImpl extends Binder implements IBookManager2 {
private CopyOnWriteArrayList<Book2> mBookList;
public BookManagerImpl(CopyOnWriteArrayList<Book2> list){
this.attachInterface(this, DESCRIPTOR);
mBookList = list;
龙胜龙脊梯田景区}
public static IBookManager2 asInterface(IBinder obj){
if(obj == null){
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if(iin != null && iin instanceof IBookManager2){
return(IBookManager2) iin;
}
return new BookManagerImpl.Proxy(obj);
}
@Override
public IBinder asBinder(){
return this;
}
@Override
protected boolean onTransact(int code,@NonNull Parcel data,@Nullable Parcel reply,int flags)throws RemoteException { switch(code){
ca INTERFACE_TRANSACTION :{
reply.writeString(DESCRIPTOR);
return true;
}
ca TRANSACTION_getBookList:{
List<Book2> result =BookList();
reply.writeNoException();
reply.writeSerializable((ArrayList<Book2>)result);
return true;
}
ca TRANSACTION_addBokk:{
Book2 arg0;
adInt()!=0){
arg0 = ateFromParcel(data);
}el{
arg0 = null;
}
this.addBook(arg0);
reply.writeNoException();
return true;
}
}
Transact(code, data, reply, flags);
}火烈鸟怎么画
@Override
public List<Book2>getBookList(){
SystemClock.sleep(5000);
return mBookList;
}
@Override
public void addBook(Book2 book){
Log.d("BookManagerImpl","--- addBook ---"+ Thread.currentThread()); mBookList.add(book);
Log.d("BookManagerImpl", String());
}
private static class Proxy implements IBookManager2 {
private IBinder mRemote;
public Proxy(IBinder remote){
this.mRemote = remote;
}
@Override
public IBinder asBinder(){
return mRemote;
}
欧月public String getInterfaceDescriptor(){
西洋参片怎么吃return DESCRIPTOR;
}
@Override
public List<Book2>getBookList(){
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
List<Book2> result = null;
try{
data.writeInterfaceToken(DESCRIPTOR);
result =(ArrayList<Book2>) adSerializable();
}catch(RemoteException e){
e.printStackTrace();
}finally{
}
return result;
}
@Override
public void addBook(Book2 book){
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
try{
data.writeInterfaceToken(DESCRIPTOR);
if(book != null){
data.writeInt(1);
book.writeToParcel(data,0);
}el{
data.writeInt(0);
}
}catch(RemoteException e){
e.printStackTrace();
}finally{
}
}
}
}
3、实现测试部分的逻辑。
(1)先实现远程服务
public class BookManager2Service extends Service {
private static final String TAG ="BMS";
private AtomicBoolean mIsServiceDestoryed =new AtomicBoolean(fal);
private CopyOnWriteArrayList<Book2> mBook2List =new CopyOnWriteArrayList<>();
private Binder mBinder =new BookManagerImpl(mBook2List);
@Override
作文我的语文老师public void onCreate(){
mBook2List.add(new Book2(1,"Android"));
mBook2List.add(new Book2(2,"IOS"));
}
小班绘画@Override
public IBinder onBind(Intent intent){
return mBinder;
}
@Override
public void onDestroy(){
mIsServiceDestoryed.t(true);
}
}
并且在 l 中注册的时候,设置为多进程的,如:android:process=":remote"。(2)实现测试的 Activity
public class BookManager2Activity extends Activity {
private static final String TAG ="BookManagerActivity";
private static final String TAG ="BookManagerActivity";
private static final int MESSAGE_NEW_BOOK_ARRIVED =1;
private IBookManager2 mRemoteBookManager;
@SuppressLint("HandlerLeak")
private Handler mHandler =new Handler(){
@Override
public void handleMessage(Message msg){
switch(msg.what){
ca MESSAGE_NEW_BOOK_ARRIVED:
Log.d(TAG,"receive new book :"+ msg.obj);
break;
default:
super.handleMessage(msg);
}
}
};
private IBinder.DeathRecipient mDeathRecipient =new IBinder.DeathRecipient(){
@Override
public void binderDied(){
Log.d(TAG,"binder died. tname:"+ Thread.currentThread().getName());
if(mRemoteBookManager == null)
return;
mRemoteBookManager.asBinder().unlinkToDeath(mDeathRecipient,0);
mRemoteBookManager = null;
}
};
private ServiceConnection mConnection =new ServiceConnection(){
public void onServiceConnected(ComponentName className, IBinder rvice){
IBookManager2 bookManager = BookManagerImpl.asInterface(rvice);
mRemoteBookManager = bookManager;
try{
mRemoteBookManager.asBinder().linkToDeath(mDeathRecipient,0);
Book2 newBook =new Book2(3,"Android进阶");
bookManager.addBook(newBook);
}catch(RemoteException e){
e.printStackTrace();
}
}
public void onServiceDisconnected(ComponentName className){
mRemoteBookManager = null;
Log.d(TAG,"onServiceDisconnected. tname:"+ Thread.currentThread().getName());
}
};
@Override
protected void onCreate(Bundle savedInstanceState){
tContentView(R.layout.activity_book_manager);
Intent intent =new Intent(this, BookManager2Service.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
public void onButton1Click(View view){
Toast.makeText(this,"click button1", Toast.LENGTH_SHORT).show();
new Thread(new Runnable(){
@Override
public void run(){
if(mRemoteBookManager != null){
Book2 newBook =new Book2(3,"Android进阶");
try{