一、添加依赖和初始化框架
1、添加依赖
在需要使用ARouter的module中添加如下代码:
1.1、java版本的依赖
android { defaultConfig { ... javaCompileOptions { annotationProcessorOptions { arguments = [moduleName :project.getName() ] } } } } dependencies { api \'com.alibaba:arouter-api:1.5.1\' annotationProcessor \'com.alibaba:arouter-compiler:1.5.1\' }
1.2、kotlin版本的依赖
plugins { ... id \'kotlin-kapt\' } dependencies { ... implementation \'com.alibaba:arouter-api:1.5.1\' kapt \'com.alibaba:arouter-compiler:1.5.1\' }
题外话: implementation 和 api 关键字,在Android studio3.0版本中,曾经的 compile 关键字被弃用,而 api 则是 compile 的替代品, api 与 compile 没有区别。但最新官方推荐使用 implementation 来代替 compile 关键字,据说 implementation 会使Android studio的编译速度更快呦。
而 implementation 和 api 关键字的区别则在于用 implementation 来声明的依赖包只限于当前module内部使用,对于依赖其module的模块是无法使用到该依赖包的。而用 api 来声明依赖包时,依赖于该module的模块可以正常使用其模块内的依赖包。
在这里,由于我是将其放入一个公共的module,来让app module进行依赖,因此使用 api 关键字。若没有对项目进行组件化,则可以使用 implementation 关键字进行依赖。
2、初始化SDK
//初始化ARouter框架 private boolean isDebugARouter = true;//ARouter调试开关 if (isDebugARouter) { //下面两行必须写在init之前,否则这些配置在init中将无效 ARouter.openLog(); //开启调试模式(如果在InstantRun模式下运行,必须开启调试模式! // 线上版本需要关闭,否则有安全风险) ARouter.openDebug(); } //官方推荐放到Application中初始化 ARouter.init((Application) mContext);
二、ARouter的简单使用
1、界面跳转
1.1、Activity界面跳转
目标Activity添加注释(跳转语句,路由路径建议写成常量,创建路由表进行统一管理。)
@Route(path = \"/app/login\") public class LoginActivity extends AppCompatActivity {
发送Activity实现跳转到
ARouter.getInstance().build(\"/app/login\").navigation();
1.2、获取fragment实例
//目标界面 @Route(path = \"/app/fragment\") public class EmptyFragment extends BaseFragment { } //启动界面 Fragment fragment= (Fragment) ARouter.getInstance().build(\"/app/fragment\").navigation(); FragmentManager manager = getSupportFragmentManager(); FragmentTransaction transaction = manager.beginTransaction(); transaction.add(R.id.fl_fragment_content, fragment); transaction.commit();
1.3、注意事项
如果像我一样对项目进行了组件化的同学就会发现,此时跳转并没有成功,而是弹出错误提示。
这是因为组件化后,即时我们使用了 api 作为依赖的关键字,但仍需在使用ARouter的其他module中配置代码。这里一般习惯的做法是把arouter-api的依赖放在基础服务的module里面,因为既然用到了组件化,那么肯定是所有的module都需要依赖arouter-api库的,而arouter-compiler的依赖需要放到每一个module里面。
java
android { defaultConfig { ... javaCompileOptions { annotationProcessorOptions { arguments = [moduleName :project.getName() ] } } } } dependencies { annotationProcessor \'com.alibaba:arouter-compiler:1.5.1\' }
kotlin
plugins { ... id \'kotlin-kapt\' } dependencies { ... kapt \'com.alibaba:arouter-compiler:1.5.1\' }
否则无法匹配路由,并且在使用withObject方法携带对象时也会报错,这个后面再说,再试一次发现界面成功跳转。关于注释 @Route 的 path 参数,也需要注意规范,必须要以“/”开头,并且路径至少为两级,不然会编译不通过或者报错。
意思是路径必须以“/”开头,并且包含的值超过2个“/”。
2、携带基本参数的界面跳转
使用方法如下,传入键值对
Bundle bundle = new Bundle(); bundle.putString(\"bundleStringKey\", \"bundleStringValue\"); ARouter.getInstance().build(\"/app/login\") .withString(\"stringKey\", \"stringValue\") .withInt(\"intKey\", 100) .withBoolean(\"booleanKey\", true) .withBundle(\"bundle\", bundle) .navigation();
目标界面使用 @Autowired 注解进行注入
@Route(path = \"/app/login\") public class LoginActivity extends AppCompatActivity { @Autowired String stringKey; @Autowired int intKey; @Autowired boolean booleanKey; @Autowired Bundle bundle; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_login); //注入ARouter ARouter.getInstance().inject(this); Log.e(TAG, stringKey + \"...\" + intKey + \"...\" + booleanKey); Log.e(TAG, bundle.getString(\"bundleStringKey\")); } }
注意:注入的属性名要和之前携带的key值完全相同,并且要在需要注入的界面通过ARouter.getInstance().inject(this)注入ARouter,否则无法注入成功。建议将ARouter.getInstance().inject(this)操作放在BaseActivity的onCreate方法中进行。既然有注入,就一定有资源的释放,因此释放资源在Application中进行。
@Override public void onTerminate() { super.onTerminate(); ARouter.getInstance().destroy(); }
如果释放资源放在BaseActivity的onDestroy方法中调用了 ARouter.getInstance().destroy( ) ; 在进入目标Activity之后,然后按back键返回原界面的时候,APP会报错崩溃,下面是崩溃日志:
3、携带对象的界面跳转
3.1、携带序列化对象的界面跳转
携带 Serializable 和 Parcelable 序列化的对象
TestSerializableBean serializableBean = new TestSerializableBean(); serializableBean.setName(\"serializable\"); TestParcelableBean parcelableBean = new TestParcelableBean(); parcelableBean.setName(\"parcelable\"); ARouter.getInstance().build(\"/app/login\") .withParcelable(\"parcelableBean\", parcelableBean) .withSerializable(\"serializableBean\", serializableBean) .navigation();
目标界面
@Autowired TestParcelableBean parcelableBean; @Autowired TestSerializableBean serializableBean; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_login); Log.e(TAG, parcelableBean + \"\"); Log.e(TAG, serializableBean + \"\"); }
我们发现Serializable序列化的对象为null,我们查看withSerializable方法发现其被装进了Bundle
public Postcard withSerializable(@Nullable String key, @Nullable Serializable value) { mBundle.putSerializable(key, value); return this; }
因此换一种方法来取值,发现打印成功
TestSerializableBean serializableBean = (TestSerializableBean) getIntent().getExtras().getSerializable(\"serializableBean\"); Log.e(TAG, serializableBean + \"\");
3.2、携带无序列化对象的界面跳转
没有进行过序列化的对象也可以通过withObject对象进行传递,接收方式相同
NormalTest normalTest = new NormalTest(); normalTest.setName(\"normal\"); ARouter.getInstance().build(\"/app/login\") .withObject(\"normalTest\", normalTest) .navigation();
但是我们直接使用该方法运行会报错,分析源码发现该方法中用到了SerializationService
public Postcard withObject(@Nullable String key, @Nullable Object value) { serializationService = ARouter.getInstance().navigation(SerializationService.class); mBundle.putString(key, serializationService.object2Json(value)); return this; }
因此我们需要实现该服务
@Route(path = \"/service/json\") public class JsonServiceImpl implements SerializationService { private Gson gson; @Override public <T> T json2Object(String input, Class<T> clazz) { return gson.fromJson(input, clazz); } @Override public String object2Json(Object instance) { return gson.toJson(instance); } @Override public <T> T parseObject(String input, Type clazz) { return gson.fromJson(input, clazz); } @Override public void init(Context context) { gson = new Gson(); } }
我们可以在里面定义所需的json解析器,再次运行成功打印该对象。那序列化的对象可以使用该方法传递吗?
TestParcelableBean objParcelableBean = new TestParcelableBean(); objParcelableBean.setName(\"objParcelable\"); TestSerializableBean objSerializableBean = new TestSerializableBean(); objSerializableBean.setName(\"objSerializable\"); NormalTest normalTest = new NormalTest(); normalTest.setName(\"normal\"); ARouter.getInstance().build(\"/app/login\") .withObject(\"objParcelableBean\", objParcelableBean) .withObject(\"objSerializableBean\", objSerializableBean) .withObject(\"normalTest\", normalTest) .navigation(); //目标界面 @Autowired(name = \"objParcelableBean\") TestParcelableBean objParcelableBean; @Autowired(name = \"objSerializableBean\") TestSerializableBean objSerializableBean; @Autowired(name = \"normalTest\") NormalTest normalTest; Log.e(TAG, objParcelableBean + \"\"); Log.e(TAG, objSerializableBean + \"\"); Log.e(TAG, normalTest + \"\");
我们发现用 Parcelable 序列化的对象为空,分析build的编译文件
@Override public void inject(Object target) { serializationService = ARouter.getInstance().navigation(SerializationService.class); LoginActivity substitute = (LoginActivity)target; substitute.objParcelableBean = substitute.getIntent().getParcelableExtra(\"objParcelableBean\"); if (null != serializationService) { substitute.objSerializableBean = serializationService.parseObject(substitute.getIntent().getStringExtra(\"objSerializableBean\"), new com.alibaba.android.arouter.facade.model.TypeWrapper<TestSerializableBean>(){}.getType()); } else { Log.e(\"ARouter::\", \"You want automatic inject the field \'objSerializableBean\' in class \'LoginActivity\' , then you should implement \'SerializationService\' to support object auto inject!\"); } if (null != serializationService) { substitute.normalTest = serializationService.parseObject(substitute.getIntent().getStringExtra(\"normalTest\"), new com.alibaba.android.arouter.facade.model.TypeWrapper<NormalTest>(){}.getType()); } else { Log.e(\"ARouter::\", \"You want automatic inject the field \'normalTest\' in class \'LoginActivity\' , then you should implement \'SerializationService\' to support object auto inject!\"); } }
我们可以看到唯独通过 Parcelable 方式序列化的对象没有使用SerializationService进行解析,而是直接从Bundle去取,但我们并不是通过withParcelable方法去设置的值,因此取得的数据为null。
小结:因此,为了方便我们的操作,没有序列化和使用 Serializable 序列化的对象使用 withObject 方法传递,使用 Parcelable 方式序列化的对象则采用 withParcelable 方法进行传递。
3.3、携带集合和数组的界面跳转
集合和数组的界面跳转统一使用 withObject 方法传递,并且能够支持成员的各种序列化方式。
List<NormalTest> listNormal = new ArrayList<>(); listNormal.add(new NormalTest()); listNormal.add(new NormalTest()); List<TestSerializableBean> listSerializable = new ArrayList<>(); listSerializable.add(new TestSerializableBean()); listSerializable.add(new TestSerializableBean()); List<TestParcelableBean> listParcelable = new ArrayList<>(); listParcelable.add(new TestParcelableBean()); listParcelable.add(new TestParcelableBean()); Map<String, NormalTest> map = new HashMap<>(); map.put(\"1\", new NormalTest()); map.put(\"2\", new NormalTest()); ARouter.getInstance().build(\"/app/login\") .withObject(\"listNormal\", listNormal) .withObject(\"listSerializable\",listSerializable) .withObject(\"listParcelable\",listParcelable) .withObject(\"map\", map) .navigation(); //目标界面 @Autowired List<NormalTest> listNormal; @Autowired List<TestSerializableBean> listSerializable; @Autowired List<TestParcelableBean> listParcelable; @Autowired Map<String, NormalTest> map; Log.e(TAG, listNormal + \"\"); Log.e(TAG, listSerializable + \"\"); Log.e(TAG, listParcelable + \"\"); Log.e(TAG, map + \"\");
4、界面跳转回调
//启动界面 ARouter.getInstance().build(\"/app/login\") .navigation(MainActivity.this, REQUEST_CODE); @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_CODE&& resultCode == RESULT_CODE) { LogUtils.e(data.getStringExtra(\"data\")); } } //目标界面 Intent intent = new Intent(); intent.putExtra(\"data\", \"resultData\"); setResult(RESULT_CODE, intent); finish();
5、未用到的知识点
由于项目中没有用到ARouter拦截器、ARouter自定义分组,这两块知识点,所以就没研究。
以上就是Android路由框架ARouter的使用示例的详细内容,更多关于Android路由框架ARouter的使用的资料请关注自学编程网其它相关文章!