组件化三问—字节真题

2020-10-29 16:42:46 浏览数 (1)

组件化由于它的解耦,独立,开发效率已经成为了被广泛使用的项目架构了,特别是大项目重构的首选,今天就一起来看看组件化开发。

  • 说说模块化和组件化
  • 说说组件间通信是怎么做的
  • Application生命周期分发是怎么做的

说说模块化和组件化

模块化也就是可以把app中的一些功能分成不同的模块,在Androidstudio里面以不同的module展示,然后模块之间会有相互依赖的关系,但是高耦合度就意味着虽然分成了不同的模块,但是还是一个整体的项目,拆分的意义就不大了。

所以这时候就需要对项目进行组件化,组件化的最大差别就是在于他的解耦,让每个模块可以独立作为app,模块之间没有直接的依赖关系,单独的基础模块可以供每个业务模块使用。这样带来的好处就是:

  • 加快了编译速度,每个业务功能都是单独的工程,可以独立编译
  • 提高协作效率,独立化使得每个组件的开发都相对独立,互不影响
  • 功能重用,组件化之后,以后做新项目就能很快开展起来,一些基础组件都可以直接用起来,比如网络组件等

说说组件间通信是怎么做的

  • 页面跳转的话,比如Activity,Fragment等跳转都是通过ARouter实现,ARouter是一种路由框架,之前的文章也讲过,通过apt生成pathactivity的关系代码,然后进行页面跳转。
  • 组件间通信的话,由于组件之前是没有耦合度的,所以需要单独新建一个组件用于暴露服务接口,然后两个需要通信的模块都依赖这个通信接口组件,一个实现所需要的服务接口,一个 去调用接口,这样就完成了通信。至于接口的实现注入还是有ARouter来完成。这样就在保证了组件之间无关联的前提下进行了通信。
  1. 接口组件module_export
代码语言:javascript复制
public interface INewsService extends IProvider {
    NewsInfo getNews();
}

public class CartServiceUtil {

 public static INewsService getService(){
        return (INewsService) ARouter.getInstance().build("/news/service").navigation();
    }

    public static NewsInfo getNews(){
        return getService().getNews();
    }
}
  1. 通信组件module_news,实现接口
代码语言:javascript复制

    //依赖接口组件
    implementation 'module_export'

@Route(path = "/news/service")
public class NewsServiceImpl implements INewsService {

    @Override
    public NewsInfo getNews() {
        //这里实际项目中 应该是 请求接口 或查询数据库
        NewsInfo newsInfo = new NewsInfo();
        return newsInfo;
    }

    @Override
    public void init(Context context) {
        //初始化工作,服务注入时会调用
    }
}

  1. 通信组件module_home,调用接口
代码语言:javascript复制

    //依赖接口组件
    implementation 'module_export'

    CartServiceUtil.getNews()

Application生命周期分发是怎么做的

这个问题其实是问的,Application的生命周期管理肯定是放在主模块上的,比如onCreate,但是其他的业务模块也有需要在Application的生命周期中需要初始化的内容,而且由于解耦,业务模块和主模块是没有联系的,那么作为业务模块,该怎么获得Application生命周期呢?

第一个方法是通过反射,就是在主 模块中反射获取子模块的初始化对象,然后调用其初始化方法。

代码语言:javascript复制
public static String[] moduleInits = {
            moduleOneInit,
            moduleTwoInit
    };

 public interface BaseAppInit {  
    boolean onInit(Application application);
 }private void initModuleHighPriority(){    
    for (String init: ModuleConfig.moduleInits){       
         try {            
        Class<?> clazz = Class.forName(init);            
        BaseAppInit appInit = (BaseAppInit) clazz.newInstance();            
        appInit.onInitHighPriority(this);        
        } 
        catch (ClassNotFoundException | IllegalAccessException | InstantiationException e)
         {           
         e.printStackTrace();       
         }    
 }}


虽然这样可以实现,但还是一个笨方法,因为还是要去获取业务模块的类名,而且反射毕竟效率很低,影响性能

其实我们可以借鉴Arouter的实现方式,通过apt,也就是注解处理工具,在编译期间去获取所有注解过的类,然后调用他们所实现接口的初始化方法。这里有个库大家可以借鉴下:https://github.com/hufeiyang/Android-AppLifecycleMgr

使用代码贴下:

代码语言:javascript复制

@AppLifecycle
public class CartApplication implements IApplicationLifecycleCallbacks {

    public  Context context;

    /**
      * 用于设置优先级,即多个组件onCreate方法调用的优先顺序
      * @return
     */
    @Override
    public int getPriority() {
        return NORM_PRIORITY;
    }

    @Override
    public void onCreate(Context context) {
        //可在此处做初始化任务,相当于Application的onCreate方法
        this.context = context;

        Log.i("CartApplication", "onCreate");
    }

//...
}


//主工程 MyApplication
public class MyApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        ApplicationLifecycleManager.init();
        ApplicationLifecycleManager.onCreate(this);
    }

}

参考

https://juejin.im/post/6881116198889586701

0 人点赞