设为首页 加入收藏

TOP

Android组件化探索与实践(一)
2019-09-01 23:13:17 】 浏览:63
Tags:Android 组件 探索 实践

什么是组件化

不用去纠结组件和模块语义上的区别,如果模块间不存在强依赖且模块间可以任意组合,我们就说这些模块是组件化的。

组件化的好处

  1. 实现组件化本身就是一个解耦的过程,同时也在不断对你的项目代码进行提炼。对于已有的老项目,实现组件化刚开始是很难受的,但是一旦组件的框架初步完成,对于后期开发效率是会有很大提升的。

  2. 组件间间相互独立,可以减少团队间的沟通成本。

  3. 每一个组件的代码量不会特别巨大,团队的新人也能快速接手项目。

如何实现组件化

这是本文所主要讲述的内容,本篇文章同时适用于新老项目,文中会逐渐带领大家实现如下目标:

  • 各个组件不存在强依赖
  • 组件间支持通信
  • 缺少某些组件不能对项目主体产生破坏性影响

组件化-理论篇

理论篇不会讲述实际项目,先从技术上实现上面的三个目标。

组件间不存在强依赖

组件间不存在强依赖从理论上来说其实很简单,我不引用你任何东西,你也不要引用我任何东西就行了。但在实际项目中,需要清楚明白那些业务模块应该定义为组件,另外在已有项目中,拆分代码也需要大量的工作。

组件间如何通信

组件间通过接口通信。为每一个组件定义一个或者多个接口,简单起见,我们假定只为每一个组件定义接口(多个接口是类似的)。

便于理解,还是要举实例。假设当前存在两个组件UserManagement(用户管理)和OrderCenter(订单中心),我们为组件接口定义的模块的名为ComponentInterface。UserManagement和OrderCenter都依赖于ComponentInterface。为了有个直观的感受,还是放张图:

工程目录1

在ComponentInterface模块中新建为组件UserManagement的定义接口:

public interface UserManagementInterface
{
    //获取用户ID
    String getUserId();
}

UserManagement实现ComponentBInterface:

public class UserManagementInterfaceImpl implements UserManagementInterface
{
    @Override
    public String getUserId()
    {
        return "UID_XXX";
    }
}

现在假定OrderCenter组件需要从UserManagement获取用户ID以便加载该用户的订单列表。那么问题来了,OrderCenter怎么才能调用到UserManagement的组件实现呢?这个问题可以通过反射来解决,只是需要满足组件的接口和组件接口的实现的路径和名称满足一定的约束条件。

我们定义组件接口和其实现的路径和名称的约束条件如下:

  1. 组件的接口和组件接口的实现必须定义在同一个包名下。

  2. 组件接口的实现的类名可以通过组件的接口的类名推导出来。比如每一个接口的实现的类名都是在该接口的名称后面接上“Impl”。

那么现在,我们的工程目录大概就像这个样子:

工程目录2

接下来,在OrderCenter组件中就可以通过反射获取到UserManagement组件接口的实现了,我们定义一个ComponentManager类:

public class ComponentManager
{
    public static <T> T of(Class<T> tInterface)
    {
        String interfaceName = tInterface.getCanonicalName();
        String implName = interfaceName + "Impl";
        try
        {
            T impl = (T) Class.forName(implName).newInstance();
            return impl;
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
            return null;
        }
    }
}

然后在OrderCenter就可以通过ComponentManager来获取UserManagement的组件接口实现了:

String userId = ComponentManager.of(UserManagementInterface.class).getUserId();

至此,组件间通信的问题就算解决了,而且组件之间还是不存在强依赖。

缺少某些组件不能对项目主体产生破坏性影响

假设打包后的项目不存在UserManagement组件,上面获取userId的代码会有什么问题?ComponentManager.of(UserManagementInterface.class)这里的返回必然为null,我们的代码就会产生空指针异常。

那么如何解决这个问题呢?像下面这样吗:

UserManagementInterface userManagementInterface = ComponentManager.of(UserManagementInterface.class);
if (userManagementInterface != null) 
{
    userId = userManagementInterface.getUserId();
}

从程序运行的角度来看,上面的代码没有什么问题。但从码农的角度来看,上面代码写起来必然不是很舒爽,整个项目中会充斥着这样的非空判断。

我们期望,在某个组件不存在时,通过ComponentManager.of获取的组件接口实现可以具备一个默认值。在Java中,我们可以通过动态代理在运行时动态生成一个接口的实现。
我们修改ComponentManager的代码:

public class ComponentManager
{
    public synchronized static <T> T of(Class<T> tInterface)
    {
        String interfaceName = tInterface.getCanonicalName();
        String implName = interfaceName + "Impl";
        try
        {
            T impl = (T) Class.forName(implName).newInstance();
            return impl;
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
            ClassLoader classLoader = ComponentManager2.class.getClassLoader();
            T fakeImpl = (T) Proxy.newProxyInstance(classLoader, new Class[]{tInterface}, new DefaultInvocationHandler());
            return fakeImpl;
        }
    }

    private static class DefaultInvocationHandler implements InvocationHandler
    {
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Android使用google breakpad捕获.. 下一篇安卓开发笔记(十七):帧动画制..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目