从零开始的ARouter新手篇

1、ARouter是什么?

ARouter是阿里开源的一款android路由框架。按照git上的原说法:他是一个用于帮助 Android App 进行组件化改造的框架 —— 支持模块间的路由、通信、解耦。

2、ARouter有什么作用?

解耦、方便管理多页面的动态跳转,提供组件化解耦的一种方案,同一Native与H5的跳转方法。

3、为什么要用ARouter?

动态跳转:针对复杂逻辑下,多个页面进行跳转。

组件化:针对组件化,随着业务量的不断增长,app也会不断的膨胀,app一般都会走向组件化。组件化就是将APP按照一定的功能和业务拆分成多个组件module,不同的组件独立开发,组件化不仅能够提供团队的工作效率,还能够提高应用性能。而组件化的前提就是解耦,那么我们首先要做的就是解耦页面之间的依赖关系。

Native与H5:因为在H5中是无法使用StartActivity()跳转到Native页面的,而从Native跳转到H5页面也只能通过配置浏览器的方式实现。

4、与常规页面跳转的比较

显式跳转:

Intent intent = new Intent(activity, XXActivity.class);


由于需要直接持有对应class,从而导致了强依赖关系,提高了耦合度


隐式跳转:

Intent intent = new Intent(); 
intent.setAction(“com.android.activity.MY_ACTION”);


其中action等属性的定义在Manifest,导致了扩展性较差,规则集中式管理,导致协作变得非常困难。

5、ARouter的基础使用 

  A、添加依赖和配置

android {
    defaultConfig {
        ...
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = [ moduleName : project.getName() ]
            }
        }
    }
}

dependencies {
    // 替换成最新版本, 需要注意的是api
    // 要与compiler匹配使用,均使用最新版可以保证兼容
    implementation 'com.alibaba:arouter-api:1.3.1'
    annotationProcessor 'com.alibaba:arouter-compiler:1.1.4'
}
// 旧版本gradle插件(< 2.2),可以使用apt插件,配置方法见文末'其他#4'
// Kotlin配置参考文末'其他#5'

注意:这里有个坑

git官方用的是下面的,然后当你运行的时候,会抛出ARouter::Compiler >>> No module name, for more information, look at gradle log. 的错误,我对官网留下的坑和其他哥们儿不负责的转载表示绝望……至少我这里是抛出这个错的。所以在按照官方配置时遇到这个报错时,将arguments的参数改成上面的代码arguments = [ moduleName : project.getName() ] 应该就能解决,其次如果使多model时,请在每个module里面的build.gradle中进行配置。

android {
    defaultConfig {
        ...
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = [AROUTER_MODULE_NAME: project.getName()]
            }
        }
    }
}

 

  B、添加注解

@Route(path = "/aroute/SecondActivity")
public class SecondActivity extends AppCompatActivity {

}

在支持路由的页面上添加注解, 这里的路径需要注意的是至少需要有两级,/xx/xx

注:在 path 这个字符串里面,”aroute” 就代表组的标识;“SecondActivity” 代表是 SecondActivity类的具体表示。组的标识和类的标识都可以自己定义的,即我把它写成@Route(path = "/aaa/SecondActivity11") 也是可以的。

需要记住的是组标识和类标识之间用斜杠来区分 ”\” 。

  C、初始化SDK

public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        if (isDebug()) {           // 这两行必须写在init之前,否则这些配置在init过程中将无效
            ARouter.openLog();     // 打印日志
            ARouter.openDebug();   // 开启调试模式(如果在InstantRun模式下运行,必须开启调试模式!线上版本需要关闭,否则有安全风险)
        }
        ARouter.init(this); // 尽可能早,推荐在Application中初始化
    }


    /**仅作参考用,免得有小伙伴说找不到方法
     */
    public boolean isDebug() {
        return true;
    }
}

  D、发起路由操作

    a、应用内简单的跳转(通过URL跳转在'进阶用法'中)

ARouter.getInstance().build("/aroute/SecondActivity").navigation();

如我从MainActivity跳转到SecondActivity,我可以这样去写点击MainActivity的button触发to2()

@Route(path = "/aroute/MainActivity")
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void to2(View view) {
        ARouter.getInstance().build("/aroute/SecondActivity").navigation();
    }
}

好了,跳转完成,很简单的写法,大家都去试一下吧。

   b、跳转并携带参数

    public void to2(View view) {
//        ARouter.getInstance().build("/aroute/SecondActivity").navigation();
        ARouter.getInstance().build("/aroute/SecondActivity")
                .withString("key1", "xiaoming")
                .withInt("key2",18)
                .withBoolean("key3",true )
                .navigation();
    }

参数的接收,给要注入的对应变量写上注解@Autowired,并赋予对应的跳转key,并执行ARouter.getInstance().inject(this);完成参数注入

@Route(path = "/aroute/SecondActivity")
public class SecondActivity extends AppCompatActivity {

    @Autowired
    public String key1;//第一种参数写法,直接写传入过来的key

    @Autowired(name = "key2")//第二种参数写法,在注解的name里传入过来的key
    public int age;//并对该值进行重命名

    @Autowired(name = "key3")
    public boolean isMan;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        ARouter.getInstance().inject(this);
        Log.i("Tomes","key1="+key1);
        Log.i("Tomes","key2="+age);
        Log.i("Tomes","key3="+isMan);
    }
}

这里打出来的日志为:

注意:前方高能,非战斗人员退避

巨坑,照着官方文档的写的我,一度让我怀疑人生

    public void to2(View view) {
        Student student=new Student("Tomes",18);
        ARouter.getInstance().build("/aroute/SecondActivity")
                .withString("key1", "xiaoming")
                .withInt("key2",18)
                .withBoolean("key3",true )
                .withObject("key4",student)
                .navigation();
    }

