Androidコンポーネント化の予備調査-この記事では、暗闇まであなたを連れて行きます

概要

ソフトウェア開発プロセスは、アーキテクチャの進化プロセスでもあります。Androidを例にとると、最初のMVC、MVP、MVVPから、後のコンポーネント化とプラグインまでですが、最終的な分析では、すべてがプロジェクトのメンテナンスを改善するためのものです。 、反復、開発コストを削減します。

プロジェクトの開発プロセスでは、すべての機能モジュールを早い段階でモジュールに入れて迅速に開発できるようにする場合がありますが、プロジェクトが成長し、開発者と機能の数が増えると、コードはますます多くなりますより肥大化すると、さまざまなモジュール間の結合がますます重くなり、全身が影響を受けます。このとき、プロジェクトの品質を確保するために、プロジェクトをリファクタリングする必要があります。

ビジネスモジュールに応じてチェックとスコアリングを行い、さまざまなビジネスモジュールをさまざまなモジュールに配置し、各ビジネス間の構造を実現できます。また、基盤となる公共図書館にも依存しています。これはモジュール性の概念ですが、複数のモジュールが関係する場合は同じ機能に達すると、コードの結合が増加します。たとえば、ビデオ再生の機能を必要とするモジュールが2つあります。ビデオ再生を2つのコンポーネントに配置すると、コードの重複の問題が発生し、感じません。公共図書館に置くのはとても良いです。現時点では、この問題を解決するためにコンポーネント化が使用されています

モジュール式でコンポーネント化

基本単位

製品詳細モジュール、製品リリースモジュール、検索モジュールなどの特定のビジネスモジュール

コンポーネント化

ビデオ再生コンポーネント、共有コンポーネントなどの単一の機能コンポーネント。各コンポーネントは個別のモジュールとして開発でき、外部リリース用のSDKとして個別に抽出できます。

モジュール化とコンポーネント化の考え方は同じで、どちらもコード分割ですが、モジュール化は機能モジュール(ビジネス指向)に基づいており、コンポーネント化は機能モジュール(機能指向)とモジュール式粒子に基づいていますモジュールとコンポーネントがプロジェクト内で共存することも一般的であり、それぞれが独自の業務を担当します。

image

画像

上図に示すように、コンポーネント化されたプロジェクトの基本構造です。

  • 基本ライブラリとパブリックライブラリ:基本操作クラス、ツールクラス、サードパーティライブラリの紹介とパッケージ化、アプリホスティング機能、プロジェクトに必要なモジュールとコンポーネントは、このライブラリに依存します
  • 组件层:项目用的功能模块或者业务模块,如:登录模块,视频播放组件,分享组件等
  • 应用层:宿主工程,APP的主项目,APP入口和主架子

组件化Demo

地址如下: github.com/syg13579/as… 我根据demo项目从以下几个方面来讲解

  • 1:项目分析
  • 2:组件application和library动态切换
  • 3:组件间的数据传递和方法调用
  • 4:组件类(例如:Fragment)的获取,以及夸组件页面跳转和通讯

1:项目分析

image

image

如上图所示,项目的主要结构

  • 应用层:app 项目的主入口
  • 组件层:goods login 商品详情页和登录组件
  • 基础库层:assemblebase用来各个组件数据和方法交互的 ,base是常用的工具类,各种类库的封装

2:组件application和library动态切换

在开发过程中,为了能够实现快速开发,组件能够独立运行就显的特别重要,moudle一般分为两种

  • App 插件,id: com.android.application
  • Library 插件,id: com.android.library

我们可以通过配置可动态进行application和library的切换,我们在各个组件的gradle.properties文件中配置一个控制切换的变量

image

image

然后在build.gradle中就可以通过isRunAlone变量来进行application和library的切换了,主要设计的点有三部分

  • plugin属性的配置
  • applicationId的配置
  • 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"
        }
        minSdkVersion 15
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "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'
            }
        }
    }

}
复制代码

如果以上配置就可以实现application和library的切换了

3:组件间的数据传递和方法调用

由于主项目、组件之间,组件和组件之间不能直接通过引用进行数据传递和方法调用,那么在开发的过程中怎么进行数据传递和方法调用呢,可以通过「接口」+「实现」的方式进行,

assemblebase基础库就是用来进行数据传递和方法调用的,它被所有组件所依赖,assemblebase提供各个组件对外提供数据和方法调用的抽象service ,同时还有serviceFactory对service进行操作,各个组件在初始化的时候对各自的service进行实现。同时中也会提供所有的 Service 的空实现,以避免引起的空指针异常

就以登录模块为例,对外提供两个数据

public interface ILoginService {

    /**
     * 是否已经登录
     *
     * @return
     */
    boolean isLogin();

    /**
     * 获取登录用户的 AccountId
     *
     * @return
     */
    String getAccountId();

}
复制代码

相关的serviceFactory类如下,可以通过serviceFactory拉取相关service的实例

public class ServiceFactory {

    private ILoginService loginService;
    private IGoodsService goodsService;

    /**
     * 禁止外部创建 ServiceFactory 对象
     */
    private ServiceFactory() {
    }

    /**
     * 通过静态内部类方式实现 ServiceFactory 的单例
     */
    public static ServiceFactory getInstance() {
        return Inner.serviceFactory;
    }

    private static class Inner {
        private static ServiceFactory serviceFactory = new ServiceFactory();
    }

//    ------------------------LoginService------------------------
    /**
     * 接收 Login 组件实现的 Service 实例
     */
    public void setLoginService(ILoginService loginService) {
        this.loginService = loginService;
    }

    /**
     * 返回 Login 组件的 Service 实例
     */
    public ILoginService getLoginService() {
        if (loginService == null) {
            loginService = new EmptyLoginService();
        }
        return loginService;
    }
复制代码

在login组件中只需要实现ILoginService,并通过serviceFactory进行设置

public class LoginService implements ILoginService {
    @Override
    public boolean isLogin() {
        return false;
    }

    @Override
    public String getAccountId() {
        return null;
    }
}
复制代码

在login的appliction中进行service的设置

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) {

    }
}
复制代码

但是有这样一个问题:在集成到app中,LoginApp是没有被执行的,这个怎么解决呢,我们可以通过反射进行解决

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 application) {

    }

    //初始化组件
    //通过反射初始化
    private void initComponentList(){
        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();
            }
        }
    }

}
复制代码

如上所示就完成了

4:组件类(例如:Fragment)的获取,以及夸组件页面跳转和通讯

fragment的获取也是通过service来完成的

public interface IGoodsService {

    /**
     * 创建 GoodsFragment
     * @param bundle
     * @return
     */
    Fragment newGoodsFragment(Bundle bundle);
}
复制代码

相关组件实现该接口就行

各个组件间页面的跳转可以通过阿里的ARouter实现,我是通过设置ComponentName来实现的,但这种方式好像并没有实现真正的代码隔离

 /**
     *
     * 去登陆
     *
     * 跨组件页面跳转
     */
    private void toLogin(){
        Intent intent = new Intent();
        intent.setComponent(new ComponentName(mContext, "ppzh.jd.com.login.LoginActivity"));
        startActivityForResult(intent,LOGIN_REQUEST_CODE);
    }
复制代码

总结

通过上面就整体实现了项目组件化,在以后也可以更多的运用组件化来进行项目开发

本博主会持续更新Android学习知识,更多学习知识以及笔记请查看我的Gitee.

おすすめ

転載: juejin.im/post/6988015894119055367