如何在片段之外观察LiveData



我有一个TextView在一个片段。使用LiveData,我能够从片段内更改文本。通过使用MainActivity中的按钮(片段外),我试图改变TextView中的文本,但它不起作用。有人能帮忙吗?下面是我的代码:

这是一个MainActivity,它有一个按钮和一个片段

class MainActivity : AppCompatActivity() {
var tg: ToneGenerator? = null
private lateinit var btn: Button
private lateinit var viewModel:ViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
tg = ToneGenerator(AudioManager.STREAM_SYSTEM, 100)
btn = findViewById(R.id.buttonTest1)
viewModel = ViewModelProvider(this).get(ViewModel::class.java)
btn.setOnClickListener {
tg?.startTone(ToneGenerator.TONE_PROP_BEEP)
viewModel.changeMLD()
}
}
}

这个片段有一个TextView


class Fragment : Fragment() {
private lateinit var txt1: TextView
public lateinit var viewModel:ViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
val view: View = inflater.inflate(R.layout.fragment, container, false)
txt1 = view.findViewById(R.id.txt1)
viewModel = ViewModelProvider(this).get(ViewModel::class.java)
viewModel.initiateMLD()
viewModel.LD.observe(viewLifecycleOwner, Observer {
txt1.setText("Count is "+it)
})
return view
}
}

这是带有LiveData的ViewModel


class ViewModel : ViewModel(){
private var clickCount:Int = 0
private var MLD = MutableLiveData<Int>()
var LD : LiveData<Int> = getMLD()             // observer watches this variable
fun initiateMLD(){
MLD.value = 5
clickCount = 5
}
fun getMLD():MutableLiveData<Int>{
return MLD
}
fun changeMLD(){
clickCount+=2
MLD.value = clickCount
}
}

在您的fragment中,您使用fragment作为owner创建了viewModel

viewModel = ViewModelProvider(this).get(ViewModel::class.java)

然而,要与activity通信,您需要使用activity作为owner创建viewModel对象。这就是sharedViewModels

ViewModelProvider(requireActivity()).get(ViewModel::class.java)

你可以在这个codelab教程中阅读更多关于SharedViewModel的内容。

您正在使用2个不同的ViewModel实例。ViewModelProvider为您的活动创建一个,为您的片段创建一个。这是因为它们都是viewmodelstoreowner。如果你想在Fragment和Activity中使用相同的ViewModel实例。它必须是活动范围的。你可以这样做


ViewModelProvider(requireActivity()).get(ViewModel::class.java)