Design and practice of Android component frame

Source: Internet
Author: User

In the current era of mobile internet, each app is a traffic portal, and in the past, unlike the PC Web browser era, the experience and iteration speed of the app affect the user's stickiness, which also puts forward higher requirements for the mobile developers, and the mobile end framework is endless.

Shows a comparison of the traditional service-side architecture and the client APP architecture. The traditional service-side architecture is at the bottom of an OS, generally Linux, the top service side of the business, and in the middle there are a lot of layers in the architecture, in accordance with our intention to build a link between the various levels, so that the architecture has sufficient flexibility and scalability. But the app will face a completely different situation, the app's OS (Android or iOS) is not a very thin Linux-like OS, but there is a heavy app Framework on the OS, The vast majority of interfaces that are used to develop a common client application are in the Framework, and the business on top is a very complex and diversified business, and eventually the "architecture" is a very awkward sandwich in the middle because there are many challenges that are not required in the service-side architecture. For example, the following two points:

    • Volume constraints. Volume is a very sensitive concept for the user, and if we are going to do a lot of things on the architecture, it usually means that the amount of code that the architecture occupies is larger. In the server-side architecture we can tolerate dozens of trillion of code at the architectural level. But for the client-side architecture, even if your schema is only one or two trillion, for a client it may occupy 10%,20% capacity.
    • Performance challenges. In terms of performance, we typically focus on throughput rates for server-side architectures, and we don't focus on startup speed. A server start-up takes two minutes, as long as it works well enough, the concurrency is good enough, the response is fast enough, and we think it's a good architecture. But the client is different, the client's process for the user, is often a stack state, the phone inside the use of an application, after exiting may not be long before it will be recycled, when the user next open, it will start the process again, you need to re-complete the initialization process. If you do a lot of things on this, it will cause the program to start very slowly, in the view of many users, this is an unacceptable user experience.

Client APP and server side in the architecture is a certain difference, in the choice of client architecture needs to be treated with caution, there is a lot of tradeoff between the conditions, on this premise, whether there is a way, can divide and conquer, parallel development, separates the business into a separate component, the entire architecture around the component development, Build is also a component, everything is a component. The answer is yes, that is to build the client component framework.

Origin, why component

Client app itself in rapid development, the app version is constantly iterative, new features continue to increase, the number of business modules is increasing, the business process logic is becoming more complex, and each module code also become more and more, this raises a problem, the maintenance of code costs more and more high, a slight change may be reaching , a small function point needs to be returned to the entire APP test, which poses a great challenge to development and maintenance. At the same time the original app architecture mode is a single engineering model, business scale expansion, with the increase in the size of the team, that involves multi-person collaboration issues, each mobile software developer is bound to be familiar with so many code, if not according to a certain module component mechanism to divide, it will be difficult to collaborate with many people to develop, As a single project becomes larger, and the Andorid project becomes very slow in compiling code, it can be very time-consuming and, most importantly, a code that wants to do a unit test without having to recompile a package test after each code change is severely coupled. So there has to be a more flexible architecture to replace the past single engineering model.

The same problem in our work on specific projects everywhere encountered, take our group in charge of a mobile APP, encountered the following issues:

    1. Code volume expansion, not conducive to maintenance, not conducive to the development of new features.
    2. Project construction is slow, write two lines of code on some computers, recompile the test at least 10-20 minutes, some even longer.
    3. The code coupling between different modules is serious, such as the message module seriously coupled video module, if the video module changes, the corresponding message module needs to be modified, otherwise it will produce a series of problems.
    4. Each module has a reference to a third-party library, but some third-party library versions are inconsistent, resulting in code redundancy when packaging apps, which can easily cause version conflicts.
    5. Some custom projects do not need to be loaded on demand if only the message modules are needed, as the modules are interconnected.
    6. Existing projects based on other people's projects on the basis of the development, handling of excessive number of times, there are different code style, the project code is disorderly, similar function of the wording is not the same, resulting in a non-uniform.

The change of project engineering structure mode is the trend, so what should we do? That is: to build a modular development framework to address the problems that are currently facing, before explaining how to build, you need to talk about the concept of components, what the component framework is.

Concept, what is the component of

Q: What is a component and what is a component?

A: In the area of software development, components (Component) are simple packages of data and methods, single-function, cohesion-poly, and are the smallest granularity that business can divide. A common example of our life is the computer motherboard on each component capacitor, each component responsible for a single, easy to assemble, Plug and Play, but the role of limited, need a certain dependency conditions to be used. Such as:

