Невозможно разделить Viewmodel между Activity и Fragment: - PullRequest
1 голос
/ 28 октября 2019

Android Studio 3.6

Вот мой viewModel:

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()?

Ответы [ 2 ]

1 голос
/ 28 октября 2019

В обоих случаях вы используете

ViewModelProviders.of(this)

Это означает, что вы хотите эту модель просмотра с разными областями действия. Один из области действия и один из области действия фрагмента. Если вы хотите поделиться этим. Если вы хотите поделиться viewmodel, вы должны использовать одну область видимости. Я рекомендую использовать область большего элемента, в этом случае активность. Во фрагменте вы должны позвонить

ViewModelProviders.of(activity)

Это должно исправить вашу проблему.

1 голос
/ 28 октября 2019

вы называете ViewModelProviders.of(this) и в действии, и во фрагменте, но это разные контексты. Таким образом, в вашем случае вы создаете 2 разных экземпляра BluetoothPageViewModel, поэтому onChanged обратный вызов не вызывается.

Чтобы разделить один экземпляр между действием и фрагментом, вы должны получить 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 ->

            })
}
...