The introduction
In the last principle article, we have expounded the basic principle of Hybrid App in detail, understood how Native terminal and H5 terminal communicate, as well as bridge design and access. This article will begin to put these reasons into practice and actually implement a complete and stable Hybrid solution in code. If you still have questions about the principle, please move on to the Analysis of Hybrid App technology — Principle section. Only on the basis of understanding the theory and further combining it with practice can you really go deep into a technology.
If you have any better plans or suggestions, you can go to github.com/xd-tayde to discuss with me ha!
The skyscraper
Said so a lot of theoretical knowledge, may have a small partner will say: “are you blowing fluff ah.” . π . So let’s just briefly talk about one of the projects that we’ve done using this approach.
This is a Hybrid module completely built into the App, which is completed by deep collaboration between Native and H5. There are four pages in total, among which the home page and production page are made by H5, while the camera page and save page are reused by Native page.
The project has been used more than 1 billion times a year. The scheme has stood the test, and is still being optimized and expanded in the process.
The implementation is based on the following considerations:
- The style of the whole module is changeable, the overall UI is matched with the makeup, and the whole module has been in continuous iteration;
- The project logic process is highly variable, which requires H5’s strong thermal update ability, timely response to data changes, rapid trial and error and correction;
- The shooting page and the saving page are the existing modules of the client, which can be customized and reused directly.
- Multiple SDKS need to be accessed with client assistance, such as using algorithm SDKS for complex image processing.
After a brief look at the project, let’s start building Bridge-js. Since this series is focused on the front end, we’ll focus on the H5 part, the bridg. js implementation that will be injected into the header of each page. The SDK part in the client will not be deconstructed in detail, but will cover only a few details.
Build the foundation – Bridge-js architecture
Based on the structure described in the previous article, we will further improve the details by organizing the following process structure diagram. Please look at the following figure to have a general concept:
nativeCall
δΈ postMessage
The two principal apis bridge the Native and H5 ends
Next, we’ll take a closer look at the code implementation of each part.
(1) The business side use posture
First, let’s look at how the business side is used in this solution. The following is an example of obtaining the network state:
(δΊ) H5 –> Native
Let’s look directly at the internal implementation of nativeCall:
It can be solved into the following four steps:
- Generates a unique handler identifier, starting at 0;
- Store parameters in the parameter pool (_paramsStore) based on handler values.
- With a handlerRegister custom events and bind callbackAnd store the callback in _callbackStore,
addEvent()
, the purpose of storage is mainly for the event unbinding use; - In the form of an iframeSend the agreement, and carries the unique identifier handler,
send()
;
Native:
- When the client receives the request, it uses a handler call
getParam
From the parameter poolGet the corresponding parameter.
- Perform functions corresponding to the protocol;
In this way, the process of H5 –> Native is passed. After the client completes the corresponding function, the execution result is sent back.
Native –> H5
Native:
- Call Native directly after completing the function
Bridge.postMessage(handler, data)
That will beThe execution resultAnd beforenativeCall
To get thelogoBack to H5;
H5:
- H5 After the unique ID is receivedExample Initialize the corresponding custom eventIs triggered after the data is mounted
fireEvent
This function:
In this way, we have completed the two-way interaction mechanism between the two ends, and combed out the core code of bridge-js, including:
-
The most important open apis: nativeCall and postMessage;
-
The client gets the parameter function getParam;
-
Event callback to addEvent and fireEvent in the system;
-
Send for the sending protocol.
Android compatibility:
If you’ve seen the children’s shoes in the previous principle article, you may have a question: When Android 4.4 is below, loadUrl is used to call js function, and at this time, the return value of the function cannot be obtained, that is, when 4.4-, Android cannot get the parameter of the protocol through getParam, here we need to do compatibility processing. And here we can use a curve to save the country SAO operation, the principle used is another H5 -> Native scheme mentioned in the last article:
Prompt interception in WebView
The scheme is as follows:
- When Android accepts the protocol, it gets the handler value;
- Use without compatibility issues
loadUrl
Perform js:Bridge.getParam(handler)
, directly passes the return value directly through jsprompt
A:
- Through rewriting
onJsPrompt
This method intercepts the contents of the prompt issued in the previous step and resolves the corresponding parameters.
In this way, the Entire Android platform can complete the parameter acquisition, and the way is unified, do not need to be compatible with the platform, which is very SKRSKR. ~ ~ π€ π» π€ π»
Now look at it, don’t you think chicken is easy? . I can write 100 in a minute. π. That’s right! In fact, the core principle is so simple, but this is only the most basic foundation, and on the foundation, we can start to build our building layer by layer!
Building – Customization of the agreement
With the basic architecture in place, we can begin to complete some of the superstructure, developing a set of protocol apis that are truly open to the business side to complete the package.
First we can divide these protocols into functional protocols and business protocols.
Function of agreement
This kind of protocol refers to some general protocols used to improve the basic functions of the whole scheme. With command:// as the general header, it is encapsulated in SDK and can be used in the whole App and the whole WebView:
1. Initialize the mechanism
As mentioned in the previous article, due to the asynchronous nature of bridge.js injection, we need the client to notify H5 when the injection is complete.
Here we can specify a generic initialization event, in this case _init_, so that the front end can listen for the entry, similar to the usual DOMContentLoaded:
As you can see, there is a bit of a marker to prevent the event from being fired repeatedly. This is because the client is listening to the WebView’s lifecycle hooks, and operations like iframe cause those hooks to fire multiple times, so you need a layer of defense on both sides.
Next, we can use this event to directly initialize some environment parameters and system information to H5, etc., we use the following:
Similarly, we can agree on more page life cycle events. For example, since the App is often hidden in the background, we can set a life cycle: _resume_, which can be used to tell H5 that the page is active.
Tips: This is where we have the advantage of using the event mechanism as a callback system. We can listen for events in the way we are most used to, and the client can use bridg.fireEvent (‘_init_’, data) directly to trigger events. This enables elegant single-directional interaction between Native -> H5.
2. Package update mechanism
One way the Hybrid module works is to bundle front-end code and build it into the App for the fastest startup performance and offline access. The biggest problem with this approach is updating the code. We can’t manually repackage the code for client replacement every time there is a change, and we lose our hot update mechanism.
Therefore, a new hot update mechanism is needed here, which requires the client/front-end/server to provide corresponding resources and work together to complete the whole process.
Resources:
- H5: Each code package has a unique and increasing version number;
- Native: a service that downloads and decompresses packages to the corresponding directory. The front end can invoke this function using the following protocol.
- Server: provides an interface to obtain the version number and download address of the latest code package online.
Process:
- The front-end update code is packaged and uploaded to the specified server according to the version number.
- Every time the page is opened, H5 requests the interface to obtain the version number of the latest code package online, and compares the version number with the local package. When the version number of the online package is greater than the local package version number, the package download protocol is initiated:
- After the client receives the protocol, it directly downloads the latest code package from the online address, decompresses it and replaces it in the current directory.
With such a mechanism, H5 can be directly packaged and uploaded to the corresponding server after development. In this way, hot updates can be made in real time after the page is opened in the App.
3. Environmental systems and multilingual systems
Often, we divide the project into several different environments that are isolated from each other. Since the Hybrid module is placed in the App, the environment needs to be matched with the App. Here we can directly use the first point above, using the data.env carried in _init_ to match:
Env: 0 – formal environment; 1 – test environment; 2 – Development environment;
Similarly, multiple languages can be matched directly using E.data. language;
Tips:
The environment mechanism is usually used to match the backend environment, the formal environment and the test environment correspond to different interfaces. However, there is a special point here, that is, we need to pay attention to the code package update, the above package update conditions should include three aspects: version number, environment and App version, in different environment and App version, should also be updated to the corresponding latest code package.
4. Event relay station
Since the page is H5 development, and Native may need to control the H5 page, such as the most commonly used scenario:
Android’s Return physical key should be able to roll back when there is a popover or SPA switch, rather than just closing the WebView because it doesn’t have a history.
Similar to this requirement, here we can customize an event center (_eventListeners_) that listens for the entity return key of the client:
5. Data transfer mechanism
In many scenarios, data synchronization between Native and H5 is required. In this case, a data transfer protocol can be formulated using principles similar to the above:
Tips:
Hybrid modules usually need to be entered from the corresponding entry point, so here is a way to optimize:
When the App is started, it first obtains online data, and after entering the WebView, it directly sends it to H5 through _init_ or triggering getData, which can reduce the number of requests and optimize the user experience.
6. Proxy request
The most common one in H5 is requests. Usually we can use Ajax directly, but there are a few tricky issues:
- The most common request is cross-domain;
- Data algorithm encryption;
- User login verification;
Client requests don’t have these problems, so we can delegate our requests to the client and customize four protocols: GetProxy, postProxy, getProxyLogined, postProxyLogined, where the Logined protocol represents that the Logined user’s token and UID parameters are automatically carried on the request for some interfaces that require login information. The good thing about this is that
- H5 does not need to deal with a large number of complex information, do not need to carry out cross-terminal transmission;
- The request exit of H5 and Native can be unified to facilitate processing.
7. More
In addition to these important features, we have the freedom to customize many protocols to make H5 more powerful. Here are some of the features we have customized:
getNetwork
: Obtains the network status.openApp
: Evoke other apps;setShareInfo
withcallShare
: Sharing content to third-party platforms;link
Open the page with a new WebView;closeWebview
: Close WebView;setStorage
δΈgetStorage
: Set and get cache data;loading
: Calls universal Loading on the client;setWebviewTitle
: Set the WebView title;saveImage
: Save the picture to local;- .
More generic protocols can be defined here, and the principle to follow is that this part of the protocol should be the basic function, should be pure and applicable to all business parties. According to the concept mentioned in the previous article, this section is maintained and upgraded as a general purpose SDK and therefore should not be coupled with any logic from the business layer.
Sometimes we come across business logic that needs to be customized, such as in the above project where we algorithmically processed user images into cartoons. This requirement is very businesslike and does not apply to any other project, so we should customize the business agreement.
Business agreement
These protocols differ from functional protocols in that they combine a certain amount of business logic that is specific to a particular project. In fact, for the use of H5, there is no big difference, but the corresponding special protocol header is used to distinguish, for example:
This kind of protocol is usually not included in the SDK, so the client needs to customize the WebView of the project, and use the basic functions provided by Bridge-js to realize the corresponding complex functions. These protocols are not available in other project entries.
conclusion
See summary two words, have long relieved. π . Through these two articles, we have finally completely deconstructed the front end of the Hybrid scheme. Do you feel refreshed and ready to start your Hybrid journey right away? Clap!! π π π!!!!!
But this is far from the end, or it will never end. After the building is completed, it is still a step away from a real skyscraper — interior decoration. In fact, we still need to do a lot of optimization measures to solve some remaining problems. In fact, we are still working on this part.
Limited by space, I will write an optimization article for this part when I have time, mainly to discuss with you some optimization programs we can think of, and I am looking forward to the leaders can also provide us with more suggestions and solutions. Gratitude ~ ~ π
More articles touch me or follow the public number to read. π» π» π»