新手避坑指南:Android组件化开发详解

新手避坑指南:Android组件化开发详解,第1张

概述学习目标:熟练使用组件开发,路由配置学习内容:**在使用组件化开发前首先要明确项目整体框架,划分模块及业务(重点),好的开始才会有好的结果。**模块划分明确后开始配置Module。如图我们要完成以下功能:1.点击商城进入ShoppingModule2.点击登录进入LoginModule3.点击账单红色 学习目标:

熟练使用组件化开发,路由配置


学习内容:

**在使用组件化开发前首先要明确项目整体框架,划分模块及业务(重点),好的开始才会有好的结果。**模块划分明确后开始配置Module。

如图我们要完成以下功能:

1.点击商城进入ShopPingModule

2.点击登录进入LoginModule

3.点击账单红色区域展示账单列表(其他Module中的Fragment)

(shareModule为公共模块)

根据业务需求创建如下:

在App的gradle.propertIEs文件下添加,用于控制module是否独立运行。

#配置某个组件是否可以独立运行isShopPingRunAlone = trueisLoginRunALone = true

 

然后配置App build.gradle。

apply plugin: 'com.androID.application'apply plugin: 'kotlin-androID'apply plugin: 'kotlin-android-extensions' androID {    compileSdkVersion 30    buildToolsversion "29.0.3"     defaultConfig {        applicationID "com.example.moduledemo"        minSdkVersion 16        targetSdkVersion 30        versionCode 1        versionname "1.0"         testInstrumentationRunner "androIDx.test.runner.AndroIDJUnitRunner"    }     buildTypes {        release {            MinifyEnabled false            proguardfiles getDefaultProguardfile('proguard-androID-optimize.txt'), 'proguard-rules.pro'        }    }} dependencIEs {    implementation filetree(dir: "libs", include: ["*.jar"])    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"    implementation 'androIDx.core:core-ktx:1.3.0'    implementation 'androIDx.appcompat:appcompat:1.1.0'    implementation 'androIDx.constraintlayout:constraintlayout:1.1.3'    testImplementation 'junit:junit:4.12'    androIDTestImplementation 'androIDx.test.ext:junit:1.1.1'    androIDTestImplementation 'androIDx.test.espresso:espresso-core:3.2.0'     //导入公共模块    implementation project(':ShareModule')     // 根据gradle中的配置来决定是否引用module    if (!isLoginRunALone.toBoolean()){        implementation project(':LoginModule')    }    if (!isShopPingRunAlone.toBoolean()){        implementation project(':ShopPingModule')    } }

      

继续配置其他Module的build.gradle文件。

if (isShopPingRunAlone.toBoolean()){    apply plugin: 'com.androID.application'}else {    apply plugin: 'com.androID.library'}apply plugin: 'kotlin-androID'apply plugin: 'kotlin-android-extensions' androID {    compileSdkVersion 30    buildToolsversion "29.0.3"     defaultConfig {        minSdkVersion 16        targetSdkVersion 30        versionCode 1        versionname "1.0"         testInstrumentationRunner "androIDx.test.runner.AndroIDJUnitRunner"        consumerProguardfiles "consumer-rules.pro"    }     buildTypes {        release {            MinifyEnabled false            proguardfiles getDefaultProguardfile('proguard-androID-optimize.txt'), 'proguard-rules.pro'        }    }    sourceSets{        main{            // 在独立运行或者作为libarary调试时,使用不同的AndroIDManifest.xml文件            if (isShopPingRunAlone.toBoolean()){                manifest.srcfile 'src/main/manifest/AndroIDManifest.xml'            }else {                manifest.srcfile 'src/main/AndroIDManifest.xml'            }        }    }} dependencIEs {    implementation filetree(dir: "libs", include: ["*.jar"])    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"    implementation 'androIDx.core:core-ktx:1.3.0'    implementation 'androIDx.appcompat:appcompat:1.1.0'    testImplementation 'junit:junit:4.12'    androIDTestImplementation 'androIDx.test.ext:junit:1.1.1'    androIDTestImplementation 'androIDx.test.espresso:espresso-core:3.2.0'    //导入公共模块    implementation project(':ShareModule') }

 

在不同运行模式下使用不同的Manifest文件。

需要在对应module的Main目录下新建manifest文件夹(不然单独运行会找不到Manifest文件)。

单独运行的manifest文件设置如下:

<?xml version="1.0" enCoding="utf-8"?><manifest xmlns:androID="http://schemas.androID.com/apk/res/androID"    package="com.example.loginmodule">     <application        androID:allowBackup="true"        androID:icon="@mipmap/ic_launcher"        androID:label="@string/app_name"        androID:roundIcon="@mipmap/ic_launcher_round"        androID:supportsRtl="true"        androID:theme="@style/Apptheme">        <activity androID:name=".LoginActivity">            <intent-filter>                <action androID:name="androID.intent.action.MAIN" />                 <category androID:name="androID.intent.category.LAUNCHER" />            </intent-filter>        </activity>    </application> </manifest>

 

并入主Module运行时manifest文件设置如下:

<manifest xmlns:androID="http://schemas.androID.com/apk/res/androID"    package="com.example.shopPingmodule">     <application>        <activity androID:name=".ShopPingActivity"/>    </application></manifest>

 

 

全部配置完成之后,可以在gradle.propertIEs中修改变量的值,编译查看配置是否正确,manifest文件是否替换。运行查看是否正常。

接下来开始配置路由。

好多人心中有疑惑,在引用Module之后是可以直接获取到子Module的Activity的为什么还要使用路由跳转。是因为组件化开发是为了使单独Module可以独自编译,运行如果主Module引用子Module的类名,当子Module单独运行时主Module会编译异常。

我们要知道一个项目不可能只有一个子Module,当我们其他子Module要进行相互跳转时如何使用路由呢?所以我们要在ShareModule进行路由的配置,在之前的配置中我们将ShareModule导入了每个Module。

第一步

我们创建对应Module的跳转模板

import androID.content.Context;import androID.os.Bundle; import androIDx.fragment.app.Fragment;import androIDx.fragment.app.FragmentManager; public interface ILoginService {    voID launch(Context ctx, String targetClass); }

 

import androID.content.Context;import androID.os.Bundle; import androIDx.fragment.app.Fragment;import androIDx.fragment.app.FragmentManager; public interface IShopPingService {    voID launch(Context ctx, String string);    Fragment newBillFragment(FragmentManager fragmentManager, int vIEwID, Bundle bundle);}

 

第二步

在对应的moudle中实现跳转逻辑及传值 *** 作

package com.example.loginmodule; import androID.content.Context;import androID.content.Intent; import com.example.sharemodule.ILoginService;  public class LoginService implements ILoginService {    @OverrIDe    public voID launch(Context ctx, String targetClass) {        Intent intent = new Intent(ctx, LoginActivity.class);        ctx.startActivity(intent);    }}

 

package com.example.shopPingmodule; import androID.content.Context;import androID.content.Intent;import androID.os.Bundle; import androIDx.fragment.app.Fragment;import androIDx.fragment.app.FragmentManager; import com.example.sharemodule.IShopPingService;  public class ShopPingService implements IShopPingService {     @OverrIDe    public voID launch(Context ctx, String string) {        Intent intent = new Intent(ctx, ShopPingActivity.class);        ctx.startActivity(intent);    }     @OverrIDe    public Fragment newBillFragment(FragmentManager fragmentManager, int vIEwID, Bundle bundle) {        BillFragment fragment = new BillFragment();        fragment.setArguments(bundle);        fragmentManager.beginTransaction().replace(vIEwID, fragment).commit();        return fragment;    }}

 

第三步

接下来我们创建一个ServiceFactory,为我们提供跳转实例,并且处理单独运行时可能会出现的异常

package com.example.sharemodule; public class ServiceFactory {    private static final ServiceFactory instance = new ServiceFactory();     private ILoginService mLoginService;    private IShopPingService mShopPingService;     private ServiceFactory(){}     public static ServiceFactory getInstance() {        return instance;    }     public ILoginService getLoginService() {        if (mLoginService == null){            mLoginService = new EmptyLoginService();        }        return mLoginService;    }     public voID setLoginService(ILoginService mLoginService) {        this.mLoginService = mLoginService;    }     public IShopPingService getSignService() {        if (mShopPingService == null){            mShopPingService = new EmptyShopPingService();        }        return mShopPingService;    }     public voID setSignService(IShopPingService mSignService) {        this.mShopPingService = mSignService;    }}

 

package com.example.mylibrarySharedlibrary; import androID.content.Context;import androID.os.Bundle; import androIDx.fragment.app.Fragment;import androIDx.fragment.app.FragmentManager; public class EmptyLoginService implements ILoginService {    @OverrIDe    public voID launch(Context ctx, String targetClass) {     }     @OverrIDe    public Fragment newUserInfoFragment(FragmentManager fragmentManager, int vIEwID, Bundle bundle) {        return null;    }}

 

package com.example.mylibrarySharedlibrary; import androID.content.Context; public class EmptySignService implements ISignService  {    @OverrIDe    public voID launch(Context ctx, String userID) {     }}

 

这样处理即使我们单独运行主Moudle时也不会发生异常。

以上我们跳转的代码就写完了接下来就是对serviceFactory中

private ILoginService mLoginService;
private IShopPingService mSignService;

进行赋值

package com.example.sharemodule; import androID.app.Application; public interface IComponentApplication {    voID initialize(Application application);}

 

提供统一初始化的接口

package com.example.moduledemo; import androID.app.Application;import androID.util.Log; import com.example.sharemodule.AppConfig;import com.example.sharemodule.IComponentApplication;  public class MainApplication extends Application implements IComponentApplication {    private static Application application;     public static Application getApplication(){        return application;    }     @OverrIDe    public voID onCreate() {        super.onCreate();        initialize(this);    }     @OverrIDe    public voID initialize(Application application) {        for (String cpnt : AppConfig.Components){            try{                Class<?> clz = Class.forname(cpnt);                Object obj = clz.newInstance();                if (obj instanceof IComponentApplication){                    ((IComponentApplication) obj).initialize(this);                }            }catch (Exception e){                Log.e("TAG", e.getMessage());            }        }    }}

 

package com.example.loginmodule; import androID.app.Application; import com.example.sharemodule.IComponentApplication;import com.example.sharemodule.ServiceFactory;  public class LoginApplication extends Application implements IComponentApplication {     private static Application application;     public static Application getApplication(){        return application;    }     @OverrIDe    public voID onCreate() {        super.onCreate();    }     @OverrIDe    public voID initialize(Application app) {        application = app;        ServiceFactory.getInstance().setLoginService(new LoginService());    }}

 

package com.example.shopPingmodule; import androID.app.Application; import com.example.sharemodule.IComponentApplication;import com.example.sharemodule.ServiceFactory;  public class ShopPingApplication extends Application implements IComponentApplication {    private static Application application;     public static Application getApplication() {        return application;    }     @OverrIDe    public voID onCreate() {        super.onCreate();     }     @OverrIDe    public voID initialize(Application app) {        application = app;        ServiceFactory.getInstance().setSignService(new SignService());    }}

 

package com.example.sharemodule; public class AppConfig {    public static final String[] Components = {            "com.example.shopPingmodule.ShopPingApplication",            "com.example.loginmodule.LoginApplication"    };}

 

进入App时进行初始化,通过反射获取子Module的Application实例进行初始化。

最终结果:

本文在开源项目:https://github.com/Android-Alvin/Android-LearningNotes 中已收录,里面包含了AndroID组件化最全开源项目(美团App、得到App、支付宝App、微信App、蘑菇街App、有赞APP…)等,资源持续更新中…

   总结

以上是内存溢出为你收集整理的新手避坑指南:Android组件化开发详解全部内容,希望文章能够帮你解决新手避坑指南:Android组件化开发详解所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1052481.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-25
下一篇 2022-05-25

发表评论

登录后才能评论

评论列表(0条)

保存