ARouter学习之一——框架的使用

按照ARouter学习之三——注解解析器(arouter-compiler源码)的结尾,似乎这应该是学习之四,但我选择标题起为之一,虽说是后面才写,但毕竟学习的话都是先学会用,再去弄懂原理。而总结顺序,则是根据好奇心的顺序来整理。

本文的初衷:搞懂在项目中怎样引入ARouter并加以使用


目录

引入ARouter建立依赖

各类简单的跳转

目标界面接收参数

ARouter进阶高级用法

1.通过URL跳转

2.解析高级参数:List、Map、对象

3.处理跳转结果

4.预处理服务

5.详细API说明

小结


引入ARouter建立依赖

该小节的内容均引自github上的文档,若需要请稳步:https://github.com/alibaba/ARouter/blob/master/README_CN.md

build.gradle文件内容如下:

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

dependencies {
    // 替换成最新版本, 需要注意的是api
    // 要与compiler匹配使用,均使用最新版可以保证兼容
    compile 'com.alibaba:arouter-api:x.x.x'
    annotationProcessor 'com.alibaba:arouter-compiler:x.x.x'
    ...
}

最可能早的注册ARouter,在MyApplication中进行初始化

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

至此,完成依赖的建立,接下来就可以正常使用。

各类简单的跳转

通过前两篇的源码阅读RouteType类,我们知道ARouter支持跳转的对象包括:Activity、Fragment、Service,本节来看看如何使用ARouter框架来进行这样的跳转。其步骤可拆分成两步:添加注解和发起路由操作。

添加注解:

// 在支持路由的页面上添加注解(必选)
// 这里的路径需要注意的是至少需要有两级,/xx/xx
@Route(path = "/test/activity")
public class YourActivity extend Activity {
    ...
}

注意path必须不能少于两级,若只是[/xx]的话,则ARouter会抛出数组越界异常,原因是在源码中获取路由“组”指明确指出的。下一篇文章重点分析为什么发起路由操作时就可以进行跳转时,会分析到这块的代码。请稳步我之前的文章(在学习ARouter源码前自己挖的坑)ARouter报错:Failed to extract default group! String index out of range: -2

然后,就可以发起路由操作了。

// 1. 应用内简单的跳转(通过URL跳转在'进阶用法'中)
ARouter.getInstance().build("/test/activity").navigation();

// 2. 跳转并携带参数
ARouter.getInstance().build("/test/1")
            .withLong("key1", 666L)
            .withString("key3", "888")
            .withObject("key4", new Test("Jack", "Rose"))
            .navigation();

简而言之,就是获取ARouter单例后,调用build传入路径,若有参数,则通过withType添加键值对,最后调用naigation()方法即可。

我怎么知道这些的呢?这是我必须告诉读者的,鱼与渔。ARouter的github上的指南以及它的源码。

上面是跳转到Activity,并传递简单的参数,下面列下跳转Fragment和Service的代码,实质实际是完全一样的。

@Route(path = "/test/fragment")
public class BlankFragment extends Fragment {

    @Autowired
    String name;

    ...
}
case R.id.getFragment:
     Fragment fragment = (Fragment) ARouter.getInstance().build("/test/fragment").navigation();
     Toast.makeText(this, "找到Fragment:" + fragment.toString(), Toast.LENGTH_SHORT).show();
     break;
import com.alibaba.android.arouter.facade.template.IProvider;
//需要继承IProvider
public interface HelloService extends IProvider {
    void sayHello(String name);
}

//接口实现类
@Route(path = "/yourservicegroupname/hello")
public class HelloServiceImpl implements HelloService {
    Context mContext;

    @Override
    public void sayHello(String name) {
        Toast.makeText(mContext, "Hello " + name, Toast.LENGTH_SHORT).show();
    }

    /**
     * Do your init work in this method, it well be call when processor has been load.
     *
     * @param context ctx
     */
    @Override
    public void init(Context context) {
        mContext = context;
        Log.e("testService", HelloService.class.getName() + " has init.");
    }
}

