首页 > 编程知识 正文

android模块化和组件化,android组件间通信

时间:2023-05-05 12:30:29 阅读:270318 作者:3789

Demo地址:https://github.com/751496032/ComponentDemo
本文是续上一篇Android组件化方案实践与思考文章一些思考,主要是针对组件间通信,比如:

每个组件如何初始化各自的数据Activity间如何跳转、Fragment实例获取、访问普通类如何在一个组件中通知另外一个组件数据变化

这些问题是我们在组件化过程中都会遇到问题,在项目中肯定远远还不止这些问题,在这样我遇到的问题记录下来,有不对的地方希望大家多多指点!!

组件数据初始化

常规下我们都会把一些库、第三方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(); } } }}

最后看看测试效果,确实达到我们想要的结果:

Activity如何跳转、Fragment实例获取、如何调用普通类的函数

这里主要还是依赖阿里的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); } }

这也是组件间通信方式之一,有时候我们也可以通过事件总线的方式来实现组件通信,具体还是要看你实现的功能了。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。