Author: Enjoy learning class lifelong VIP week

Reprint please state the source!

preface

Hand in hand series of articles, I wrote for you, but also for myself. The article may be too detailed, but this is to help as many people as possible, after all, after working for 5 or 6 years, they can not always suck blood, and it is time to give back to open source. Articles in this series:

1. Explain the practical value of a technology in an easy-to-understand way

2, detailed writing source tracking, source screenshots, drawing class structure diagram, as detailed as possible to explain the principle of the exploration process

3. Provide Github’s runnable Demo project, but the code I provide is more to provide ideas and throw a brick to attract others. Please consider CV

4. Some pits in the process of exploring the principle of collection and arrangement, or matters needing attention in the running process of demo

5, with GIF diagram, the most intuitive demo operation effect

If the details are too detailed, skip to the conclusion. My ability is limited, if found improper description, welcome comments criticism and correction.

Never too old to learn, the road is long. With the gentleman mutual encouragement!

The body of the outline

Concept QA and pre-production skills

2. The comparison between traditional IPC communication writing method and RPC communication using IPC framework

Third, Demo demonstration

Iv. Explanation of the framework’s core ideas

Five, write the last words

The body of the

Concept QA and pre-production skills

Q: When will multi-process communication be used?

A: Common multiple processesappGenerally, it is the APP group of large companies, such as TencentQQ wechat QQ space, QQ mailboxWait a minute. It could beQQ emailIt can be invoked directly during loginQQ login serviceIn addition, Tencent Ali have small program, as a third party developed small program application, inWechat client running, if and wechat in the same process to run, oncecollapse, wechat also follow over, it is small program developerspan, just let Tencent givebackNot suitable. Small companies, emMMMM, use very little even multi-process development, let alone communication. However, if you don’t have the heart to enter a big factory, you can’t learn advanced skills. It is better to learn something than to know nothing.

Q: What are the benefits of using multiple processes?

A: 1) Process isolation, subappCrash does not affect other processes.

2) During the operation of the system, there is an upper limit for the memory partition of each process. The specific amount depends on the specific device. The use of multi-process development can improve the running memory limit of the program.

3) If memory is tight during system operation, child processes can be killed to reduce system stress. Killing processes is often more straightforward than optimizing the memory of a single app

Q: what do you meanRPC?

A: Call A function on the server from the client by passing parameters and get the return result, hiding the underlying communication details. In use form like callLocal functionSame to callRemote function.

Q: What is the practical use of defining our own RPC interprocess communication framework? A: The definition of the function of the framework is to put dirty work, tiring work, others do not want to repeat, into the framework, so that users can use the business interface in the cleanest way. Define a framework for RPC interprocess communication, which can put all the nasty AIDL code on both sides of C/S into the framework module. This is the most obvious benefit. Additionally, clients would have to manually go to bindService, define ServiceConnection, obtain Binder, Then to communicate, using the RPC framework, these contents can be put in the framework Module. For the code at both ends of C/S, only the service registration at the S end and RPC interface call at the C end are left. The code is very simple in appearance (maybe the text description is not intuitive here, as shown in the figure below).

Front skills

To understand the core code of this article, you need some basics: Service usage, Android AIDL communication mechanism, Java annotations, Java reflection, and Java generics

Second,Traditional IPC communication formatUse IPC framework for RPC communicationThe contrast of

See lot: github.com/18598925736… , run aidl_client and aidl_service

Let me show you what it looks like

The lookup user in the figure is the data read from the server. Take a look at the core code:

This is the IPC project structure I optimized (otherwise, the client and server would have to write the same AIDL code and have a JavaBean that is identical in everything including package name, which is ugly):

Server core code:

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)); // Start service automatically after app starts}}Copy the code
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.StubPublic UserInfoBean getInfo(String name) {public UserInfoBean getInfo(String name) {returnmap.get(name); }}; } @Override public voidonCreate() {
		super.onCreate();
		Log.e("MyService"."onCreate: success"); }}Copy the code

The clientCore code:

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("Try to release");
				}
				catch (IllegalArgumentException e) {
					resultView.setText("It has been released."); }}}); findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
			@Override
			public  void onClick(View v) {
				if(iUserInfo ! = null) { try { ((Button) v).setText("Search for name :name" + ((i++) + 1) + "UserInfoBean." ");
						UserInfoBean bean = iUserInfo.getInfo("name" + i);
						if(bean ! = null) resultView.setText(bean.toString());else
						resultView.setText("I didn't find it."); } catch (RemoteException e) { e.printStackTrace(); }}else {
					resultView.setText("Service not connected"); }}}); } // As an IPC client, we need to establish a connection with the Service private IUserInfo IUserInfo; // Handle the operation through which data can be sent to the service private voidbindService() {
		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("Try to connect");
		} else {
			resultView.setText("Already connected to service" + iUserInfo);
		}
	}
	private  ServiceConnection connection = new  ServiceConnection() {
		@Override
		public  void onServiceConnected(ComponentName name, IBinder service) {
			iUserInfo = IUserInfo.Stub.asInterface(service);
			resultView.setText("Connection successful");
			Log.d(TAG, "connection:" + "Connection successful");
		}
		@Override
		public  void onServiceDisconnected(ComponentName name) {
			iUserInfo = null;
			resultView.setText("Connection has been disconnected");
			Log.d(TAG, "connection:" + "Disconnected"); }}; @Override protected voidonDestroy() { super.onDestroy(); unbindService(connection); }}Copy the code

It is easy to find that the amount of code on the server side is reasonable and not very complicated, but on the client side, to handle connection, to manually unbind and unbind the Service, all the Javabeans involved in communication must also implement the serialization interface. It’s not obvious, but if there are N client activities that need to communicate with the Service, that means that each Activity must write similar code. It’s cumbersome and ugly.

high energy alert

When RPC framework is not used, the code structure at both ends of CS has a general impression. The following is the core code of client and server when IPC framework is used

The client

What about bindService before that? Didn’t. The client uses this framework to communicate with the process without worrying about how to write AIDL, bindService, ServiceConnection, saving a lot of work.

The service side

Compare the changes in our core code before and after using the framework

What has changed? Obviously, it’s drastically reducedThe clientAnd, once and for all, unless the requirements change drastically, the framework, once written, for life. In addition, there are huge savings to be made using frameworksThe clientThe amount of code, reduce the possible omission caused by artificial coding (such as forgetting to release the connection caused by leakage, etc.). Imagine if you were a teamleaderThe level of team members is likelyunevenSo how to ensure the development of the projectMinimum error probability ——- Using a framework, using frameworks to simplify team memberscodingandCoding difficultyAnd let themThe foolWrite code.

Third, Demo demonstration

Github address: github.com/18598925736…

The scenario simulated in the above Demo is:

Server: Start a login service. After starting the service, save a user name and password that can log in

Client 1: the RPC invokes the login service. The user name and password are the same as those on the server. The login succeeds

Client 2: When the RPC invokes the login service, the user name and password are different from those on the server, and the login fails

DemoEngineering code structure diagram

Note: Both client and server must rely on the framework layer Module Implementation Project (“: IPC “)

(To be continued……)

Follow me and share more technical dry goods