发起Service路由,有两种方式,一种通过路由路径,一种通过类

case R.id.navByName:
	((HelloService) ARouter.getInstance().build("/yourservicegroupname/hello").navigation()).sayHello("mike");
	break;
case R.id.navByType:
	ARouter.getInstance().navigation(HelloService.class).sayHello("mike");
	break;

目标界面接收参数

前面通过.withString()等方法传入了对应类似的数据,目标界面需要代码实现这个数据的接收。有两种方式:一通过注解;二通过Intent本身接收。下面摘录ARouter源码中Demo工程的Test1Activity.java来说明这两种方式。

@Route(path = "/test/activity1", name = "测试用 Activity")
public class Test1Activity extends AppCompatActivity {

    @Autowired(desc = "姓名")
    String name = "jack";

    @Autowired
    int age = 10;

    @Autowired
    int height = 175;

    @Autowired(name = "boy", required = true)
    boolean girl;

    @Autowired
    char ch = 'A';

    //方式一,并附默认值
    @Autowired
    float fl = 12.00f;

    @Autowired
    double dou = 12.01d;

    @Autowired
    TestSerializable ser;

    @Autowired
    TestParcelable pac;

    @Autowired
    TestObj obj;

    @Autowired
    List<TestObj> objList;

    @Autowired
    Map<String, List<TestObj>> map;

    private long high;

    @Autowired
    String url;

    @Autowired
    HelloService helloService;

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

        ARouter.getInstance().inject(this);    //方式一:通过注解,必须添加该句

        //方式二:为下方注释掉的代码,它取Intent本身的bundle,其实方式一本质也是
        //只是被注解解释处理了。

        // No more getter ...
        // name = getIntent().getStringExtra("name");
        // age = getIntent().getIntExtra("age", 0);
        // girl = getIntent().getBooleanExtra("girl", false);
        // high = getIntent().getLongExtra("high", 0);
        // url = getIntent().getStringExtra("url");

    }
}

截止目前,我们完成了构建依赖和路由跳转及参数传递。下面看下高级用法。

ARouter进阶高级用法

1.通过URL跳转

// 新建一个Activity用于监听Schame事件,之后直接把url传递给ARouter即可
public class SchameFilterActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    //        直接通过ARouter处理外部Uri
        Uri uri = getIntent().getData();
        ARouter.getInstance().build(uri).navigation(this, new NavCallback() {
            @Override
            public void onArrival(Postcard postcard) {
                finish();
            }
    }
}

//---------AndroidManifest.xml---------//
<activity android:name=".activity.SchameFilterActivity">
    <!-- Schame -->
    <intent-filter>
        <data
        android:host="m.aliyun.com"
        android:scheme="arouter"/>

        <action android:name="android.intent.action.VIEW"/>

        <category android:name="android.intent.category.DEFAULT"/>
        <category android:name="android.intent.category.BROWSABLE"/>
    </intent-filter>
</activity>

2.解析高级参数:List、Map、对象

ARouter对高级对象的参数传递也是支持,实现如下

// 为每一个参数声明一个字段,并使用 @Autowired 标注
// URL中不能传递Parcelable类型数据,通过ARouter api可以传递Parcelable对象
@Route(path = "/test/activity")
public class Test1Activity extends Activity {
    @Autowired
    public String name;
    @Autowired
    int age;
    
    // 通过name来映射URL中的不同参数
    @Autowired(name = "girl") 
    boolean boy;
    
    // 支持解析自定义对象,URL中使用json传递
    @Autowired
    TestObj obj;      
    
    // 使用 withObject 传递 List 和 Map 的实现了
    // Serializable 接口的实现类(ArrayList/HashMap)
    // 的时候,接收该对象的地方不能标注具体的实现类类型
    // 应仅标注为 List 或 Map,否则会影响序列化中类型
    // 的判断, 其他类似情况需要同样处理        
    @Autowired
    List<TestObj> list;
    @Autowired
    Map<String, List<TestObj>> map;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ARouter.getInstance().inject(this);

