有没有一种方法可以在Kotlin和Android中绑定函数引用,以便可以从其他片段调用这些函数?例如,我的fragment factory方法看起来像这样:
fun newInstance(tryAgainFunction: () -> Unit): TimeOutHandlerFragment {
val fragment = TimeOutHandlerFragment()
val bundle = Bundle()
return fragment
}
字符串
我希望能够将我的tryAgainFunction保存在bundle中以供进一步检索。
多谢了!
编辑
最后,最合适的解决方案是使用热键的答案,然后在onViewCreated中使用传递的函数初始化一个侦听器。代码如下:
companion object {
val CALLBACK_FUNCTION: String = "CALLBACK_FUNCTION"
fun newInstance(tryAgainFunction: () -> Unit): TimeOutHandlerFragment {
val fragment = TimeOutHandlerFragment()
val bundle = Bundle()
bundle.putSerializable(CALLBACK_FUNCTION, tryAgainFunction as Serializable)
fragment.arguments = bundle
return fragment
}
}
override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
try {
val callback: () -> Unit = arguments.getSerializable(CALLBACK_FUNCTION) as () -> Unit
btnTryAgain.setOnClickListener { callback.invoke() }
} catch (ex: Exception) {
// callback has a wrong format
ex.printStackTrace()
}
}
型
感谢大家的帮助!
7条答案
按热度按时间7rfyedvj1#
如果
tryAgainFunction
是Serializable
,则you can put it into thebundle
使用bundle.putSerializable("try_again_function", tryAgainFunction);
。如果它是一个函数引用(
SomeClass::someFunction
)或lambda,则它实际上是Serializable
。但如果它是函数接口() -> Unit
的一些自定义实现,则可能不是,因此您应该检查它并处理它不是的情况。pdsfdshx2#
2022年更新:
1.我原来的方法有一个缺点,在我的演示中,如果我按下home键将应用程序置于后台,它将崩溃
NotSerializableException
。1.实际上还有另一个API只是为了监听另一个
Fragment
的变化,那就是FragmentResultListener
,官方教程在这里:https://youtu.be/oP-zXjkT0C0?t=468的数据。1.如果
FragmentResultListener
不能满足您的需求,Shared ViewModel
是最终的解决方案:https://youtu.be/THt9QISnIMQ。1.您需要将
id 'kotlin-parcelize'
添加到您的build.gradle(app)中,如下所示:字符串
2.创建一个Class来封装Lambda函数:
型
3.传递Lambda:
型
4.取回:
型
Demo(所有
Fragment
):https://youtu.be/0OnaW4ZCnbk的6ss1mwsb3#
也许太晚了,但:
你有没有试过把
val callback
放到伴随对象里面?解决方案可能类似于:字符串
eyh26e7m4#
不,正如其他人所说,没有办法将函数字面量传递给
Bundle
。但是由于
enum
实现了Serializable
,因此可以传递可以保存一些方法的枚举变量。尝试以下代码;字符串
在你的from-activity(或片段)中;
型
在你的to-activity(或片段)中;
型
oyxsuwqo5#
是的,有一个简单的解决方案,我一直在我的项目中使用。这个想法是将任何引用类型/对象 Package 在一个warper类中,该类是
Parcalabe
和Serializable
,而不实际实现底层引用类型的封送。下面是 Package 器类以及如何使用它而不会导致任何潜在的内存泄漏:字符串
任何对象都可以 Package 在
TrackedReference
对象中,并作为可序列化或可打包的对象传递:型
您还可以根据用例传递
weak
或soft
引用。用例一:
对象(在本例中为
objectA
)不能保证在接收器活动需要使用它的时候(例如:可能是垃圾收集)。在这种情况下,对象将保留在内存中,直到显式移除强引用。在这个 Package 器中传入一个
Intent
或Bundle
,并以一种简单的方式进行访问,例如(伪码)型
用例二:
对象保证在需要时在内存中,例如保证容纳片段的活动在片段的生命周期内保持在存储器中。
或者,我们不关心对象是否被垃圾回收,我们不想成为它存在的原因。在这种情况下,在初始化
TrackedReference
示例时传递weak
或soft
引用:型
最好理解为什么
Intent
需要Parcelable
或Serializable
,以及在给定场景中使用此解决方案的最佳方法是什么。序列化对象以允许活动之间的 * 委托 * 或 * 回调 * 通信当然不是理想的。
这里是
Intent
上的 * 文档 *,但简单地说,Intent
被传递到 *Android系统 *,然后查找如何处理它,并在这种情况下启动下一个Activity(就接收Intent的 *Android系统 * 而言,它可以是另一个应用程序)。因此,系统需要确保Intent中的所有内容都可以从地块中重建。咆哮:
IMO,
Intent
作为IPC(进程间通信)的更高级别抽象可能在内部方便和高效,但以这些限制为代价。这可能是比较苹果和橘子,但在iOS中,ViewControllers(类似于 Activities)就像任何类一样,可以传递任何Type
(值或引用)作为参数。然后,开发人员负责避免可能阻止ARC(内存管理)释放未使用的引用的潜在引用周期。w7t8yxp56#
1 -创建接口并扩展serializable
字符串
2 -传递到片段、dialogFragment或BottomSheetDialogFragment的示例
型
3 - in fragment,dialogFragment或BottomSheetDialogFragment,
onCreate
型
通过这样做,如果设备更改
dark mode or light mode
,configuration change
,screen rotation
,您将是安全的。70gysomp7#
但是,如果无法将函数文字放入
Bundle
中,则可以通过Fragment
中类似setter的函数将函数传递给Fragment
。字符串