按下按钮打开一个单独的输入窗口时,将显示结果吐司。
class MainActivity : AppCompatActivity() {
val disposable = CompositeDisposable()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
button.setOnClickListener {
val f = TestPopup()
usingRxJava(f)
//usingLiveData(f)
}
}
private fun usingRxJava(f: TestPopup) {
val subject = SingleSubject.create<String>()
f.show(supportFragmentManager, "TAG")
button.post {
f.dialog.setOnDismissListener {
val str = f.arguments?.getString(TestPopup.TEST_KEY) ?: ""
subject.onSuccess(str)
}
}
subject.subscribe({
Toast.makeText(this, "Accept : $it", Toast.LENGTH_SHORT).show()
}, {
}).addTo(disposable)
}
private fun usingLiveData(f: TestPopup) {
val liveData = MutableLiveData<String>()
f.show(supportFragmentManager, "TAG")
button.post {
f.dialog.setOnDismissListener {
val str = f.arguments?.getString(TestPopup.TEST_KEY) ?: ""
liveData.postValue(str)
}
}
liveData.observe(this, Observer {
Toast.makeText(this, "Accept : $it", Toast.LENGTH_SHORT).show()
})
}
override fun onDestroy() {
disposable.dispose()
super.onDestroy()
}
}
DialogFragment
class TestPopup : DialogFragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.dialog_test, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
button_test.setOnClickListener {
val arg = Bundle()
arg.putString(TEST_KEY, edit_test.text.toString())
arguments = arg
dismiss()
}
}
companion object {
const val TEST_KEY = "KEY"
}
}
(示例项目网址:https://github.com/heukhyeon/DialogObserverPattern)
此示例代码在正常情况下有效。但是,按照以下步骤操作,烤面包不会漂浮。
在这种情况下,我输入的文本仍保留在屏幕上,但是当我按“确定”按钮时什么也没有发生。
我当然知道发生这种情况是因为在活动结束时,活动与对话框之间的观察关系已经结束。
大多数代码使用Activity中该对话框的回调接口的实现来处理这种情况。
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
button_test.setOnClickListener {
val input = edit_test.text.toString()
(activity as MyListener).inputComplete(input)
dismiss()
}
}
class MainActivity : AppCompatActivity(), TestPopup.MyListener {
override fun inputComplete(input: String) {
Toast.makeText(this, "Accept : $input", Toast.LENGTH_SHORT).show()
}
}
但是我认为这是一种与Observer模式不匹配的方式,我想尽可能地使用Observer模式来实现它。
我正在考虑从FragmentManager获取一个Fragment,然后再次在onCreate上进行订阅,但是我认为有更好的方法。
有人可以帮我吗?
答案 0 :(得分:1)
您对问题的理解是正确的,除了问题是任何配置更改(包括屏幕旋转)都会发生。您无需使用开发人员模式即可重现问题。尝试以下示例:
还要注意,您的“观察者模式”实现不是正确的观察者模式。观察者模式有一个主题和一个观察者。在您的实现中,活动同时充当主题和观察者。对话框不参与此观察者模式,而使用.setOnDismissListener
只是监听器模式的另一种形式。
为了在Fragment(主题)和Activity(观察者)之间实现观察者模式,Activity需要使用您所建议的FragmentManager获取Fragment的引用。我建议使用视图模型并在视图层和视图模型层之间建立观察者模式。
RxJava 示例:
//MainViewModel.kt
class MainViewModel: ViewModel() {
val dialogText = PublishProcessor.create<String>()
fun postNewDialogText(text: String) {
dialogText.onNext(text)
}
}
// Activity
val disposable = CompositeDisposable()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val viewModel = ViewModelProviders.of(this).get(MainViewModel::class.java)
viewModel.dialogText.subscribe {
Toast.makeText(this, "Accept : $it", Toast.LENGTH_SHORT).show()
}.addTo(disposable)
button.setOnClickListener {
TestPopup().show(supportFragmentManager, "TAG")
// usingRxJava(f)
// usingLiveData(f)
}
}
override fun onDestroy() {
disposable.dispose()
super.onDestroy()
}
// Dialog Fragment
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
// Important!! use activity when getting the viewmodel.
val viewModel = ViewModelProviders.of(requireActivity()).get(MainViewModel::class.java)
button_test.setOnClickListener {
viewModel.postNewDialogText(edit_test.text.toString())
dismiss()
}
}