    // ARouter会自动对字段进行赋值,无需主动获取
    Log.d("param", name + age + boy);
    }
}


// 如果需要传递自定义对象,新建一个类(并非自定义对象类),然后实现 SerializationService,并使用@Route注解标注(方便用户自行选择序列化方式),例如:
@Route(path = "/yourservicegroupname/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);
    }
}

3.处理跳转结果

// 使用两个参数的navigation方法,可以获取单次跳转的结果
ARouter.getInstance().build("/test/1").navigation(this, new NavigationCallback() {
    @Override
    public void onFound(Postcard postcard) {
    ...
    }

    @Override
    public void onLost(Postcard postcard) {
    ...
    }
});

4.预处理服务

// 实现 PretreatmentService 接口,并加上一个Path内容任意的注解即可
@Route(path = "/xxx/xxx")
public class PretreatmentServiceImpl implements PretreatmentService {
    @Override
    public boolean onPretreatment(Context context, Postcard postcard) {
        // 跳转前预处理,如果需要自行处理跳转,该方法返回 false 即可
    }

    @Override
    public void init(Context context) {

    }
}

5.详细API说明

// 构建标准的路由请求
ARouter.getInstance().build("/home/main").navigation();

// 构建标准的路由请求,并指定分组
ARouter.getInstance().build("/home/main", "ap").navigation();

// 构建标准的路由请求,通过Uri直接解析
Uri uri;
ARouter.getInstance().build(uri).navigation();

// 构建标准的路由请求,startActivityForResult
// navigation的第一个参数必须是Activity,第二个参数则是RequestCode
ARouter.getInstance().build("/home/main", "ap").navigation(this, 5);

// 直接传递Bundle
Bundle params = new Bundle();
ARouter.getInstance()
    .build("/home/main")
    .with(params)
    .navigation();

// 指定Flag
ARouter.getInstance()
    .build("/home/main")
    .withFlags();
    .navigation();

// 获取Fragment
Fragment fragment = (Fragment) ARouter.getInstance().build("/test/fragment").navigation();
                    
// 对象传递
ARouter.getInstance()
    .withObject("key", new TestObj("Jack", "Rose"))
    .navigation();

// 觉得接口不够多,可以直接拿出Bundle赋值
ARouter.getInstance()
        .build("/home/main")
        .getExtra();

// 转场动画(常规方式)
ARouter.getInstance()
    .build("/test/activity2")
    .withTransition(R.anim.slide_in_bottom, R.anim.slide_out_bottom)
    .navigation(this);

// 转场动画(API16+)
ActivityOptionsCompat compat = ActivityOptionsCompat.
    makeScaleUpAnimation(v, v.getWidth() / 2, v.getHeight() / 2, 0, 0);

// ps. makeSceneTransitionAnimation 使用共享元素的时候,需要在navigation方法中传入当前Activity

ARouter.getInstance()
    .build("/test/activity2")
    .withOptionsCompat(compat)
    .navigation();
        
// 使用绿色通道(跳过所有的拦截器)
ARouter.getInstance().build("/home/main").greenChannel().navigation();

// 使用自己的日志工具打印日志
ARouter.setLogger();

// 使用自己提供的线程池
ARouter.setExecutor();

小结

使用一个框架来讲,还是相对简单。就像刚开始学习Java一样,人家API就是这么定义,根据你想实现的效果去找到对应的API,然后进行实现即可。

PS:高级进阶用法是不全面的,详细请稳步github上的文档。中文地址:https://github.com/alibaba/ARouter/blob/master/README_CN.md

看完后,来打我吧。哈哈,因为本文除了部分源码外,多数出自github上的文档,但这也是学习一个框架最官方的方法(假设没有前辈整理)。

下一篇是最难的,源码功能分析,解释为什么API就生效,完成了我们想要的路由跳转和参数传递等功能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值