赞
踩
Demo地址:https://github.com/751496032/ComponentDemo
本文是续上一篇Android组件化方案实践与思考文章一些思考,主要是针对组件间通信,比如:
这些问题是我们在组件化过程中都会遇到问题,在项目中肯定远远还不止这些问题,在这样我遇到的问题记录下来,有不对的地方希望大家多多指点!!
常规下我们都会把一些库、第三方SDK等等的初始化工作放在Application中初始化,在组件化思想中,每个业务组件是不存在任何依赖关系的,都可以单独运行,是一个同级关系,每个组件都有一个Application,在组件合并组合时,在Mainfest只允许声明一个Application类,哪如何做到初始化Main的Application,其他组件中的Application同步初始化数据,我的方案是:
1、在BaseApp中定义一个抽象方法,每个组件的Application都必须重写该方法
public abstract class BaseApp extends MultiDexApplication {
public abstract void initModuleApp(Application application);
}
2、接着每个组件的Application继承于BaseApp,重写initModuleApp
方法,同时在其方法中初始化每个组件需要的数据,如下
public class HomeApp extends BaseApp { private Context mContext; /** * 在onCreate中初始化是组件独立运行时用来初始化 * 在合并组合时是不会调用onCreate */ @Override public void onCreate() { super.onCreate(); this.mContext=this; } /** * 合并组合时初始化数据 * @param application */ @Override public void initModuleApp(Application application) { mContext=application.getApplicationContext(); Log.d(TAG,"HomeApp 初始化数据"); }
这里只贴一个组件的Application的代码,其他组件类似。
3、最后一步很重要,在Main的Application中通过反射获取每个组件的Application实例,通过实例来调用initModuleApp
函数,在这里我定义AppConfig类用来管理每个组件的Application类名
public class AppConfig {
public static final String[] apps={"com.hzw.home.HomeApp",
"com.hzw.cart.CartApp",
"com.hzw.me.MeApp",
"com.hzw.login.LoginApp"};
}
public class App extends BaseApp { @Override public void onCreate() { super.onCreate(); initModuleApp(this); } /** * 通过反射调用每个组件的initModuleApp函数 * @param application */ @Override public void initModuleApp(Application application) { for (String appClassName:AppConfig.apps){ try { Class<?> name = Class.forName(appClassName); BaseApp baseApp = (BaseApp) name.newInstance(); baseApp.initModuleApp(application); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } } } }
最后看看测试效果,确实达到我们想要的结果:
这里主要还是依赖阿里的ARouter框架来实现,官方的介绍:
ARouter:一个用于帮助 Android App 进行组件化改造的框架 —— 支持模块间的路由、通信、解耦
除了ARouter还有ActivityRouter也可以实现组件的通信,ActivityRouter是个人开源项目,这里以ARouter为准。
Activity跳转
1、添加注解:
// 在支持路由的页面上添加注解(必选)
// 这里的路径需要注意的是至少需要有两级,/xx/xx
@Route(path = "/test/activity")
public class YourActivity extend Activity {
...
}
2、发起跳转
// 1. 应用内简单的跳转(通过URL跳转在'进阶用法'中)
ARouter.getInstance().build("/test/activity").navigation();
// 2. 跳转并携带参数
ARouter.getInstance().build("/test/1")
.withLong("key1", 666L)
.withString("key3", "888")
.withObject("key4", new Test("Jack", "Rose"))
.navigation();
Fragment实例获取
Fragment fragment = (Fragment) ARouter.getInstance().build("/test/fragment").navigation();
访问普通类
比如说我们要在Home组件中的某个页面中获取Me组件中的某个属性值,可以暴露服务的方式,为了Home组件提供内容,同样也是基于ARouter来实现的:
下面获取Me组件中的坚持总会看到不一样
文字为例
1、在Base基础组件中,定义接口继承于IProvider
,其他组件通过该接口来调用需要的函数;
public interface IBaseProvider extends IProvider { } public class BaseProvider implements IBaseProvider{ private String meText; @Override public void init(Context context) { } public void setMeText(String meText) { this.meText = meText; } public String getMeText(){ return meText; } }
2、接着在Me组件中实现该接口,通过声明该类的路由路径。
@Route(path = "/me/provider/text")
public class MeTextProvider extends BaseProvider {
}
3、在Me组件上初始化setMeText
BaseProvider provider = (BaseProvider) ARouter.getInstance().build("/me/provider/text").navigation();
provider.setMeText(mTvIntro.getText().toString());
4、在Home组件通过getMeText
得到Me组件中属性值,由此就完成了两个业务组件间数据访问。
@Override
public void onHiddenChanged(boolean hidden) {
super.onHiddenChanged(hidden);
if (!hidden){
BaseProvider provider = (BaseProvider) ARouter.getInstance().build("/me/provider/text").navigation();
String meText = provider.getMeText();
mTextView.setText(TextUtils.isEmpty(meText)?"请先初始化Me组件":meText);
Log.d("BaseProvider:: ",TextUtils.isEmpty(meText)?"请先初始化Me组件":meText);
}
}
这也是组件间通信方式之一,有时候我们也可以通过事件总线的方式来实现组件通信,具体还是要看你实现的功能了。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。