Skip to content

bambootang/stitch

Repository files navigation

stitch

目标:降低不同module进行交互时的沟通成本,让开发人员更容易做正确的事情。

Hex.pm


功能支持

  1. 不同module都能接收Application的onCreate等生命周期回调进行本module的初始化
  2. 不同module之间的页面跳转,自动打包传递参数
  3. 不同module之间的数据交互,接口参数对开发友好可见
  4. 页面跳转支持所有Intent可配置的参数
  5. 支持页面跳转拦截
  6. 自动绑定并注入到框架
  7. 支持Multdex
  8. 支持单接口多module多实现方案

基础依赖

在项目根目录的build.gradle文件中添加classpath依赖

buildscript { dependencies {        classpath 'bamboo.components.stitch:stitch-gradle-plugin:1.2' } } 

在需要使用stitch的module的build.gradle文件中加入:

//apply plugin: 'com.android.application' apply plugin: 'com.android.library' //需要放在android的plugin后面,目前只支持与application及library的plugin共同使用 apply plugin: 'stitch.plugin'

组件(module)生命周期

@Component、ComponentLife

ComponentLife类是组件生命周期代理基类,我们通过继承ComponentLife类并使用@Component进行标记,即可将我们的组件注入到stitch中。

每一个Module只允许有1个@Component标注类,如果标注了多个,只会有一个生效。一个显然已经满足需求了,^_^

具体使用方法:

1. 自定义ComponentLife子类

如果Module不需要在Application的onCreate、attachBaseContext等生命周期时进行初始化操作,不需要自定义ComponentLife类。

@Component public class TestComponetLife extends ComponentLife { /*  * 代理Application的OnCreate方法  */    public void onCreate(){        //TODO 进行需要的初始化操作    }    public void attachBaseContext(Context baseContext){ } } //获取TestComponetLife对象 TestComponetLife testComponent = Stitch.searchComponentApplication(TestComponetLife.class); //获取Application对象 Application application = testComponent.getApplication(); //或者 Application application = Stitch.getApplication();

2. 生命周期回调

在Application里面我们需要主动传递Application的生命周期给stitch,stitch提供了两种实现方式:

1. 直接继承StitchApplication

StitchApplication继承自Application,只是添加了stitch的生命周期调用

2. 通过Stitch调用组件的生命周期。

如果不能直接继承StitchApplication,在你自己的Application中主动调用Stitch.onCreate()、Stitch.attachBaseContext()等方法,具体可参考StitchApplication的实现。

页面跳转

@Exported、ActivityPage

@Exported注解用于将Module中的Activity开放给其他Module调用,

ActivityPage 用于与开放的Activity进行关联,同时它实现了Serializable接口,所以也作为Activity的数据传递的封装类使用。

在实际使用之前,我们需要新建1个公用Module作为路由Module,这里我们假设我们所有的Module都依赖于名为Router的Module,而我们开发的Module名为ModuleA,其他Module名为ModuleB

1. 使用

每一个需要共享给其他Module使用的Activity都需要与一个ActivityPage进行关联,其他Module通过ActivityPage即可与Activity进行交互。

//1.在Router中创建TestPage.java public class TestPage extends ActivityPage{ public final String text; public TestPage(Context context,String text) { super(context); this.text = text; } } //2.在ModuleB中启动TestPage,开发ModuleB的人不需要知道TestPage对应到具体哪个页面 Stitch.start(new TestPage(context,"text test")); //或者使用 new TestPage(context,"text test").start(); //3.在ModuleA中创建TestActivity并关联TestPage @Exported(TestPage.class) public class TestActivity extends Activity { protected void onCreate(Bundle savedInstanceState) { ...       //接收页面启动时传递的参数,TestPage的simpleClassName为参数key       TestPage infoPage = (TestPage) getIntent().getSerializableExtra("TestPage"); mTestTextView.setText(infoPage.text); } }

2. Intent Flags等设置

public void onActionTest(View view) {    new ActionTestPage(context) .setTargetIntent(new Intent().setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)) .start();    //如果需要在Activity接收返回值    new ActionTestPage(context) .setTargetIntent(new Intent().setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)) .setRequestCode(100) .startForResult(); }

3.Activity跳转时的参数传递

在页面交互时,有时候我们需要往下一个页面传递参数,stitch默认支持Serializable,同时也支持Parcelable方式

如果你定义的TestPage实现了Parcelable接口,stitch会自动切换为Parcelable方式进行参数传递。

// 默认的Serializable方式 public class TestPage extends ActivityPage { .... // 不想传递的参数用transient描述 public transient final int noParamer = 100; } // Parcelable方式,需要自己写序列化方法 public class TestPage extends ActivityPage implements Parcelable { .... }

@Intercept

@Intercept用来作为@Exported的补充,在某些情况下,Module对外公开的是一个页面入口,但是在不同的条件下可能该入口打开的页面并不是同一个。

public class InterceptTest{ @Intercept public static void receive(TestPage page){ if (AppUtils.isHuaweiChannel()) { Intent intent = Stitch.pack(page);            intent.setClass(page.context, TestActivityA.class); page.context.startActivity(intent);        } else { Intent intent = Stitch.pack(page);            intent.setClass(page.context, TestActivity.class); page.context.startActivity(intent); }    } }

数据交互

@Service

@Service注解用于向stitch中注入Module对外公开的实现接口。

// 1.在 Router 中创建 ITestService.java public interface ITestService { String getTestText(); } // 2. 在 ModuleA 中创建 TestServiceImp.java 并实现 ITestService @Service public class TestServiceImp implements ITestService { public String getTestText() { return "hello world!"; } } // 3. 在 ModuleB 中使用该接口 public class TestServiceTest { public void test() { ITestService testService = Stitch.searchService(ITestService.class); //如果组件没有引用(未打包到apk中)时,testService为null String testText = testService == null ? "" : testService.getTestText(); } }

高级功能

在不同module想要调用其他module对外公开的页面,就需要知道有哪些页面被公开或公开的页面叫什么名称。同样的,想要调用其他module对外公开的接口,也需要知道接口是什么以及在哪个service中。为解决这个问题,stitch提供了整合ActivityPage及Service的功能。

在Router Module中添加依赖