Then again, the component is based on the purpose of reusable components, a large software system in the form of separation of concerns, split into multiple independent components, so that the entire software system as a circuit board, is a single or multiple component components assembled, which component is broken, the entire system can continue to run , without the occurrence of crashes or anomalies, to achieve less coupling and higher cohesion.

Q: What is the difference between component-and modular-confusing?

A: modularity is a program according to its function to split, divided into separate modules, so that each module only contains its function-related content, modules we are relatively familiar with, such as the login function can be a module, the search function can be a module and so on. Component is more attention to reusability, more attention to separation, if from a set point of view, it can be said that often a module contains one or more components, or the module is a container, assembled by the component. Simply put, the modularity is smaller than the modular granularity, both of the essence of the idea are consistent, are to the small direction of splitting, are for reuse and decoupling, but the modular more focused on the division of business functions, biased towards reuse, the component more focused on the single function of the cohesion, in favor of decoupling.

Q: What are the benefits of component?

A: simply to improve efficiency and liberate productivity, the benefits are as follows:

    • Simple code, less redundancy, easy maintenance, easy to expand new features.
    • Improve the speed of compilation, thus improving the efficiency of parallel development.
    • Avoid the cross-dependence between modules to achieve low coupling and high cohesion.
    • Referenced third-party library code Unified management, avoid version unification, reduce the introduction of redundant libraries.
    • Custom projects can be loaded on demand, and components can be flexibly assembled to quickly generate different types of custom products.
    • Develop the corresponding component development specification, can promote the code style specification, the wording unify.
    • System-level control is refined to component-level control, and complex systems are built into components.
    • Each component has its own independent version, which can be compiled, tested, packaged, and deployed independently.
Design, build a modular framework

Back to the beginning of the app single project mode, see Zhang Common App single project schema diagram:

is currently more commonly used in the Android APP technology architecture, often in an interface with a large number of business logic, and business logic is flooded with various network requests, data manipulation and other behaviors, the whole project also does not have the concept of modules, only a simple business logic to divide the folder, And the business is also directly between the call, highly coupled together. The business relationship under a single engineering model is generally: you have me, I have you, interdependent, unable to separate. Such as:

The guiding ideology of component is: divide and conquer, parallel development, all components. To implement the component, regardless of the technical approach, the following seven aspects need to be considered:

    1. Code decoupling. How to divide a huge project into organic whole?
    2. Component to run separately. Because each component is highly cohesive and is a complete whole, how do you make it run and debug separately?

    3. Communication between components. Since each component's implementation details are not known to each other, but each component needs to provide services to other callers, how does the communication between the master project and the component, component, and component become critical?
    4. UI jumps. UI jumps refer to Special data transfer, which differs from communication between components.
    5. The component life cycle. The life cycle here refers to the time that the component exists in the application, whether the component can be used on demand, dynamically, and therefore involves management issues such as component loading and unloading.
    6. Integrated debugging. How do I compile components on demand during the development phase? There may be one or two components participating in the integration in a single debug, so that the compilation time is greatly reduced and the development efficiency is increased.
    7. Code isolation. If the interaction between components is directly referenced, then the components are not decoupled at all, how to fundamentally avoid the direct reference between components, that is, how to fundamentally eliminate the generation of coupling?

Component Architecture Objective: To say goodbye to the bloated structure, to make each business relatively independent, business components can be independently developed in the component mode, and in the integrated mode can become the AAR package integrated into the "APP Shell project" to form a full-featured app.

First give the frame design diagram, and then the seven questions to answer each.

As you can see, the business components are independent and unrelated to each other , and these business components are libraries in the integrated mode, which are relied on by the app Shell to form an app with full business functions, but in component development mode, business components become Application, they can be developed and debugged independently, because in the component development model, the code volume of the business components is far worse than the complete project, so the compile time can be significantly reduced at run time.

Each business component communicates via route forwarding,

This is the business relationship under the modular engineering model, where the business is no longer directly referenced and dependent, but rather indirectly through a transit station such as "Routing".

Then the above seven questions, the specific solution is as follows:

1, code decoupling problem

Module splitting of existing projects, the module is divided into two types, one is a functional component module, encapsulating some public method services, as a dependent library to provide external, one is the Business component module, specialized in business logic and other functions, these business components module is responsible for the final assembly of the app.

2, component run-alone issue

