使用Navigation时,如何在Fragment之间传递数据?

1,819 阅读2分钟

0.为什么有这个东西

今年年初启动的项目中计划使用JetPackNavigation框架,于是如何在Fragment之间传递数据就成为了一个新的问题。
因为Fragment中并没有像ActivitysetResultonActivityResult这样的API,而且Navigation对此也是毫无支持。
虽然在最新的Fragment-1.3.0-alpha08中有新加入的API,但是你看到alpha几个字符后,还是算了吧。
于是自己琢磨出了一套方法,相比官方推荐的一系列方法中,这套方法拥有以下优势:

  • 使用类型签名的方式进行匹配,不需要传递String类型的Key
  • 直接传递任意类型的对象,不需要实现SerializableParcelable接口
  • 无需声明接口或ViewModel、LiveData等

1.引入方法

1.在你的android工程的根目录下的build.gradle文件中适当的位置添加以下代码:

	allprojects {
		repositories {
			...
			maven { url 'https://jitpack.io' }
		}
	}

2.在你的模块下的build.gradle文件中的适当位置添加以下代码:

	dependencies {
	    implementation 'com.gitee.numeron:mortar:0.1.0'
	}

2.初始化

1.在启用NavigationActivity中的onCreate方法中、setContentView之前,调用以下方法:

mortarEnabled()

3.使用方法

1.在要接收数据的AFragment中使用onResult方法:

onResult<List<User>> { resultCode: Int, list: List<User>? ->
	if(resultCode == RESULT_OK) {
    	if(!list.isNullOrEmpty()) {
        	//TODO()
        }
    } else {
    	//TODO()
    }
}

2.在要传递数据的BFragment中使用setResult方法:

val userList: List<User> = ...
setResult(RESULT_OK, userList)

3.当从BFragment返回到AFragment时,之前通过onResult方法设置的Lambda回调就会运行。

  • 注:onResultsetResult传递的参数的类型必需一致,MutableList和List是不一样的,当其中一个为MutableList时,应该将类型声明为具体的List类型。

4.原理解析

  • Mortar通过在FragmentManager中注册FragmentLifecycleCallbacks的方式来监听所有Fragment的生命周期,并在每个FragmentonViewCreated方法时,查找该Fragment所等待的结果实例并处理回调。
  • 不管是setResult方法传递的类型、还是onResult方法等待的类型,都会抽取出一个String类型的、表示具体类型的参数,这个参数会被封装到TypedValueTypedCallback的实例中,这就是setResultonResult之间进行匹配的关键所在。(这里参考了Gson)

5.结尾

以上两点就是整个Mortar的主要思路,目前已在公司的项目中稳定运行,欢迎start: github.com/xiazunyang/…