熟练使用组件化开发,路由配置
学习内容:
**在使用组件化开发前首先要明确项目整体框架,划分模块及业务(重点),好的开始才会有好的结果。**模块划分明确后开始配置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组件化开发详解所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)