 implementation 'bamboo.components.stitch:stitch-router-anno:1.2' annotationProcessor 'bamboo.components.stitch:stitch-router-compiler:1.2'

打包整合ActivityPage

将所有的ActivityPage统合到ActivityPageManager中,我们只需要通过ActivityPageManager就可以知道有哪些页面是全局可见的。

@Wrapper public class TestPageA extends ActivityPage { @Parameter public Strint text; private String param; public TestPageA(Context context) { super(context); } @Parameter("param") public void setParam(String param){ this.param = param; } } @Wrapper public class TestPageB extends ActivityPage { public TestPageB(Context context,String text) { super(context); this.text = text; } } //使用时通过ActivityPageManager访问 ActivityPageManager.newTestPageA(context).setText("test text").setParam("param test").setRequestCode(1000).startForResult(); ActivityPageManager.newTestPageB(context,"test text").start();

打包整合接口方法

将所有Service实现的接口方法统合ServiceManager中,可跳过Class层直接调用到方法。

@Wrapper public interface ITestService {        String getTestText();    //容易混淆或重名的方法,用@Alias指定别名    @Alias("getTestServiceName")    String getName(); } @Wrapper public interface ITestService2 {    //容易混淆或重名的方法,用@Alias指定别名    @Alias("getTestService2Name")    String getName(); } //调用时通过ServiceManager直接访问方法 String text = ServiceManager.getTestText(); String testName = ServiceManager.getTestServiceName(); String testName2 = ServiceManager.getTestService2Name(); //设定默认值,如果接口没有实现或者实现的module没有被打包到Apk,接口会返回默认值 //原始数据类型默认值是其数据值的最小值,boolean默认值为false,其他引用类型为null,如果要覆盖这个设定可以通过以下方式 String defaultText = "defaultText"; //如果getTestText没有实现,会返回defaultText String text = ServiceManager.getTestText(defaultText);

About

An android components middleware that help app activities and custom services interaction in different modules.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors