美文网首页
MultiRouter-多进程组件化路由

MultiRouter-多进程组件化路由

作者: f1abf4d2779c | 来源:发表于2017-08-31 20:53 被阅读179次

APP诞生之初,用的是常见的分层结构设计, 这种架构简单、清晰并一直沿袭至今,随着业务的快速发展,业务模块越来越多,各个模块间相互引用,耦合越来越严重,因此做了第一版架构重构,对各模块进行拆分,多个模块并行开发,为了解决模块间相互依赖,模块间通信采用最简单的单进程路由架构。

单进程路由架构 使用简单,适合小型项目或者初期项目的开发。在持续了一段开发时间后,渐渐的它的单进程模型的弊端也越来越明显,由于代码、内存、apk大小都在增长,对系统资源的占用越来越多,导致进程容易被系统回收或导致内存溢出崩溃,如果不进行内存优化,将很快无法支撑整个业务的发展,此时将整体的应用架构转型为多进程迫在眉睫,独立的通信进程可以保持各个进程模块的稳定性,也可以阻隔一些内存泄露导致的问题。

实现方案

一. 目标&需求

  1. 接口调用简单
  2. 实现apt自动注册Provider、Action
  3. 进程间可以传递复杂数据
  4. 初始化建立进程间通信通道,避免对每次请求结果都要判断是否异步
  5. 添加缓存策略,避免重复请求

二. 技术选型

2.1 如何让接口调用简单?

使用建造者模式构建请求体,链式调用同时避免参数混乱

2.2 如何自定义注解注册来生成Provider,Action注册代码?

注解解析器: 使用官方推荐的AnnotationProcessor
代码自动生成: 使用JavaPoet库或JDK自带的JavaFileObject类

2.3 进程间如何通讯?
  1. 使用AIDL来做进程间的数据交换
  2. Boardcast发布进程间通知
2.5 进程间如何传递复杂数据?

有两种可选方案:

  1. 使用Binder支持的Parceable
  2. 使用Json格式String

使用String来传递数据有两个明显不足:

  1. 使用麻烦,需要在请求和返回时对数据进行解析
  2. 效率不如Parceable

所以选择Binder支持的Parceable来传递数据为最优方案。

三. 最终实现 MultiProcessRouter

Github项目地址:MultiProcessRouter

MultiProcessRouter是一个基于AnnotationProcessor实现的多进程路由框架,它支持注解注册接口、多进程间数据交互,可快速应用于项目多进程模块化。

使用说明

Gradle配置
dependencies {
    classpath 'com.android.tools.build:gradle:2.3.1'
    classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}

allprojects {
    repositories {
        jcenter()
        maven {
            url 'https://dl.bintray.com/shamschu/maven'
        }
    }
}

apply plugin: 'com.neenbedankt.android-apt'

compile 'com.sc.framework:router:1.0.0'
compile 'com.sc.framework:annotation:1.0.0'
apt "com.sc.framework:compiler:1.0.0"
创建每个进程对应的LocalRouterService

LocalRouterService为本地Service(运行在每个单独进程中),用来进行进程间的AIDL通信,一般来说,你只要继承LocalRouterService,并且在你的AndroidMenifest中注册该Service并使用android:process指定它所在的进程名称即可。

public class ProcessService2 extends LocalRouterService {

}

<service
    android:name=".ProcessService2"
    android:process=":second"/>
初始化路由

在应用启动时调用:

Router.register(Context context, IRouterServiceRegister serviceRegister);

并实现IRouterServiceRegister的getServices()方法来返回每个进程对应的LocalRouterService映射列表。
例如您的应用有两个进程,一个主进程,一个名称为second的其他进程,那么调用如下所示:

Router.register(this, new IRouterServiceRegister() {
    @Override
    public Map<String, Class<? extends LocalRouterService>> getServices() {
        Map<String, Class<? extends LocalRouterService>> services = new HashMap<>();
        services.put(ProcessUtils.getMainProcess(TestApplication.this), ProcessService1.class);
        services.put(ProcessUtils.getMainProcess(TestApplication.this) + ProcessUtils.COLON + "second", ProcessService2.class);
        return services;
    }
});
接收路由服务初始化完成广播

Router初始化时,动态注册InitializeCompleteReceiver,并实现onRouterServiceInitCompleted方法,它会在Router服务初始化完成后被触发,你可以在你应用的闪屏页Activity的onCreate中注册,并等待通知,通知成功后再进行app的下一步操作,一旦初始化完成,你可以任意的调用其他进程的接口。

public class SplashActivity extends AppCompatActivity {

    private InitializeCompleteReceiver receiver;
    private boolean mReceiverRegister = false;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_splash);
        // enter main activity if router service has been initialized
        if (Router.checkRouterServiceInitCompleted(this)) {
            startMainActivity();
            return;
        }
        // register InitializeCompleteReceiver to receive router initialized broadcast.
        if (!mReceiverRegister) {
            receiver = new InitializeCompleteReceiver() {
                @Override
                protected void onRouterServiceInitCompleted() {
                    startMainActivity();
                }
            };
            IntentFilter filter = new IntentFilter();
            filter.addAction(InitializeCompleteReceiver.ACTION_ROUTER_SERVICE_COMPLETED);
            registerReceiver(receiver, filter);
            mReceiverRegister = true;
        }
    }

    /**
     * Start your main activity
     */
    private void startMainActivity() {
        Intent intent = new Intent(SplashActivity.this, MainActivity.class);
        startActivity(intent);
        finish();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mReceiverRegister) {
            unregisterReceiver(receiver);
            mReceiverRegister = false;
        }
    }
}
注册Provider
使用注解

@Provider(process = PROCESS_NAME)

PROCESS_NAME为Provider的进程名称。

@Provider(process = "com.shamschu.framework")
public class TestProvider extends RouterProvider {

    @Override
    public String getName() {
        return "TestProvider";
    }
}
注册Action
使用注解

@Action(provider = YOUR_PROVIDER.class)

YOUR_PROVIDER.class为Action所属的Provider的类。

@Action(provider = TestProvider.class)
public class TestAction extends RouterAction<String> {

    @Override
    public RouterResponse<String> invoke(Context context, RouterRequest request) {
        return new RouterResponse.Builder<String>()
            .result("this is a router test!")
            .build();
    }

}
创建请求
RouterRequest request = new RouterRequest.Builder()
        .process("com.shamschu.framework") // 请求进程
        .provider("TestProvider") // 请求进程提供的接口
        .action("TestAction") // 请求接口提供的动作,
        .cacheStrategy(CacheStrategy.FIXED) // 请求缓存策略 NONE: 不缓存,每次都重新获取 FIXED: 一旦请求后则缓存,不在重新发起请求
        .build();
请求并获取结果
RouterResponse<String> response = Router.route(v.getContext(), request);
if (response.isSuccess()) {
    Toast.makeText(SecondActivity.this, response.getResult(), Toast.LENGTH_LONG).show();
} else {
    Toast.makeText(SecondActivity.this, response.getError(), Toast.LENGTH_LONG).show();
}

相关文章

  • MultiRouter-多进程组件化路由

    APP诞生之初,用的是常见的分层结构设计, 这种架构简单、清晰并一直沿袭至今,随着业务的快速发展,业务模块越来越多...

  • 路由组件化

    撸一个简单路由RouteriOS 组件化与路由的本质App 的组件化之路

  • vue项目基建

    路由模块化 , 高频全局组件模块化 权限

  • iOS 组件化2

    组件化2 本文主要讲组件化之间是如何通讯的 组件化通讯方案 1、URL路由 2、target-action 3、p...

  • 路由处理

    基础功能设置 初始化路由页面组件 在views目录中创建路由页面组件,设置方式: 每个页面组件设置独立的目录,内部...

  • 一个Android路由框架的诞生之路

    组件化的一个基础设施:路由!没有它组件化可以说是寸步难行,本篇文章我们就来谈谈一个组件化路由框架诞生过程中的那些思...

  • vue-router 路由

    组件化之后才能路由化 (一定要先安装路由) 单页面路由封装router.js mian.js中引用 App.vue...

  • CTMediator路由swift

    接着上篇组件化的demo,在demo中借助CTMediator实现各个功能块间的调用 路由?组件化? 组件化是将A...

  • OC项目优化之路(四)之Router篇

    最近对路由与组件化产生了兴趣,写了一个DPRouter。路由与组件化是目前大型app都会去做的事情,他有很多的好处...

  • 用50行代码教你写出路由组件

    组件化和路由 路由的实现 客户端的使用 一些小想法 使用组件化是为了解耦处理,多个模块之间通过协议进行交互。而负责...

网友评论

      本文标题:MultiRouter-多进程组件化路由

      本文链接:https://www.haomeiwen.com/subject/yjmwrxtx.html