• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >Android > Android IPC机制(四):细说Binder连接池

Android IPC机制(四):细说Binder连接池

作者:网友 字体:[增加 减小] 来源:互联网 时间:2017-05-26

网友通过本文主要向大家介绍了binder ipc,android binder机制,android中binder机制,android binder,android binder使用等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

Android IPC机制(四):细说Binder连接池


一、 前言

在上一篇文章 Android IPC机制(三):浅谈Binder的使用中,笔者浅谈了Binder的使用及其工作机制,利用AIDL方式能很方便地进行客户端和服务端的跨进程通信。但是,我们想一下,如果按照我们之前的使用方法,必须满足一个AIDL接口对应一个service,那么问题来了,假如我们的应用,有很多模块,而每一个模块都需要和服务端通讯,那么我们也要为每一个模块创建特定的aidl文件,那么服务端service也会产生很多个,显然,如果aidl接口变多,那么service也会跟着变多,那么这样的用户体验就会非常不好,那么我们该怎么做呢?在任玉刚著的《Android 开发艺术探索》一书中,给出了一个Binder连接池的概念,即利用一个Binder连接池来管理所有Binder,服务端只需要管理这个Bindere连接池即可,这样就能实现一个service管理多个Binder,为不同的模块返回不同的Binder,以实现进程间通讯。所以,本文将讲述如何实现Binder连接池。


二、实现

1、先提供两个AIDL接口来模拟多个模块都要使用AIDL的情况:ISpeak接口和ICalculate接口:

package com.chenyu.service;
interface ISpeak {
    void speak();
}

package com.chenyu.service;
interface ICalculate {
    int add(in int num1,in int num2);
}


接着,实现这两个接口:分别为Speak.java和Calculate.java文件:

public class Speak extends Stub {
    public Speak() {
        Log.d("cylog","我被实例化了..............");
    }
    @Override
    public void speak() throws RemoteException {
        int pid = android.os.Process.myPid();
        Log.d("cylog","当前进程ID为:"+pid+"-----"+"这里收到了客户端的speak请求");
    }
}

public class Calculate extends ICalculate.Stub {
    @Override
    public int add(int num1, int num2) throws RemoteException {
        int pid = android.os.Process.myPid();
        Log.d("cylog", "当前进程ID为:"+pid+"----"+"这里收到了客户端的Calculate请求");
        return num1+num2;
    }
}



可以看到,这两个接口的实现类,都是继承了Interface.Stub类,这个在上一章的服务端代码出现过,是在服务端的service内部实现了接口的方法,而这里我们把实现了接口的方法从服务端抽离出来了,其实这个实现类依然是运行在服务端的进程中,从而实现了AIDL接口和服务端的解耦合工作,让服务端不再直接参与AIDL接口方法的实现工作。那么,服务端通过什么桥梁与AIDL接口联系呢?答案就是Binder连接池。Binder连接池管理着所有的AIDL接口,就如一位将军统帅着千军。客户端需要什么Binder,就提供信息给Binder连接池,而连接池根据相应信息返回正确的Binder,这样客户端就能执行特定的操作了。可以说,Binder连接池的思路,非常类似设计模式之中的工厂模式。接下来我们看Binder连接池的具体实现:

2、为Binder连接池创建AIDL接口:IBinderPool.aidl:

interface IBinderPool {
    IBinder queryBinder(int binderCode);  //查找特定Binder的方法
}

为什么需要这个接口?我们从上面的分析可以知道,service端并不直接提供具体的Binder,那么客户端和服务端连接的时候就应该返回一个IBinderPool对象,让客户端拿到这个IBinderPool的实例,然后由客户端决定应该用哪个Binder。所以服务端的代码很简单,只需要返回IBinderPool对象即可:


3、服务端service代码:

public class BinderPoolService extends Service {

    private Binder mBinderPool = new BinderPool.BinderPoolImpl();   // 1
    private int pid = Process.myPid();
    @Override
    public IBinder onBind(Intent intent) {
        Log.d("cylog", "当前进程ID为:"+pid+"----"+"客户端与服务端连接成功,服务端返回BinderPool.BinderPoolImpl 对象");
        return mBinderPool;
    }
}

①号代码处,实例化了一个BinderPool.BinderPoolImpl类,并在onBind方法返回了这个mBinderPool对象。


4、接下来我们看BinderPool的具体实现,代码比较长,我们先大体上认识,再详细分析:

public class BinderPool {
    public static final int BINDER_SPEAK = 0;
    public static final int BINDER_CALCULATE = 1;

    private Context mContext;
    private IBinderPool mBinderPool;
    private static volatile BinderPool sInstance;
    private CountDownLatch mConnectBinderPoolCountDownLatch;

