Интеллектуальное приведение к ListViewModel невозможно, так как binding.listViewModel является изменяемым свойством, которое могло быть изменено к этому времени. - PullRequest
0 голосов
/ 03 ноября 2019

Я делаю маленькую таскер для андроида с kotlin. Я разделил основное действие на несколько фрагментов, а затем создал ViewModel для каждого. Но теперь здесь появилась проблема с умным приведением.

Вот некоторый код:

class ListFragment : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?): View? {

        val binding: FragmentListBinding = DataBindingUtil.inflate(
            inflater, R.layout.fragment_list, container, false)

        val application = requireNotNull(this.activity).application

        val dataSource = TaskDatabase.getInstance(application).taskDatabaseDao

        val viewModelFactory = ListViewModelFactory(dataSource, application)

        val listViewModel =
            ViewModelProviders.of(this, viewModelFactory).get(ListViewModel::class.java)

        binding.listViewModel = listViewModel

        binding.setLifecycleOwner(this)

        binding.addButton.setOnClickListener {
            findNavController().navigate(R.id.action_listFragment_to_createTaskFragment)
        }

        binding.listViewModel.tasks.observe(this, Observer {
            it?.forEach {
                Log.i("ListFragment", "tasks exist")
                val radioButton = RadioButton(context)
                radioButton.text = it.title
                radioButton.visibility = View.VISIBLE
                radioButton.setOnClickListener {
                    Toast.makeText(context, "Working", Toast.LENGTH_SHORT).show()
                }
            }
        })

        return binding.root
    }
}
class ListViewModel(
    val database: TaskDao,
    application: Application) : AndroidViewModel(application) {

    private val viewModelJob = Job()

    private val uiScope = CoroutineScope(Dispatchers.Main + viewModelJob)

    private val _tasks = MutableLiveData<List<Task>>()
    val tasks: LiveData<List<Task>>
        get() = _tasks

    init {
        initializeTasks()
    }

    private fun initializeTasks() {
        uiScope.launch {
            _tasks.value = getTasksFromDatabase()?.value
            Log.i("ListViewModel", "something")
        }
    }

    private suspend fun getTasksFromDatabase(): LiveData<List<Task>>? {
        return withContext(Dispatchers.IO) {
            database.getAllTasks()
        }
    }

    override fun onCleared() {
        super.onCleared()
        viewModelJob.cancel()
    }
}

Я ожидал увидеть некоторые созданные радио-кнопки на главном экране с помощью метода наблюдателя, но вместо этого я получил исключение, которое упоминается в заголовке этого вопроса. Заранее благодарю за помощь!

1 Ответ

2 голосов
/ 03 ноября 2019

Вместо использования

binding.listViewModel.tasks.observe(this, Observer {

Просто используйте переменную listViewModel, которая у вас уже есть:

listViewModel.tasks.observe(this, Observer {

Это работает, потому что ваш listViewModel является val - т.е. неизменяемая, никогда не пустая переменная. Это отличается от binding.listViewModel, который является изменяемой переменной с нулевым значением - хотя вы знаете, что она не равна нулю, так как вы вызвали binding.listViewModel = listViewModel, компилятор не знает, был ли какой-то другой поток, который установил его обратно в null.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...