淘先锋技术网

首页 1 2 3 4 5 6 7

正文

一、 概念QA以及前置技能

Q:什么时候会用到多进程通信?

A: 常见的多进程 app一般是大型公司的 app组,像是腾讯系的 QQ微信QQ空间,QQ邮箱等等,有可能 在 QQ邮箱登录时,可以直接调用 QQ的登录服务,另外,腾讯阿里都有小程序,作为一个第三方开发的小程序应用,在 微信客户端运行,如果和微信放在同一个进程运行,一旦 崩溃,微信也跟着玩完,明明是小程序开发者的 ,硬是让腾讯给 了,不合适。而小型公司,emmmmm,连多进程开发都用的很少,就不要说通信了。但是,如果没有一颗进大厂的心,就学不到高阶技能,有些东西学了,总比一无所知要好。

Q:使用多进程有什么好处?

A: 1)进程隔离,子 app崩溃,不会影响其他进程。

2)系统运行期间,对每个进程的内存划分是有一个上限的,具体多少,视具体设备而定,利用多进程开发,可以提高程序的可运行内存限制。

3)如果系统运行期间内存吃紧,可以杀死子进程,减少系统压力。杀死进程的方式,往往比优化单个app的内存更加直接有效

Q:什么叫 RPC

A:从客户端上通过参数传递的方式调用服务器上的一个函数并得到返回的结果,隐藏底层的通讯细节。在使用形式上像调用 本地函数一样去调用 远程函数

Q:我们自己定义一个 RPC进程间通信框架,有什么实际用处?
A:定义框架的作用,都是 把脏活,累活,别人不愿意重复干的活,都放到框架里面去,让使用者用最干净的方式使用业务接口。定义一个 RPC进程间通信框架,可以把C/S两端那些恶心人的 AIDL编码都集中放到框架 module中,这是最直观的好处,另外,客户端原本还需要手动去 bindService,定义 ServiceConnection,取得 Binder,再去通信,使用 RPC框架,这些内容都可以放到框架 module中. 而C/S两端的代码,就只剩下了 S端的服务注册, C端RPC接口调用,代码外观上非常简洁(可能这里文字描述不够直观,后面有图)

前置技能

要理解本文的核心代码,还是需要一些基础的,大致如下:四大组件之一 Service使用方法, android AIDL通信机制, java注解,java反射,java 泛型

二、传统方式IPC通信写法 与 使用IPC框架进行RPC通信 的对比

见github : https://github.com/18598925736/MyRpcFramework , 运行 aidl_clientaidl_service

先展示原本效果

图中的 查找用户,是从 服务端读取的数据,观察一下核心代码:

这是我优化之后的 IPC项目结构( 如果不优化,那么客户端服务端都需要编写一样的AIDL代码,还要有一个包括包名在内神马都要一模一样的JavaBean,实在是丑陋):

服务端核心代码:

public  class  ServiceActivity  extends  AppCompatActivity {
	@Override
	protected  void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		startService(new  Intent(this, MyService.class));//服务端,app启动之后,自动启动服务
	}
}
public  class  MyService  extends  Service {
	ConcurrentMap<String, UserInfoBean> map;
	@Nullable
	@Override
	public  IBinder onBind(Intent intent) {
		map = new  ConcurrentHashMap<>();
		for (int i = 0; i < 100; i++) {
			map.put("name" + i, new  UserInfoBean("name" + i, "accountNo" + i, i));
		}
		return  new  IUserInfo.Stub() {
			//数据接收器 Stub
			@Override
			public  UserInfoBean getInfo(String name) {
				return map.get(name);
			}
		}
		;
	}
	@Override
	public  void onCreate() {
		super.onCreate();
		Log.e("MyService", "onCreate: success");
	}
}

客户端核心代码 :

public  class  ClientActivity  extends  AppCompatActivity {
	private  TextView resultView;
	private  String TAG = "clientLog";
	private  int i = 0;
	@Override
	protected  void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		initView();
	}
	private  void initView() {
		resultView = findViewById(R.id.resultView);
		findViewById(R.id.connect).setOnClickListener(new  View.OnClickListener() {
			@Override
			public  void onClick(View v) {
				bindService();
			}
		}
		);
		findViewById(R.id.disconnect).setOnClickListener(new  View.OnClickListener() {
			@Override
			public  void onClick(View v) {
				try {
					unbindService(connection);
					resultView.setText("尝试释放");
				}
				catch (IllegalArgumentException e) {
					resultView.setText("已经释放了");
				}
			}
		}
		);
		findViewById(R.id.btn).setOnClickListener(new  View.OnClickListener() {
			@Override
			public  void onClick(View v) {
				if (iUserInfo != null) {
					try {
						((Button) v).setText("查找name为:name" + ((i++) + 1) + "的UserInfoBean");
						UserInfoBean bean = iUserInfo.getInfo("name" + i);
						if (bean != null)
						resultView.setText(bean.toString()); else
						resultView.setText("没找到呀");
					}
					catch (RemoteException e) {
						e.printStackTrace();
					}
				} else {
					resultView.setText("没有连接上service");
				}
			}
		}
		);
	}
	//作为IPC的客户端,我们需要 建立起和Service的连接
	private  IUserInfo iUserInfo;
	//操作句柄,可以通过它向service发送数据
	private  void bindService() {
		if (iUserInfo == null) {
			Intent intent = new  Intent();
			intent.setComponent(new  ComponentName(
			"study.hank.com.aidl_service",
			"study.hank.com.aidl_service.MyService"));
			bindService(intent, connection, Context.BIND_AUTO_CREATE);
			resultView.setText("尝试连接");
		} else {
			resultView.setText("已经连接上service" + iUserInfo);
		}
	}


intent, connection, Context.BIND_AUTO_CREATE);
			resultView.setText("尝试连接");
		} else {
			resultView.setText("已经连接上service" + iUserInfo);
		}
	}