进程间通讯:Binder: Binder原理剖析

1:Binder原理解析

1: 这是一种比startService更复杂的启动方式,同时使用这种方式启动的service也能完成更多的事情,
  2: 比如其他组件可向其发送请求,接受来自它的响应,甚至通过它来进行IPC等等。我们通常将绑定它的组件称为客户端,而称它为服务端。
   3:如果要创建一个支持绑定的service,我们必须要重写它的onBind()方法。这个方法会返回一个IBinder对象,它是客户端用来和服务器进行交互的接口。
    而要得到IBinder接口,我们通常有三种方式:继承Binder类,使用Messenger类,使用AIDL。

上面概念如此复杂,下来跟着我来一步一步解析Binde诞生过程。

举个例子:

    使用Binder实现一个客户端连接服务端查询学生成绩的例子。

1.服务端提供查询服务

public class GradeService extends Service {
    public static final int REQUEST_CODE=1000;
    private final Binder mBinder = new Binder() {
        @Override
        protected boolean onTransact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags) throws RemoteException {
            if (code == REQUEST_CODE) {

                // 1 先匹配客户端的请求码,然后从data读出数据
                String name = data.readString();

                // 根据姓名查询学生成绩并将成绩写入到返回数据
                int studentGrade = getStudentGrade(name);
                if (reply != null)

                    // 2. 从reply向客户端写返回值,这时唤醒了客户端。
                    reply.writeInt(studentGrade);

                 // 3. 处理完成
                return true;
            }
            return super.onTransact(code, data, reply, flags);
        }
        // 根据姓名查询学生成绩
        public int getStudentGrade(String name) {         
            return StudentMap.getStudentGrade(name);
        }
    };

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }
}

<service
    android:name="com.zhpan.sample.binder.server.GradeService"
    android:process=":server">
    <intent-filter>
        <action android:name="android.intent.action.server.gradeservice" />
    </intent-filter>
</service>

2.客户端连接服务查询成绩

public class BinderActivity extends AppCompatActivity {
    // 远程服务的Binder代理
    private IBinder mRemoteBinder;

    private final ServiceConnection mServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            // 获取远程服务的Binder代理
            mRemoteBinder = iBinder;
       
             // 1:从对象池拿到可复用的对象(享元模式)
             Parcel data = Parcel.obtain();
             Parcel reply = Parcel.obtain();
             int grade = 0;

             // 2. 往 data里面写数据,作为请求参数
             data.writeString(name);
             try {
                 if (mRemoteBinder == null) {
                throw new IllegalStateException("Need Bind Remote Server...");
              }

            // 3. 拿到了服务端的IBinder句柄,调用 transact ,并约定请求码,其中第四个参数
            flag = 0 表示同步调用,1 表示表示异步调用
            mRemoteBinder.transact(REQUEST_CODE, data, reply, 0);
            
            //4 从服务端已经获取到内容了,直接从 relpy中读取
            grade = reply.readInt();
            } catch (RemoteException e) {
            e.printStackTrace();
            }
            return grade;

        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            mRemoteBinder = null;
        }
    };



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_binder);
        // 绑定服务
        findViewById(R.id.btn_bind_service).setOnClickListener(view -> bindGradeService());

    }
    // 绑定远程服务
    private void bindGradeService() {
        String action = "android.intent.action.server.gradeservice";
        Intent intent = new Intent(action);
        intent.setPackage(getPackageName());
        bindService(intent, mServiceConnection, BIND_AUTO_CREATE);
    }

2:Binder原理剖析2

     图解 | Binder浅析(一)

3:Binder原理图

        

 3.1 Binder总结

       1:通过这个例子,我们可以看出,Binder机制使用了Parcel来序列化数据,客户端在主线程调用了transact来请求(Parcel data传参),服务端在Binder线程调用onTransact来响应(Parcel reply回传结果)。

     2: 由于我们的flags传入的是0同步调用,可以试着在服务端onTransact里sleep几秒,会发现客户端需要几秒后才能打印出返回值。所以如果服务端需要进行耗时操作,客户端则需要在子线程里进行binder调用。

   3:默认情况下,binder传递数据是同步的,

transact(int code, Parcel data, Parcel reply, int flags)

你可以定义oneway关键字来实现异步  

mRemote.transact(int code, Parcel data, Parcel reply,  android.os.IBinder.FLAG_ONEWAY);

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值