Different environments are switched by Gradle script configuration mode. For example, just need to apply plugin: ' com.android.library ' switch to apply plugin: ' Com.android.application ' can, and also need in androidmanifest The manifest file is set up because a single debug requires an entry Activity. For example, set a variable ismodule, whether the current need to debug separately, based on the value of IsModule, using different Gradle plug-ins and androidmanifest manifest files, and even can add application and other Java files, So that you can do the initialization operation.

3, inter-component communication issues

Communication between components is done through the interface + implemented structure. Each component declares its own service provider API, which is a number of interfaces that are responsible for implementing and registering these services in a unified routing Router, and if you want to use the functionality of a component, simply request this service from Router Implementation, specific implementation details we do not care, as long as we can return to the results we need. In the component architecture design diagram, the Common component contains the routing service component, which includes the routing entries and jumps for each component.

4,ui Jump Problem

It can be said that UI jumps are also a kind of communication between components, but belong to the more special data passing. However, the general UI jump basically will be processed separately, generally by short-chain way to jump to specific Activity. Each component can register the scheme and host of the short chain that it can handle, and define the format of the transmitted data, and then register it in the Unified Uirouter, Uirouter is responsible for distributing the route through Scheme and Host matching relationships. However, the current mainstream approach is to create specific logic codes through APT by adding annotations to each Activity. The current way is to refer to the Arouter framework of Ali, through the annotated way page jump.

5, Component life cycle issues

The core management component in the architecture diagram defines a component lifecycle interface that, by setting up a configuration file in each component, is automatically generated at compile time by using annotations, and the implementation class that specifies the specific implementation component lifecycle interface in the configuration file. To complete the component some need to initialize the operation and do automatic registration, there is no way to provide manual registration.

6, integrated debugging issues

Individual debugging of each component does not mean that integration is not a problem, so in the late stages of development we need to integrate several component machines into one APP to verify. Due to the previous steps to ensure the isolation between components, so you can choose a few components to participate in the integration, this on-demand loading mechanism can ensure that the integration debugging has great flexibility, and can increase the speed of the compilation. It is important to note that after each component has been developed, it is necessary to set IsModule to True and synchronize so that the main project can be compiled uniformly by parameter configuration.

7, Code isolation issues

If you are still compile project (Xxx:xxx.aar) to introduce a component, we can use it directly into the implementation class, then the coupling between the master project and the component is not eliminated, and the programming of the interface becomes meaningless. We want to introduce AAR only when Assembledebug or assemblerelease, and in the development phase, all components are invisible, which fundamentally eliminates the problem of referencing the implementation class.

The current practice is that the master project relies only on Common's dependent libraries, the business components are searched on demand through the routing service Dependency library, the component is loaded by reflection, then the Component Services are invoked in the main project, the calls between components and components are communicated through the interface + implementation, and subsequent planning is through the custom Gradle plugin. The dependency of the bytecode auto-insert component is compiled and packaged, and the Assembledebug or assemblerelease are automatically filtered to compile the task, only the commands that contain these two tasks are introduced into the concrete implementation class, others are not introduced.

Code, concrete Project Practice

First, create the project

1,app Empty Shell Project

Create an app shell project through Androidstudio,

Then add dependencies to the specific business component module in the APP project. Like what:

2, specific business component module

There is a need to follow a certain component naming convention, why the specification is required, because the component naming conventions are required to constrain and ensure the uniformity and consistency of components to avoid conflicts. For example, the login component, then the name: B (Type)-GA (department abbreviation)-login (component name), which we named based on a common convention, for the subsequent maintenance and expansion of the identification.

Two, business component configuration file

1,build.gradle Configuration Text modification. As follows:

if(IsModule.ToBoolean()) {Apply plugin: ' com.Android.Application'}Else{Apply plugin: ' com.Android.Library'}android {compilesdkversion rootproject.ext.compilesdkversionBuildtoolsversion Rootproject.ext.buildtoolsversionDefaultconfig {minsdkversion rootproject.ext.minsdkversionTargetsdkversion Rootproject.ext.targetsdkversion        if(IsModule.ToBoolean()) {ApplicationID"Com.hik.ga.business.login"Versioncode1Versionname"1.0"}Else{//arouterjavacompileoptions {annotationprocessoroptions {arguments = [modulename:project.GetName()]}}}} sourcesets {main {if(IsModule.ToBoolean()) {manifest.Srcfile' Src/main/module/androidmanifest.XML'            }Else{manifest.Srcfile' Src/main/androidmanifest.XML'//Integrated development mode excludes all Java files in the Debug folderjava {exclude ' debug/**'                }            }        }    }Buildtypes {Release {minifyenabled falseproguardfiles getdefaultproguardfile (' proguard-android.txt '), ' Proguard-rules.pro '        }    }}Dependencies {implementation project (': B-ga-common-function-comlib ')if (!ismodule.toboolean ()) {annotationprocessor "Com.alibaba:arouter-compiler:${rootproject.annotationprocessor}"    }}

Here are a few things to note:

1, through the Ismodule.toboolean () method to switch between components integration mode and component mode, including whether the module belongs to the application or the Library, because the integration of Arouter, so the Arouter configuration file needs to be processed.

2, if the component mode, you need to reset the Androidmanifest.xml file, inside the configuration of the new application path. For example, the login component runs the androidmanifest manifest file separately

<manifest xmlns:android="Http://schemas.android.com/apk/res/android"     Package= "Hik.ga.business.applogin" > <application android:name="Debug. Loginapplication "android:allowbackup="false"android:icon="@mipmap/ic_launcher"Android:label="@string/login_btn_str"Android:supportsrtl="true"Android:theme="@style/theme.appcompat.light.noactionbar"> <activity android:name="Hik.ga.business.applogin.login.views.LoginActivity"Android:label="@string/login_btn_str"Android:launchmode="Singletop"android:screenorientation="Portrait"Android:theme="@style/apptheme.noactionbarfullscreen"> <intent-filter> <action android:name="Android.intent.action.MAIN"/> <category android:name="Android.intent.category.LAUNCHER"/> </intent-filter> </activity> </application></manifest>

3, implement the component global application configuration class, the purpose of this class is to initialize some component's own resources when the component is loaded, as follows:

 Public classLoginapplicationdelegateImplementsiapplicationdelegate {Private Static FinalString TAG ="Loginapplicationdelegate";@Override     Public void onCreate() {Eflog.D(TAG,"*------------------onCreate ()---------------->"); }@Override     Public void Enterbackground() {Eflog.D(TAG,"*------------------enterbackground ()---------------->"); }@Override     Public void Enterforeground() {Eflog.D(TAG,"*------------------enterforeground ()---------------->"); }@Override     Public void receiveremotenotification(map<string, string> message) {Eflog.D(TAG,"receiveremotenotification msg ="+ message); }@Override     Public void onterminate() {Eflog.D(TAG,"*------------------onterminate ()---------------->"); }@Override     Public void onconfigurationchanged(Configuration Configuration) {Eflog.D(TAG,"*------------------onconfigurationchanged ()---------------->"); }@Override     Public void onlowmemory() {Eflog.D(TAG,"*------------------onlowmemory ()---------------->"); }@Override     Public void ontrimmemory(intVAR1) {Eflog.D(TAG,"*------------------ontrimmemory ()---------------->"); }}

Third, the routing service

1, define common component routing APIs and portals, find through routing service components,

2, Component routing implementation

What capabilities each component provides externally requires first creating an interface file in the Routing service component, which is the login component interface declaration and implementation.

Login Interface:

Specific implementation:

Routing use: for example, we want to jump from the settings page to the landing page, using the Login interface method, using the following:

ILoginProvider loginService = (ILoginProvider) ARouter.getInstance().build(RouterPath.ROUTER_PATH_TO_LOGIN_SERVICE).navigation();ifnull){    loginService.accountToLogin(AccountActivity.this);}
Summary

In general, by applying a component-based framework, the specific projects in our work are made lighter, assembled, and built faster, not only to improve productivity, but also to improve the awareness of mobile application development. Because the modular framework is versatile, it is a good solution for large and medium-sized projects where business modules are iterative and large-scale. As for the evolutionary path after the modular framework, it is to build the component warehouse, perfect the component development specification, enrich the Component function library, some granular business components can be further refined, the component functions more single cohesion, and based on the existing modular framework, easy to build a plug-in framework in the future, to further upgrade the APP Dynamic capabilities, such as unloading, hot fixes, and so on, are another use scenario and design architecture, in fact, the biggest difference between the component and the plug-in framework is the ability to dynamically update.

Simplify the project, GitHub address: democomponent, interested can go down to see.

Reference article:

1,android Modular Solution

Practice of 2,android Complete assembly scheme

Android Modular framework design and practice

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.