An overview of the

Software development process is also the evolution process of architecture. Take Android for example, from the beginning of MVC,MVP and MVVP, to the later componentization and plug-in, but in the final analysis, everything is for better maintenance and iteration of the project, and to reduce the development cost.

Early in a project’s development process, we can put all the function modules in a moudle, so quick development, but as projects grow, the increase of the developers and the function, returned to cause code is more and more bloated, and the coupling between modules is getting heavier and heavier, single point, this time in order to ensure the quality of the project, We need to refactor the project.

We can undertake check grade according to the business module, put different business modules in the different moudle, between various business structure, they also rely on the underlying common public library, this is the concept of modularity, but when it comes to the same function code in multiple modules coupling increases, for example, there are two modules need video playback function, Componentization is a solution to the duplication of code that occurs when video playback is placed in two components and does not feel good in a common library

Modularity and componentization

modular

Specific business modules, such as commodity details module, commodity release module, search module

componentization

Single functional components, such as video playback components, sharing components, and so on, each component can be developed as a separate module, and can be extracted as an SDK for external use

Modular and modular thought is the same, is to take apart the code, but is modular check grade according to the functional modules (business), check grade componentization is according to the functional modules (function), modular bigger, the particle size, particle degree of the component smaller, a project of modules and components exist at the same time also is very common, each responsible for their own things

image

The basic architecture of a componentized project is shown in the figure above

  • Basic libraries, common libraries: basic operation classes, utility classes, introduction of third-party libraries, app hosting functions, modules, and components required by the project depend on this library
  • Component layer: functional module or business module used by the project, such as: login module, video playback component, sharing component, etc
  • Application layer: host project, APP’s main project, APP entry and main shelf

Componentization Demo

The address is: github.com/syg13579/as… I will explain the following aspects according to the demo project

  • 1: Project analysis
  • 2: Dynamic switch between application and library components
  • 3: Data transfer and method invocation between components
  • 4: Obtaining component classes (for example, Fragment), and kua component page jump and communication

1: Project analysis

image

The main structure of the project is shown in the figure above

  • Application layer: The main entry for the app project
  • Component layer: Goods Login Product details page and login component
  • Base: AssembleBase is used to interact with the data and methods of various components. Base is a common tool class, the encapsulation of various class libraries

2: Dynamic switch between application and library components

In the development process, in order to be able to achieve rapid development, components can run independently on the particularly important,moudle is generally divided into two kinds

  • App plug-in, ID: com.android.application
  • Library plugin, id: com.android.library

We can dynamically switch between application and library by configuring a variable in each component’s Gradle. properties file to control the switch

image

In build.gradle, you can use the isRunAlone variable to switch between application and library. There are three main design points

  • Plugin property
  • ApplicationId configuration
  • The configuration of AndroidManifest
if (isRunAlone.toBoolean()) { apply plugin: 'com.android.application' } else { apply plugin: 'com.android.library' } android { compileSdkVersion 26 defaultConfig { if (isRunAlone.toBoolean()) { applicationId "Ppzh.jd.com.goods}" 15 targetSdkVersion 26 versionCode minSdkVersion 1 versionName testInstrumentationRunner "1.0" "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } sourceSets { main { if (isRunAlone.toBoolean()) { manifest.srcFile 'src/main/manifest/AndroidManifest.xml' } else { manifest.srcFile 'src/main/AndroidManifest.xml' } } } }Copy the code

The above configuration will enable the switch between Application and Library

3: Data transfer and method invocation between components

Since data transfer and method invocation between main project, components, and components cannot be carried out directly by reference, how to carry out data transfer and method invocation during the development process can be carried out by “interface” + “implementation”.

The base assembleBase library is used for data transfer and method invocation. It is relied on by all components. It provides an abstract service for each component to provide data and method invocation. Each component implements its own service when it is initialized. It also provides null implementations for all services to avoid null-pointer exceptions

Take the login module as an example to provide two data

Public interface ILoginService {/** * whether you have logged in ** @return */ Boolean isLogin(); /** * getAccountId ** @return */ String getAccountId(); }Copy the code

The related serviceFactory classes are as follows. You can use the serviceFactory to pull instances of related services

public class ServiceFactory { private ILoginService loginService; private IGoodsService goodsService; /** * Disable external creation of ServiceFactory objects */ private ServiceFactory() {} /** * Implement the ServiceFactory singleton using a static inner class */ public static ServiceFactory getInstance() { return Inner.serviceFactory; } private static class Inner { private static ServiceFactory serviceFactory = new ServiceFactory(); } / / -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- LoginService -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - / * * * to receive the Login Service instance of component implementation * / public void setLoginService(ILoginService loginService) { this.loginService = loginService; Public ILoginService getLoginService() {if (loginService == null) {loginService = new EmptyLoginService(); } return loginService; }Copy the code

You only need to implement ILoginService in the Login component and set it up through the serviceFactory

public class LoginService implements ILoginService { @Override public boolean isLogin() { return false; } @Override public String getAccountId() { return null; }}Copy the code

Set the service in the Appliction of login

public class LoginApp extends BaseApp {

    @Override
    public void onCreate() {
        super.onCreate();
        initModuleApp(this);
        initModuleData(this);
    }

    @Override
    public void initModuleApp(Application application) {
        ServiceFactory.getInstance().setLoginService(new LoginService());
    }

    @Override
    public void initModuleData(Application application) {

    }
}
Copy the code

However, there is a problem: LoginApp is not implemented when integrated into the app. How can we solve this problem by reflection

public class AssembleApplication extends BaseApp { @Override public void onCreate() { super.onCreate(); initModuleApp(this); initModuleData(this); initComponentList(); } @Override public void initModuleApp(Application application) { } @Override public void initModuleData(Application Private void componentList (){for (String moduleApp: AppConfig.moduleApps) { try { Class clazz = Class.forName(moduleApp); BaseApp baseApp = (BaseApp) clazz.newInstance(); baseApp.initModuleApp(this); baseApp.initModuleData(this); } catch (Exception e) { e.printStackTrace(); }}}}Copy the code

That’s it, as shown above

4: Obtaining component classes (for example, Fragment), and kua component page jump and communication

Retrieving fragments is also done through services

Public interface IGoodsService {/** * Create GoodsFragment * @param bundle * @return */ Fragment newGoodsFragment(bundle bundle); }Copy the code

The relevant component implements the interface

The jump between the various components of the page can be implemented through the ARouter Ali, I am by setting ComponentName to achieve, but this way does not seem to achieve real code isolation

Private void toLogin(){Intent Intent = new Intent(); private void toLogin(){Intent Intent = new Intent(); intent.setComponent(new ComponentName(mContext, "ppzh.jd.com.login.LoginActivity")); startActivityForResult(intent,LOGIN_REQUEST_CODE); }Copy the code

conclusion

Through the above, the overall realization of the project componentization, in the future, we can also use more componentization to carry out project development

This blog will continue to update Android learning knowledge, more learning knowledge and notes please check myGitee.