美文网首页
Binder方法调用

Binder方法调用

作者: tesla1984 | 来源:发表于2018-07-08 15:16 被阅读0次

    Service Stub实现类

    public class BookManagerService extends Service {
             private static final String TAG = "BMS";
             private CopyOnWriteArrayList<Book> mBookList = new CopyOnWriteArray-
             List<Book>();
             private Binder mBinder = new IBookManager.Stub() {
                 @Override
                 public List<Book> getBookList() throws RemoteException {
                     return mBookList;
                 }
                 @Override
                 public void addBook(Book book) throws RemoteException {
                     mBookList.add(book);
                 }
             };
             @Override
             public void onCreate() {
                 super.onCreate();
                 mBookList.add(new Book(1,"Android"));
                 mBookList.add(new Book(2,"Ios"));
             }
             @Override
             public IBinder onBind(Intent intent) {
                 return mBinder;
             }
        }
    

    客户端调用类

    public class BookManagerActivity extends Activity {
             private static final String TAG = "BookManagerActivity";
             private ServiceConnection mConnection = new ServiceConnection() {
                 public void onServiceConnected(ComponentName className,IBinder
                 service) {
                     IBookManager bookManager = IBookManager.Stub.asInterface
                     (service);
                     try {
                         List<Book> list = bookManager.getBookList();
                         Log.i(TAG,"query book list,list type:" + list.getClass().
                         getCanonicalName());
                         Log.i(TAG,"query book list:" + list.toString());
                     } catch (RemoteException e) {
                         e.printStackTrace();
                     }
                 }
                 public void onServiceDisconnected(ComponentName className) {
                 }
             };
             @Override
             protected void onCreate(Bundle savedInstanceState) {
                 super.onCreate(savedInstanceState);
                 setContentView(R.layout.activity_book_manager);
                 Intent intent = new Intent(this,BookManagerService.class);
                 bindService(intent,mConnection,Context.BIND_AUTO_CREATE);
             }
             @Override
             protected void onDestroy() {
                 unbindService(mConnection);
                 super.onDestroy();
             }
        }
    

    getBookList和addBook这两个AIDL方法是在服务端的Binder线程池中执行的,因此当多个客户端同时连接的时候,会存在多个线程同时访问的情形,所以我们要在AIDL方法中处理线程同步,而我们这里直接使用CopyOnWriteArrayList来进行自动的线程同步。

    asInterface(android.os.IBinder obj)

    用于将服务端的Binder对象转换成客户端所需的AIDL接口类型的对象,这种转换过程是区分进程的,如果客户端和服务端位于同一进程,那么此方法返回的就是服务端的Stub对象本身,否则返回的是系统封装后的Stub.proxy对象。

    onTransact

    这个方法运行在服务端中的Binder线程池中,当客户端发起跨进程请求时,远程请求会通过系统底层封装后交由此方法来处理。该方法的原型为public Boolean onTransact(int code,android.os.Parcel data,android.os.Parcel reply,int flags)。服务端通过code可以确定客户端所请求的目标方法是什么,接着从data中取出目标方法所需的参数(如果目标方法有参数的话),然后执行目标方法。

    这里的目标方法就是上面的getBooklistaddBook

    Proxy#getBooklist

    这个方法运行在客户端,当客户端远程调用此方法时,它的内部实现是这样的:首先创建该方法所需要的输入型Parcel对象_data、输出型Parcel对象_reply和返回值对象List;然后把该方法的参数信息写入_data中(如果有参数的话);接着调用transact方法来发起RPC(远程过程调用)请求,同时当前线程挂起;然后服务端的onTransact方法会被调用,直到RPC过程返回后,当前线程继续执行,并从_reply中取出RPC过程的返回结果;最后返回_reply中的数据。

    总体来说

    IBookManager bookManager = IBookManager.Stub.asInterface (service);

    • 如果是同一个进程,返回Stub对象,然后执行Stub实现类的getBooklist方法

    • 如果不是同一个进程,返回Proxy对象,调用Proxy#getBooklist方法,而该方法就是设置参数,然后调用transact方法(该方法运行在服务端的Binder线程中),然后执行目标方法(就是Service中Stub实现类的getBooklist方法)

    所以Proxy#getBooklist运行在客户端
    而Stub实现类的getBooklist方法运行在服务端Binder线程中

    相关文章

      网友评论

          本文标题:Binder方法调用

          本文链接:https://www.haomeiwen.com/subject/bieouftx.html