我正在使用导航组件,我有片段A和片段B,从片段A我发送一个对象到带有安全参数的片段B,并导航到它。
override fun onSelectableItemClick(position:Int,product:Product) {
val action = StoreFragmentDirections.actionNavigationStoreToOptionsSelectFragment(product,position)
findNavController().navigate(action)
}
现在,在我的片段B中进行了一些逻辑之后,我想再次将这些数据传递给我使用的片段A
btn_add_to_cart.setOnClickListener {button ->
findNavController().previousBackStackEntry?.savedStateHandle?.set("optionList",Pair(result,product_position))
findNavController().popBackStack()
}
然后在片段A中,我用
findNavController().currentBackStackEntry?.savedStateHandle?.getLiveData<Pair<MutableList<ProductOptions>,Int>>("optionList")
?.observe(viewLifecycleOwner, Observer {
storeAdapter.updateProductOptions(it.second,it.first)
})
现在,这很好,但是如果我从片段A转到片段B并按下后退按钮,上面的观察者会再次激发,复制我的当前数据,当我只从片段B按下btn\u add\u to\u cart按钮时,有没有办法只激发这个观察者?
从您的代码中不清楚您的最后一段代码在哪里被调用——您在哪里向LiveData添加了一个观察者。我猜想它在onResume()或onViewStateRestored()方法之一或任何其他生命周期回调中,每当您从片段B返回片段A时,都会再次调用该回调。如果是这样,那么您将向LiveData添加一个新的观察者,并且LiveData的任何观察者都会收到当前值的即时更新。
将这段代码移动到回调方法之一,该方法在片段的生命周期中只调用一次。
面临同样的问题
通过从savedStateHandle
实时数据中删除旧数据来解决此问题
内部碎片B:
button?.setOnClickListener {
findNavController().previousBackStackEntry?.savedStateHandle?.set(key, data)
findNavController().popBackStack()
}
片段A内部:
这是使用实时数据删除方法删除旧数据的关键,它应该在视图创建后,就像在片段的onViewCreated方法中一样
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
findNavController().currentBackStackEntry?.savedStateHandle?.getLiveData<String>(key)?.observe(viewLifecycleOwner) {
result(it)
findNavController().currentBackStackEntry?.savedStateHandle?.remove<String>(key)
}
}
更新:
我为此创建了扩展以更好地使用
fun <T> Fragment.setBackStackData(key: String, data: T, doBack: Boolean = false) {
findNavController().previousBackStackEntry?.savedStateHandle?.set(key, data)
if (doBack)
findNavController().popBackStack()
}
fun <T> Fragment.getBackStackData(key: String, singleCall : Boolean= true , result: (T) -> (Unit)) {
findNavController().currentBackStackEntry?.savedStateHandle?.getLiveData<T>(key)
?.observe(viewLifecycleOwner) {
result(it)
//if not removed then when click back without set data it will return previous data
if(singleCall) findNavController().currentBackStackEntry?.savedStateHandle?.remove<T>(key)
}
}
在碎片中呼唤就像
在片段B中设置数据时
var user : User = User(data) // Make sure this is parcelable or serializable
setBackStackData("key",user,true)
在片段A中获取数据时
getBackStackData<User>("key",true) { it ->
}
多亏了这个家伙
您使用此扩展:
fun <T> Fragment.getResult(key: String = "key") =
findNavController().currentBackStackEntry?.savedStateHandle?.get<T>(key)
fun <T> Fragment.getResultLiveData(key: String = "key"): MutableLiveData<T>? {
viewLifecycleOwner.lifecycle.addObserver(LifecycleEventObserver { _, event ->
if (event == Lifecycle.Event.ON_DESTROY) {
findNavController().previousBackStackEntry?.savedStateHandle?.remove<T>(key)
}
})
return findNavController().currentBackStackEntry?.savedStateHandle?.getLiveData<T>(key)
}
fun <T> Fragment.setResult(key: String = "key", result: T) {
findNavController().previousBackStackEntry?.savedStateHandle?.set(key, result)
}
例子:
碎片a-
片段B需要设置TestModel的结果。班
结果模型。班
data class ResultTestModel(val id:String?, val name:String?)
片段A:
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// ...
getNavigationResultLiveData<PassengerFragmentResultNavigationModel>(
"UNIQUE_KEY")?.observe(viewLifecycleOwner) { result ->
Log.i("-->","${result.id} and ${result.name}")
}
//...
}
片段B:设置数据并调用popBackStack。
ResultTestModel(id = "xyz", name = "Rasoul")
setNavigationResult(key = "UNIQUE_KEY", result = resultNavigation)
findNavController().popBackStack()
当我将一个片段(它是带有背景的全屏)显示在另一个片段(我们称之为main)上时,我的main片段仍然会对单击做出反应(即使我们没有看到按钮,我们也可以单击它)。 问题:如何防止点击第一(主)片段?
我读过很多关于这方面的文章,但也有2012年或更早的文章。 (我只是打算从数据库中读取和插入一些数据。)
我想创建一个类,它的功能只是做一个碎片事务,但我有一个错误。我的课是下一个: 进程:net.elinformaticoenganchado.sergio.crossfights,PID:5116 java.lang.runtimeException:无法启动活动ComponentInfo{net.elinformaticoenganchado.sergio.crossfights/net.elin
先生/女士,我想使用android JAVA将一个片段回调到另一个片段。我试图找到问题,但没有找到解决方案。若我使用接口,它会向活动发送回调响应,这是我不想要的。非常感谢。
每当一个片段显示给用户时,我需要执行一些代码。 通过查看API,我能看到的最接近的钩子方法是onResume。但是,从我的代码调试来看,当用户选择back-button返回到先前显示的片段时,似乎没有调用onResume。 为了澄清我看到的行为: 我有一个“parent”活动,它在ActionBar中配置选项卡...和2个片段F1和F2。 用户选择一个选项卡,F1被加载到活动中。按下按钮,用户就可