片段中的 Android Room ViewModel 初始化崩溃应用程序

时间:2020-12-29 13:50:04

标签: android kotlin android-room

情况非常简单。我有一个简单的 android 应用程序,通过底部导航栏显示 4 个片段,以及一个中央 Room 数据库。每个片段都应该能够通过视图模型对数据库执行 CRUD 操作(细节可能无关紧要,但我也会展示这一点以确保):

class ViewModel(application: Application): AndroidViewModel(application) {
    val readAllIngredients: LiveData<List<Ingredient>>
    val readAllRecipes: LiveData<List<Recipe>>
    private val ingredientRepository: IngredientRepository
    private val recipeRepository: RecipeRepository

    init {
        val ingredientDAO = ShoppingAppDatabase.getDatabase(application).ingredientDAO()
        val recipeDAO = ShoppingAppDatabase.getDatabase(application).recipeDAO()
        ingredientRepository = IngredientRepository(ingredientDAO)
        recipeRepository = RecipeRepository(recipeDAO)
        readAllIngredients = ingredientRepository.allIngredients
        readAllRecipes = recipeRepository.allRecipes
    }

    fun addIngredient(ingredient: Ingredient) {
        viewModelScope.launch(Dispatchers.IO) {
            ingredientRepository.put(ingredient)
        }
    }

    fun deleteIngredient(ingredient: Ingredient) {
        viewModelScope.launch(Dispatchers.IO) {
            ingredientRepository.delete(ingredient)
        }
    }

    fun addRecipe(recipe: Recipe) {
        viewModelScope.launch(Dispatchers.IO) {
            recipeRepository.put(recipe)
        }
    }

    fun updateRecipe(recipe: Recipe) {
        viewModelScope.launch(Dispatchers.IO) {
            recipeRepository.update(recipe)
        }
    }

    fun updateIngredient(ingredient: Ingredient) {
        viewModelScope.launch(Dispatchers.IO) {
            ingredientRepository.update(ingredient)
        }
    }
}

我正在每个片段中初始化一个视图模型,但成功率有限。这是一个一切正常的片段:

class InventoryFragment() : Fragment() {
    private var listAdapter = IngredientAdapter()
    private 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
        return inflater.inflate(R.layout.fragment_inventory, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        listAdapter = IngredientAdapter()
        recycler_view.apply {
            layoutManager = LinearLayoutManager(activity)
            adapter = listAdapter
        }
        viewModel = ViewModelProvider(this).get(ViewModel::class.java)
        viewModel.readAllIngredients.observe(viewLifecycleOwner, Observer { ingredient -> listAdapter.setData(ingredient) })
        add_button.setOnClickListener{
            val errorMessages = validateInput()
            if(errorMessages.isNotEmpty()) {
                displayToast(activity, errorMessages)
            }
            else {
                viewModel.addIngredient(Ingredient(
                    edit_name.text.toString(),
                    edit_qty.text.toString().toFloat(),
                    edit_um.text.toString()
                ))
                listAdapter.notifyDataSetChanged()
                displayToast(activity, "Ingredient added")
                hideKeyboard(activity, requireView().windowToken)
            }
            clearInput()
        }
    }
}

我在 onViewCreated 回调中初始化它,是的,它工作正常。在不同的片段中做同样的事情会产生......出于某种原因的不同结果。

class BrowseFragment() : Fragment() {
    private lateinit var viewModel: ViewModel
    var recipeAdapter = RecipeAdapter()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_browse, container, false)
    }


    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        viewModel = ViewModelProvider(this).get(ViewModel::class.java)
        viewModel.readAllRecipes.observe(viewLifecycleOwner, Observer { recipe -> recipeAdapter.setData(recipe) })
        submit_button.setOnClickListener{
            var submitFragment = SubmitFragment(recipeAdapter)
            var tr = (view.context as FragmentActivity).supportFragmentManager.beginTransaction()
            tr.replace(R.id.fragment_container, submitFragment)
            tr.commit()
        }
        browse_recycler_view.apply {
            layoutManager = LinearLayoutManager(activity)
            adapter = recipeAdapter
        }
    }
}

当我尝试在 onViewCreated 中初始化视图模型时,出现 IllegalStateException: Can't access ViewModels from detached fragment 异常。在 onCreate 中创建它也不起作用,因为生命周期所有者为空,我想这是有道理的。我到底做错了什么?

0 个答案:

没有答案
相关问题