【问题标题】:Can't share Viewmodel between Activity and Fragment:无法在 Activity 和 Fragment 之间共享 Viewmodel:
【发布时间】:2019-10-28 17:20:34
【问题描述】:

Android Studio 3.6

这是我的视图模型:

import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.ViewModelProviders
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.*
class BluetoothPageViewModel(application: Application) : AndroidViewModel(application) {
    private val isSearchingTableModeLiveData = MutableLiveData<Boolean>()
    private val isInitModeLiveData = MutableLiveData<Boolean>()
    private val errorMessageLiveData = MutableLiveData<String>()
private val toastMessageLiveData = MutableLiveData<String>()

 fun isInitModeLiveData(): LiveData<Boolean> {
        return isInitModeLiveData
    }

    fun isSearchingTableModeLiveData(): LiveData<Boolean> {
        return isSearchingTableModeLiveData
    }

    fun getErrorMessageLiveData(): LiveData<String> {
        return errorMessageLiveData
    }


    fun getToastMessageLiveData(): LiveData<String> {
        return toastMessageLiveData
    }

这里片段订阅这个viewmodel和成功调用Observer.onChanged()

class BluetoothPageFragment : Fragment() {
private lateinit var bluetoothPageViewModel: BluetoothPageViewModel

 override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        dataBinding =
            DataBindingUtil.inflate(inflater, R.layout.bluetooth_page_fragment, container, false)
        val view = dataBinding.getRoot()
        dataBinding.setHandler(this)
        init()
        return view
    }

    private fun init() {
        val context = this.context
        val viewViewModelProvider = ViewModelProviders.of(this)
        bluetoothPageViewModel = viewViewModelProvider.get(BluetoothPageViewModel::class.java)

        bluetoothPageViewModel.isInitModeLiveData().observe(this, // SUCCESS CALL
            Observer<Boolean> { isInitMode ->

            })
}

我的活动是订阅此viewmodel不调用Observer.onChanged()

import androidx.lifecycle.ViewModelProviders
class QRBluetoothSwipeActivity : AppCompatActivity() {
private lateinit var bluetoothPageViewModel: BluetoothPageViewModel

 private fun init() {
        val viewViewModelProvider = ViewModelProviders.of(this)
        bluetoothPageViewModel = viewViewModelProvider.get(BluetoothPageViewModel::class.java)

        val customFragmentStateAdapter = CustomFragmentStateAdapter(this)
        customFragmentStateAdapter.addFragment(QrPageFragment())
        bluetoothPageFragment = BluetoothPageFragment()
        customFragmentStateAdapter.addFragment(bluetoothPageFragment)
        dataBinding.viewPager2.adapter = customFragmentStateAdapter

        initLogic()
    }

    private fun initLogic() {
        dataBinding.viewPager2.registerOnPageChangeCallback(object :
            ViewPager2.OnPageChangeCallback() {
            override fun onPageSelected(position: Int) {
                positionObservable.set(position)
            }
        })


         bluetoothPageViewModel.getToastMessageLiveData()  // this not call
            .observe(this,
                Observer<String> { message ->
                    Toast.makeText(this, message, Toast.LENGTH_LONG).show()
                })
}

为什么不打电话给getToastMessageLiveData()

【问题讨论】:

    标签: android android-livedata android-viewmodel


    【解决方案1】:

    在这两种情况下你都在使用

    ViewModelProviders.of(this)
    

    这意味着您希望此视图模型具有不同的范围。一个来自活动范围,一个来自片段范围。如果你想分享它。 如果要共享视图模型,则必须使用单个范围。我建议使用更大元素的范围,在这种情况下是活动。 在片段中你应该调用

    ViewModelProviders.of(activity)
    

    这应该可以解决您的问题。

    【讨论】:

      【解决方案2】:

      您在活动和片段中都调用ViewModelProviders.of(this),但这是不同的上下文。因此,在您的情况下,您实例化了 2 个不同的 BluetoothPageViewModel 实例,因此不会调用 onChanged 回调。

      为了在 Activity 和 Fragment 之间共享一个实例,您应该从同一上下文中获取 viewModelProvider。 在您的活动中: ViewModelProviders.of(this) 在您的片段中: ViewModelProviders.of(activity)

      activity?.let {
          val bluetoothPageViewModel = ViewModelProviders.of(it).get(BluetoothPageViewModel::class.java)
      
          bluetoothPageViewModel.isInitModeLiveData().observe(this, // SUCCESS CALL
                  Observer<Boolean> { isInitMode ->
      
                  })
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-11-10
        • 2017-01-12
        • 1970-01-01
        • 2021-06-27
        • 1970-01-01
        • 2021-04-09
        相关资源
        最近更新 更多