    private BinderPool(Context context) {	   // 1
        mContext = context.getApplicationContext();
        connectBinderPoolService();
    }

    public static BinderPool getInstance(Context context) {     // 2
        if (sInstance == null) {
            synchronized (BinderPool.class) {
                if (sInstance == null) {
                    sInstance = new BinderPool(context);
                }
            }
        }
        return sInstance;
    }

    private synchronized void connectBinderPoolService() {      // 3
        mConnectBinderPoolCountDownLatch = new CountDownLatch(1);
        Intent service = new Intent(mContext, BinderPoolService.class);
        mContext.bindService(service, mBinderPoolConnection,
                Context.BIND_AUTO_CREATE);
        try {
            mConnectBinderPoolCountDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    
    public IBinder queryBinder(int binderCode) {          // 4
        IBinder binder = null;
        try {
            if (mBinderPool != null) {
                binder = mBinderPool.queryBinder(binderCode);
            }
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        return binder;
    }

    private ServiceConnection mBinderPoolConnection = new ServiceConnection() {       // 5

        @Override
        public void onServiceDisconnected(ComponentName name) {
            
        }

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mBinderPool = IBinderPool.Stub.asInterface(service);
            try {
                mBinderPool.asBinder().linkToDeath(mBinderPoolDeathRecipient, 0);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
            mConnectBinderPoolCountDownLatch.countDown();
        }
    };

    private IBinder.DeathRecipient mBinderPoolDeathRecipient = new IBinder.DeathRecipient() {    // 6
        @Override
        public void binderDied() {
            mBinderPool.asBinder().unlinkToDeath(mBinderPoolDeathRecipient, 0);
            mBinderPool = null;
            connectBinderPoolService();
        }
    };

    public static class BinderPoolImpl extends IBinderPool.Stub {     // 7

        public BinderPoolImpl() {
            super();
        }

        @Override
        public IBinder queryBinder(int binderCode) throws RemoteException {
            IBinder binder = null;
            switch (binderCode) {
                case BINDER_SPEAK: {
                    binder = new Speak();
                    break;
                }
                case BINDER_CALCULATE: {
                    binder = new Calculate();
                    break;
                }
                default:
                    break;
            }

            return binder;
        }
    }

}

大体上看,这个类完成的功能有实现客户端和服务端的连接,同时内有还有一个静态内部类:BinderPoolImpl,继承了IBinderPool.Stub,这也非常眼熟,所以这个静态内部类应该是运行了服务端的。好了,我们从上往下分析每一个方法的作用:

①private BinderPool(Context context)构造方法:这里传递了context对象,注意到,这个构造方法使用了private修饰,那么外界是无法直接调用构造器的,所以有了②号方法。


②public static BinderPool getInstance(Context context):看到getInstance字样,熟悉设计模式的读者应该知道了这里是使用了单例模式,而且是线程同步的懒汉式单例模式,在方法内部,把传递进来的context上下文参数传递进构造函数,即此时调用了①号方法,接着①号方法调用了connectBinderPoolService()方法,即③号方法。


③private synchronized void connectBinderPoolService():这个方法主要用于客户端与服务端建立连接,在方法内部出现了CountDownLatch类,这个类是用于线程同步的,由于bindService()是异步操作,所以如果要确保客户端在执行其

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • Android IPC机制(四):细说Binder连接池

相关文章

  • 2017-05-26使用phonegap播放音频,phonegap播放音频
  • 2017-05-26安卓开源项目周报0208,安卓开源项目0208
  • 2017-05-26Android版本和API Level对应关系,androidlevel
  • 2017-05-26关于TCP MSS的内核设置
  • 2017-05-26Android学习笔记-开关按钮ToggleButton和开关Switch,togglebuttonswitch
  • 2017-11-18android 自定义View圆圈箭头_
  • 2017-05-26App启动页倒计时功能,app启动倒计时
  • 2017-05-26Android开发:Android SDK的介绍
  • 2017-05-26认清Android Studio下的Gradle是什么
  • 2017-05-26使用Gradle动态配置资源,gradle动态资源

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • 一个特别适合新手练习的Android小项目——每日一妹纸
    • Spider引擎分布式数据库解决方案(最全的spider教程)
    • 实现图片拖动,图片拖动
    • android adb pull push,androidadb
    • Android开发学习——画横线竖线,android横线
    • Android--线程详解
    • Android 调用百度地图API,androidapi
    • 深入理解RCU实现
    • android发送邮件
    • 说说Android6.0动态申请权限的那些坑,android6.0动态权限

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有