千家信息网

Android路由框架ARouter怎么用

发表于:2024-09-22 作者:千家信息网编辑
千家信息网最后更新 2024年09月22日,今天小编给大家分享一下Android路由框架ARouter怎么用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,
千家信息网最后更新 2024年09月22日Android路由框架ARouter怎么用

今天小编给大家分享一下Android路由框架ARouter怎么用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

一、添加依赖和初始化框架

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();

目标界面

@AutowiredTestParcelableBean parcelableBean;@AutowiredTestSerializableBean serializableBean;@Overrideprotected 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 json2Object(String input, Class clazz) {        return gson.fromJson(input, clazz);    }    @Override    public String object2Json(Object instance) {        return gson.toJson(instance);    }    @Override    public  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(){}.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(){}.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 listNormal = new ArrayList<>(); listNormal.add(new NormalTest()); listNormal.add(new NormalTest()); List listSerializable = new ArrayList<>(); listSerializable.add(new TestSerializableBean()); listSerializable.add(new TestSerializableBean()); List listParcelable = new ArrayList<>(); listParcelable.add(new TestParcelableBean()); listParcelable.add(new TestParcelableBean()); Map 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 listNormal; @Autowired List listSerializable; @Autowired List listParcelable; @Autowired Map 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();

以上就是"Android路由框架ARouter怎么用"这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注行业资讯频道。

0