You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MainActivity中LiveData Observer未响应Fragment数据更新问题

问题:LiveData无法在Activity与Fragment间共享数据

我期望通过LiveData实现MainActivity的TextView实时显示Fragment中EditText的输入内容,但当在Fragment的EditText中输入内容时,MainActivity中的Observer未被触发,TextView也没有做出响应。相关代码如下:

MainActivity代码

package com.example.translator

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.util.Log

import android.widget.EditText
import android.widget.TextView
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import com.example.translator.databinding.ActivityMainBinding;
import com.example.translator.databinding.FragmentTranslateBinding
import com.example.translator.viewmodellivedata.TranslateViewModel

class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding
    private lateinit var viewModel: TranslateViewModel


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding =ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        binding.translateText.text = "translation.."



        viewModel = ViewModelProvider(this).get(TranslateViewModel::class.java)
        viewModel.currentWord().observe(this, Observer {
            binding.translateText.text = it.toString()
            Log.d("current", it.toString())
        })




    }


}

TranslateViewModel代码

package com.example.translator.viewmodellivedata

import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.LiveData

class TranslateViewModel : ViewModel() {
    private var _currentWord = MutableLiveData<String>()


    fun currentWord(): LiveData<String> {
        return _currentWord
    }

    fun setCurrentWord(word: String) {
        _currentWord.value = word
    }



}

TranslateFragment代码

package com.example.translator

import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.text.TextWatcher
import android.text.Editable
import android.view.View
import android.view.ViewGroup
import android.util.Log
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import com.example.translator.databinding.FragmentTranslateBinding
import com.example.translator.viewmodellivedata.TranslateViewModel


// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private const val ARG_PARAM1 = "param1"
private const val ARG_PARAM2 = "param2"

/**
 * A simple [Fragment] subclass.
 * Use the [translateFragment.newInstance] factory method to
 * create an instance of this fragment.
 */
class translateFragment : Fragment() {
    // TODO: Rename and change types of parameters
    private var param1: String? = null
    private var param2: String? = null
    private var _binding: FragmentTranslateBinding? = null  // View Binding instance
    private val binding get() = _binding!!
    private lateinit var  viewModel: TranslateViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        arguments?.let {
            param1 = it.getString(ARG_PARAM1)
            param2 = it.getString(ARG_PARAM2)
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        _binding = FragmentTranslateBinding.inflate(inflater, container, false)
        val view = binding.root

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


        binding.editText.hint = "Write something..."




        // Add a TextWatcher to the EditText
        binding.editText.addTextChangedListener(object : TextWatcher {
            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
                // This method is called before text is changed
            }

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                // This method is called as text is changing
            }

            override fun afterTextChanged(s: Editable?) {
                // This method is called after text has changed
                val enteredText = s.toString()
                //binding.editText.setText(enteredText)
                //binding.translateText.text

                viewModel.setCurrentWord(enteredText)
                //viewModel.currentWord().observe(viewLifecycleOwner, Observer { word ->
                //    // This code will execute when the LiveData value changes
                ///    Log.d("current", word.toString())
               // })





                // Reattach the TextWatcher



                // You can perform translation or any other actions here with the enteredText
            }
        })


            //val view = binding.root

        //viewModel = ViewModelProvider(this).get(TranslateViewModel::class.java)
        return view
    }
    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }

    companion object {
        /**
         * Use this factory method to create a new instance of
         * this fragment using the provided parameters.
         *
         * @param param1 Parameter 1.
         * @param param2 Parameter 2.
         * @return A new instance of fragment translateFragment.
         */
        // TODO: Rename and change types and number of parameters
        @JvmStatic
        fun newInstance(param1: String, param2: String) =
            translateFragment().apply {
                arguments = Bundle().apply {
                    putString(ARG_PARAM1, param1)
                    putString(ARG_PARAM2, param2)
                }
            }
    }


}

解决方案

核心问题

当前代码的问题在于Fragment和MainActivity各自创建了独立的ViewModel实例,导致两者绑定的LiveData不是同一个对象,Fragment更新数据后,Activity观察的LiveData完全没有变化。

修改步骤

  1. Fragment中共享Activity的ViewModel实例
    在Fragment的onCreateView方法中,获取ViewModel时,将ViewModelProvider(this)改为ViewModelProvider(requireActivity()),这样Fragment就会使用Activity的ViewModelStore,和Activity共享同一个ViewModel实例:

    // 原代码
    // viewModel = ViewModelProvider(this).get(TranslateViewModel::class.java)
    // 修改后
    viewModel = ViewModelProvider(requireActivity()).get(TranslateViewModel::class.java)
    
  2. 优化命名规范(可选但推荐)
    将Fragment类名translateFragment改为TranslateFragment,符合Kotlin类名首字母大写的规范,避免代码风格不一致。

  3. 初始化LiveData默认值(可选)
    在ViewModel中给_currentWord设置默认值,避免首次观察时出现空值:

    private var _currentWord = MutableLiveData<String>("")
    

修改后的Fragment关键代码片段

class TranslateFragment : Fragment() {
    // ... 其他代码不变

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        _binding = FragmentTranslateBinding.inflate(inflater, container, false)
        val view = binding.root

        // 使用Activity的ViewModelStore获取共享实例
        viewModel = ViewModelProvider(requireActivity()).get(TranslateViewModel::class.java)

        // ... 其他代码不变
        return view
    }

    // ... 其他代码不变
}

完成以上修改后,Fragment输入内容时,会更新共享ViewModel里的LiveData,Activity的Observer就能实时收到数据变化,TextView也会同步更新。


内容的提问来源于stack exchange,提问作者Python coder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 17:14:56