Android模块化中数据传递/路由跳转实现示例

 更新时间:2018年07月07日 09:33:57   作者:左手木亽  
这篇文章主要介绍了Android模块化中数据传递/路由跳转实现示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

虽然说模块通信、路由协议在Android已经不新鲜了,但是如果脱离了那些优秀的开源库我们从零开始自己造一个库,有时候重复造轮子会让自己对所谓"车"的原理懂得更透彻。

直接上造完的轮子地址: https://github.com/Neacy/NeacyComponent

这个轮子有两个大功能分别是模块通信以及路由跳转:

模块通信

首先,统一声明姿势:

public interface IComponent {

  String getName();

  void startComponent(ComponentParam param);
}

也就是说,在各自的维护的模块内若想提供一个类供别的模块调用那么需要实现这个 IComponent 类,这样子可以根据面向对象的优势统一管理,所以我们就有了接下来的这么一个个Component类,比如:

@NeacyComponent("app")
public class AppComponent implements IComponent {

  @Override
  public String getName() {
    return "app";
  }

  @Override
  public void startComponent(ComponentParam param) {
    Log.w("Jayuchou", "==== Start AppComponent ====");
    if (param != null && param.getParam().containsKey("callback")) {
      ICallBack callBack = (ICallBack) param.getParam().get("callback");
      Map<String, Object> results = new HashMap<>();
      results.put("result", "我来自AppComponent");
      ComponentParam cp = new ComponentParam(results);
      callBack.onComponentBack(cp);
    }
  }
}

两个地方比较重要:

  1. NeacyComponent 这个注释,主要是为后面的gradle扫描使用
  2. getName() 这个方法返回每个 IComponent 对应的实例key值,方便在不同的模块我们可以根据这个key值找到对应的 IComponent 对象

其次,如何调用呢?

ComponentController.getComponentByName("app").startComponent(null);

是的,只要根据app这个key值我们就能轻易的找到对应的 IComponent 对象,从而执行 startComponent ,这个方法就是你想要在该模块做的逻辑地方。

看上面我们声明的 AppComponent 类,我们在 startComponent 有判断一下传入的参数是否为空,这里直接放了一个伪 Map 类专门用于存放传递的参数。

如何回调结果以及如何获取别的模块的回调结果?

首先你执行了别的模块的 startComponent 方法,在这个方法中你返回的类肯定只有对应的模块能识别,也就是说你在自己模块获取不到别的模块中的类,所以这里使用 ComponentParam 采用key/value的风格存放参数以及回调返回结果,然后看一下下面的代码就能明白答案了。

// 传递参数给IComponent, 可以通过传递回调函数从而得到回调结果
 Map<String, Object> p = new HashMap<>();
 p.put("callback", new ICallBack() {
   @Override
   public void onComponentBack(ComponentParam result) {
     Log.w("Jayuchou", "==== 运行结果 = " + result.getParam().get("result"));
   }
 });
 ComponentParam cp = new ComponentParam(p);

// 回调结果回去
ICallBack callBack = (ICallBack) param.getParam().get("callback");
Map<String, Object> results = new HashMap<>();
results.put("result", "我来自AppComponent");
ComponentParam cp = new ComponentParam(results);
callBack.onComponentBack(cp);

// 调用的时候传入参数即可
ComponentController.getComponentByName("app").startComponent(cp);

路由跳转

首先,老规矩肯定也是声明一下路由协议(这里只是一个简单的字符串)

@NeacyProtocol("/activity/a")
public class AActivity extends AppCompatActivity

@NeacyProtocol("/activity/b")
public class BActivity extends AppCompatActivity

@NeacyProtocol("/activity/app")
public class MainActivity extends AppCompatActivity

然后调用就是了:

RouterController.startRouter(MainActivity.this, "/activity/a");// 跳转到AActivity

Bundle args = new Bundle(); 
args.putString("key", "AActivity"); 
RouterController.startRouter(AActivity.this, "/activity/b", args);// 跳转到BActivity并携带bundle参数

原理

原理就是通过gradle插件结合ASM扫描注解并在编译的时候注入代码,我们先看下注入成功后的代码结构:

1.模块通信的注入结果

public class ComponentController
{
 static
 {
  registerComponent(new AComponent());
  registerComponent(new BComponent());
  registerComponent(new AppComponent());
 }
 
 private static Map<String, IComponent> components = new HashMap();
 
 static void registerComponent(IComponent component)
 {
  components.put(component.getName(), component);
 }
 . 
 . 
 .
}

2.路由跳转注入结果

public class RouterController
{
 static
 {
  addRouter("/activity/a", "com.neacy.neacy_a.AActivity");
  addRouter("/activity/b", "com.neacy.neacy_b.BActivity");
  addRouter("/activity/app", "com.neacy.component.MainActivity");
 }
 
 private static Map<String, String> routers = new HashMap();
 
 public static void addRouter(String key, String value)
 {
  routers.put(key, value);
 }
}

3.更多gradle插件的代码查阅 https://github.com/Neacy/NeacyComponent

最后

再次感谢灵感: https://github.com/luckybilly/CC

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • Android 系统net和wap接入点的区别

    Android 系统net和wap接入点的区别

    这篇文章主要介绍了Android 系统net和wap接入点的区别的相关资料,需要的朋友可以参考下
    2016-09-09
  • Android序列化接口Parcelable与Serializable接口对比

    Android序列化接口Parcelable与Serializable接口对比

    我们使用 Intent 传递数据的时候,putExtra() 所支持的数据类型事有限的,当需要传递自定义对象的时候就需要序列化。Serializable更简单但是会把整个对象进行序列化因此效率比Parcelable低一些
    2023-02-02
  • Android自定义控件仿QQ抽屉效果

    Android自定义控件仿QQ抽屉效果

    这篇文章主要为大家详细介绍了Android自定义控件仿QQ抽屉效果的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-03-03
  • Android实现记住密码功能

    Android实现记住密码功能

    这篇文章主要为大家详细介绍了Android实现记住密码功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-09-09
  • Flutter获取ListView当前正在显示的Widget信息(应用场景)

    Flutter获取ListView当前正在显示的Widget信息(应用场景)

    ListView是Flutter里最常用的Widget了,当屏幕放不下的时候,它可以自带滚动功能,用法也很简单,本文通过实例代码给大家介绍Flutter获取ListView当前正在显示的Widget信息,感兴趣的朋友一起看看吧
    2022-05-05
  • Android代码检查规则Lint的自定义与应用详解

    Android代码检查规则Lint的自定义与应用详解

    本文主要介绍了Android代码检查规则Lint的自定义与应用详解,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-04-04
  • Android 通过ViewHolder优化适配器的实现方法(必看)

    Android 通过ViewHolder优化适配器的实现方法(必看)

    下面小编就为大家带来一篇Android 通过ViewHolder优化适配器的实现方法(必看)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-04-04
  • Android获取联系人姓名和电话代码

    Android获取联系人姓名和电话代码

    这篇文章主要为大家详细介绍了Android获取联系人姓名和电话代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-02-02
  • Android开发笔记之Intent初级学习教程

    Android开发笔记之Intent初级学习教程

    这篇文章主要介绍了Android开发笔记之Intent初级学习,较为详细的分析了Android Intent项目的建立,功能实现及Intent使用技巧,需要的朋友可以参考下
    2016-02-02
  • Android实现短信验证码输入框

    Android实现短信验证码输入框

    这篇文章主要为大家详细介绍了Android实现短信验证码输入框,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-11-11

最新评论