官网说可以用withObject()传递参数,如果有小伙伴敢这样写……

public class Student{

    private String name;
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;

    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

很好……

Caused by: java.lang.NullPointerException: Attempt to invoke interface method 'java.lang.String com.alibaba.android.arouter.facade.service.SerializationService.object2Json(java.lang.Object)' on a null object reference

惊不惊喜,意不意外!!!

很好,看来你看到大坑了。

这里你需要加上一个类。不懂没关系,先照着抄下来吧。使用fastjson的小伙伴使用下面的类

@Route(path = "/service/json")
public class JsonServiceImpl implements SerializationService {
    @Override
    public void init(Context context) {

    }

    @Override
    public <T> T json2Object(String text, Class<T> clazz) {
        return JSON.parseObject(text, clazz);
    }

    @Override
    public String object2Json(Object instance) {
        return JSON.toJSONString(instance);
    }

    @Override
    public <T> T parseObject(String input, Type clazz) {
        return JSON.parseObject(input, clazz);
    }
}

使用GSON的小伙伴用下面的类

@Route(path = "/service/json")
public class JsonServiceImpl implements SerializationService {

    private Gson mGson;

    @Override
    public void init(Context context) {
        mGson = new Gson();

    }

    @Override
    public <T> T json2Object(String text, Class<T> clazz) {
        checkJson();
        return mGson.fromJson(text, clazz);
    }

    @Override
    public String object2Json(Object instance) {
        checkJson();
        return mGson.toJson(instance);
    }

    @Override
    public <T> T parseObject(String input, Type clazz) {
        checkJson();
        return mGson.fromJson(input, clazz);
    }

    public void checkJson() {
        if (mGson == null) {
            mGson = new Gson();
        }
    }
}

ok,终于不报错了,血泪的教训啊。

好了接受数据吧。

@Route(path = "/aroute/SecondActivity")
public class SecondActivity extends AppCompatActivity {

    @Autowired
    public String key1;//第一种参数写法,直接写传入过来的key

    @Autowired(name = "key2")//第二种参数写法,在注解的name里传入过来的key
    public int age;//并对该值进行重命名

    @Autowired(name = "key3")
    public boolean isMan;

    @Autowired(name = "key4")
    public Student student;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        ARouter.getInstance().inject(this);
        Log.i("Tomes","SecondActivity-->onCreate");
        Log.i("Tomes","key1="+key1);
        Log.i("Tomes","key2="+age);
        Log.i("Tomes","key3="+isMan);
        Log.i("Tomes","key4 name="+student.getName()+"<>age="+student.getAge());

    }
}

Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.example.admin.aroute.Student.getName()' on a null object reference

第二次冲击来袭……

这一刻我回想起被ARouter支配的恐惧……

这坑有完没完?

告诉你,没完……

教练我想放弃……

来回到Student类

public class Student{

    public String name;
    public int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;

    }

    public Student(){}
}

这里阵亡次数太多,我就不一一复述了,总结如下:

注意修改点:

1、将用到的属性都从private改成public;

2、没有默认构造的都加上默认构造;

3、如果Student类里面还包含了其他对象,其他对象也按照Student类的标准;

一二三四,再试一次。bug解除,bug解除,bug解除。

参数终于传递过来了,真不容易啊。


  c、路由过程监听

在路由跳转的过程中,我们可以监听路由的过程。有需要的同学可以根据需求加上。

public Object navigation(Context context, NavigationCallback callback) 
    public void to2(View view) {
        ARouter.getInstance().build("/aroute/SecondActivity")
                .withString("key1", "xiaoming")
                .withInt("key2",18)
                .withBoolean("key3",true )
                .navigation(this, new NavigationCallback() {
                    @Override
                    public void onFound(Postcard postcard) {
                        Log.i("Tomes","onFound");
                    }

                    @Override
                    public void onLost(Postcard postcard) {
                        Log.i("Tomes","onLost");
                    }

                    @Override
                    public void onArrival(Postcard postcard) {
                        Log.i("Tomes","onArrival");
                    }

                    @Override
                    public void onInterrupt(Postcard postcard) {
                        Log.i("Tomes","onInterrupt");
                    }
                });
    }

如果不需要这么多回调实现,可以NavCallback替代NavigationCallback则

    public void to2(View view) {
        ARouter.getInstance().build("/aroute/SecondActivity")
                .withString("key1", "xiaoming")
                .withInt("key2",18)
                .withBoolean("key3",true )
                .navigation(this, new NavCallback() {
                    @Override
                    public void onArrival(Postcard postcard) {
                        Log.i("Tomes","onArrival");
                    }
                });
    }

E、添加混淆规则

这里以基础混淆proguard-rules.pro文件为例,混淆配置文件里加入

-keep public class com.alibaba.android.arouter.routes.**{*;}
-keep public class com.alibaba.android.arouter.facade.**{*;}
-keep class * implements com.alibaba.android.arouter.facade.template.ISyringe{*;}

# 如果使用了 byType 的方式获取 Service,需添加下面规则,保护接口
-keep interface * implements com.alibaba.android.arouter.facade.template.IProvider

# 如果使用了 单类注入,即不定义接口实现 IProvider,需添加下面规则,保护实现
# -keep class * implements com.alibaba.android.arouter.facade.template.IProvider

基础运行demo避免踩坑

ARouter git地址:https://github.com/alibaba/ARouter

猜你喜欢

转载自blog.csdn.net/qq_35559358/article/details/84300708