ModularizationArchitecture

Introduction: Android 组件化多进程通信
More: Author   ReportBugs   OfficialWebsite   
Tags:

SpinyTech/ModularizationArchitecturefork 的代码

关于架构说明可以参考 Android 架构思考(模块化、多进程)

关于这个 fork 版本增加了一些新的特性,方便使用,文档地址:Android 组件化之通信(多模块,多进程)

此 fork 版本的特性

1 进程间通信数据格式的修改

请求数据RouterResquest 和返回数据MaActionResult分别实现了 Parcelable 接口,并且分别提供了两个可以自定义的成员变量requestObjectresult,用户在建立请求数据RouterResquest 和返回数据MaActionResult可以把自定义的数据传递进去,需要注意的是传递的自定义类型也要实现 Parcelable 接口。

//自定义数据
public class Song implements Parcelable {
    public String name;

    public Song(String name) {
        this.name = name;
    }

    protected Song(Parcel in) {
        name = in.readString();
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(name);
    }

    @Override
    public int describeContents() {
        return 0;
    }

    public static final Creator<Song> CREATOR = new Creator<Song>() {
        @Override
        public Song createFromParcel(Parcel in) {
            return new Song(in);
        }

        @Override
        public Song[] newArray(int size) {
            return new Song[size];
        }
    };
}
//RouterResquest 中设置了自定义类型 Song
RouterRequestUtil.obtain(MainActivity.this)
                                    .domain("com.spinytech.maindemo:music")
                                    .provider("music")
                                    .action("play")
                                    .reqeustObject(new Song("see you"))
                            )
//MaActionResult 中设置自定义类型 Song
MaActionResult result = new MaActionResult.Builder()
                .code(MaActionResult.CODE_SUCCESS)
                .msg("play success")
                .result(new Song("lili"))
                .build();

2 Provider、Action 自动生成

// 注解 Provider,程序运行后将自动注册 MusicProvider 到 com.spinytech.maindemo:music 到 Router
@Provider(processName = "com.spinytech.maindemo:music")
public class MusicProvider extends MaProvider{
    @Override
    protected String getName() {
        return "music";
    }
}
// 注解 Action,程序运行后将自动注册 PlayAction 到 Provider
@Action(processName = "com.spinytech.maindemo:music", providerName = "music")
public class PlayAction implements MaAction<Song>

3 Rxjava 的引入

引入 Rxjava 之后,修改 LocalRoute 的 route 方法,使之返回Observable<MaActionResult>,在调用时可以非常方便地使用 Rxjava 切换线程:

 LocalRouter.getInstance(MaApplication.getMaApplication())
                .rxRoute(MainActivity.this, RouterRequestUtil.obtain(MainActivity.this)
                        .domain("com.spinytech.maindemo:pic")
                        .provider("pic")
                        .action("pic")
                        .data("is_big", "0"))
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.from(ThreadPool.getThreadPoolSingleton()))
                .subscribe(new Consumer<MaActionResult>() {
                    @Override
                    public void accept(MaActionResult maActionResult) throws Exception {
                        Toast.makeText(MainActivity.this, maActionResult.getMsg(), Toast.LENGTH_SHORT).show();
                    }
                }, new Consumer<Throwable>() {
                    @Override
                    public void accept(Throwable throwable) throws Exception {
                        Toast.makeText(MainActivity.this, "error", Toast.LENGTH_SHORT).show();
                    }
                });

使用教程

项目地址:https://github.com/wutongke/ModularizationArchitecture

1 在项目中集成

1.1 在 project 的 build.gradle 中设置 dependencies 块中支持 apt:

classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'

1.2 所有 Module 中配置 apt 插件:

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

dependencies 块中设置:

 apt 'com.github.wutongke.modularization:compile:1.1.1'
 compile 'com.github.wutongke.modularization:macore:1.1.1'

2 创建自定义 Application

2.1 实际 Application 我们知道一个 app 中只有一个 Application,所以在主 Module 中定义 Application,然后在其它模块中根据需要实现逻辑 Application 即可,然后启动时注册逻辑 Application,即可管理其生命周期:

public class MyApplication extends MaApplication {

    //多进程中注册各个进程的 Router,可以参考第 3 小节的原理图
    @Override
    public void initializeAllProcessRouter() {
        WideRouter.registerLocalRouter("com.spinytech.maindemo",MainRouterConnectService.class);
        WideRouter.registerLocalRouter("com.spinytech.maindemo:music",MusicRouterConnectService.class);
        WideRouter.registerLocalRouter("com.spinytech.maindemo:pic",PicRouterConnectService.class);
    }

//注册各个模块中的逻辑 Application,每个模块中可以注册多个逻辑
//Applicatoin,设置优先级,可以调整模块中多个逻辑 Application 的
//调用顺序
    @Override
    protected void initializeLogic() {
        registerApplicationLogic("com.spinytech.maindemo",999, MainApplicationLogic.class);
        registerApplicationLogic("com.spinytech.maindemo",998, WebApplicationLogic.class);
        registerApplicationLogic("com.spinytech.maindemo:music",999, MusicApplicationLogic.class);
        registerApplicationLogic("com.spinytech.maindemo:pic",999, PicApplicationLogic.class);
    }

//设置是否支持多进程
    @Override
    public boolean needMultipleProcess() {
        return true;
    }
}

当然这个自定义的 Application 需要注册到 manifest 文件中。 使用多进程提供服务的模块需要继承LocalRouterConnectService,并且在 manifest 中注册服务:

public class MusicRouterConnectService extends LocalRouterConnectService {
    @Override
    public boolean onUnbind(Intent intent) {
        Log.e("MRCS","onUnbind");
        return super.onUnbind(intent);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.e("MRCS","onDestroy");
    }
}
<service android:name=".MusicRouterConnectService"
            android:process=":music"/>

2.2 逻辑 Application 逻辑 Application 通过继承 BaseApplicationLogic,实现相应的方法即可被回调。

public class BaseApplicationLogic {
    protected MaApplication mApplication;
    public BaseApplicationLogic() {
    }

    public void setApplication(@NonNull MaApplication application) {
        mApplication = application;
    }

    public void onCreate() {
    }

    public void onTerminate() {
    }

    public void onLowMemory() {
    }

    public void onTrimMemory(int level) {
    }

    public void onConfigurationChanged(Configuration newConfig) {
    }
}

//逻辑 Application 只需要继承 BaseApplicationLogic,注册后
//生命周期会被回调
public class MainApplicationLogic extends BaseApplicationLogic {
    @Override
    public void onCreate() {
        super.onCreate();
    }
}

3 自定义 Provider 和 Action

定义 Provider

@Provider(processName = "com.spinytech.maindemo:music")
public class MusicProvider extends MaProvider{
    @Override
    protected String getName() {
        return "music";
    }
}

定义 Action

@Action(processName = "com.spinytech.maindemo:music", providerName = "music")
public class PlayAction implements MaAction<Song> {

    @Override
    public boolean isAsync(Context context, RouterRequest<Song> requestData) {
        return false;
    }

    @Override
    public MaActionResult invoke(final Context context, final RouterRequest<Song> requestData) {
        Intent intent = new Intent(context, MusicService.class);
        intent.putExtra("command", "play");
        context.startService(intent);
        MaActionResult result = new MaActionResult.Builder()
                .code(MaActionResult.CODE_SUCCESS)
                .msg("play success")
                .result(new Song("lili"))
                .build();
        Handler handler = new Handler(context.getMainLooper());
        handler.post(new Runnable() {
            @Override
            public void run() {
                if (requestData != null && requestData.getRequestObject() != null) {
                    Toast.makeText(context, "歌曲名字:" + requestData.getRequestObject().name + "(并不知道)", Toast.LENGTH_SHORT).show();
                }
            }
        });
        Logger.d("com.spinytech", requestData.getRequestObject().name);
        return result;
    }

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

可以看到定义 Provider 和 Action 时分别使用了@Provider@Action 注解,这样可以在程序编译时完成自动的注册,不需要手动注册到 Router 了。

其中 @Provider需要设置进程名字,@Action 需要设置进程名字和注册到的 Provider 名字:

@Provider(processName = "com.spinytech.maindemo:music")
@Action(processName = "com.spinytech.maindemo:music", providerName = "music")

4 调用 Action

4.1 建立 Action 调用 首先需求建立一个请求RouterRequest,说明要请求的内容:

RouterRequestUtil.obtain(MainActivity.this)
                                    .domain("com.spinytech.maindemo:music")
                                    .provider("music")
                                    .action("play")
                                    .reqeustObject(new Song("see you"))

可以通过 RouterRequestUtil 的 obtain 方法快速建立请求,上例中请求的 Action 位于"com.spinytech.maindemo:music"进程,Provider 是"music",Action 是"play",并且传递了相应的参数 new Song("see you")。

然后使用 Rxjava 的方式请求 Action:

LocalRouter.getInstance(MaApplication.getMaApplication())
                            .rxRoute(MainActivity.this, RouterRequestUtil.obtain(MainActivity.this)
                                    .domain("com.spinytech.maindemo:music")
                                    .provider("music")
                                    .action("play")
                                    .reqeustObject(new Song("see you"))
                            )
                            .subscribeOn(Schedulers.from(ThreadPool.getThreadPoolSingleton()))
                            .observeOn(AndroidSchedulers.mainThread())
                            .subscribe(new Consumer<MaActionResult>() {
                                @Override
                                public void accept(MaActionResult maActionResult) throws Exception {
                                    Toast.makeText(MainActivity.this, maActionResult.getMsg(), Toast.LENGTH_SHORT).show();
                                }
                            }, new Consumer<Throwable>() {
                                @Override
                                public void accept(Throwable throwable) throws Exception {
                                    Toast.makeText(MainActivity.this, "error", Toast.LENGTH_SHORT).show();
                                }
                            });

4.2 处理请求 在 music 模块中处理刚刚发出的请求,6.3 中定义的 Provider 和 Action 其实就是处理 6.4.1 中的请求的,并且返回了MaActionResult:

MaActionResult result = new MaActionResult.Builder()
                .code(MaActionResult.CODE_SUCCESS)
                .msg("play success")
                .result(new Song("lili"))
                .build();

其它

注意:在 demo 的 gradle.properties 中可以配置 Local 属性,从而根据需要设置使用本地的 library,还是远端的 library,更改 Local 后注意 sync。

License

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Apps
About Me
GitHub: Trinea
Facebook: Dev Tools