Search code examples
androidandroid-recyclerviewadapterviewmodel

visit ViewModel in Recycler´s Adapter


i am stuck in the problem that, i want to visit my ViewModel in a RecyclerView´s Adapter, but i have the Exception: "Your activity is not yet attached to the Application instance. You can't request ViewModel before onCreate call"

class FoodInSortAdapter( val activity:MainActivity,private val list:List<String>):RecyclerView.Adapter<FoodInSortAdapter.Holder>() {

    val viewModel :FoodViewModel by lazy {
        println("servus")
        ViewModelProvider(activity).get(FoodViewModel::class.java)}

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.sortitem, parent, false)
        return Holder(view)
    }


    override fun onBindViewHolder(holder: Holder, position: Int) {
        holder.sortName.text = list[position]
        holder.itemView.setOnClickListener {
            val m=list[position]
            viewModel.setQuery(m)
        }
    }

anyone know what ´s wrong?

thanks


Solution

  • First things first, you should not initialize viewModel outside of activity or fragment.

    I assume you do not create adapter in onCreate but during initialization phase. There are two solution for your concern.

    1. Initialize vm in activity, and set it in adapter by newly added method setupViewModel, called in onCreate. That's the better one.
    class FooActivity : Activity{
    
      private val viewModel: FoodViewModel by lazy {
            println("servus")
            ViewModelProvider(activity).get(FoodViewModel::class.java)
      }
    
      private val adapter = FoodInSortAdapter(emptyList())
    
      override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            adapter.setupViewModel(viewModel)
      }
    
    }
    
    class FoodInSortAdapter(private val list:List<String>):RecyclerView.Adapter<FoodInSortAdapter.Holder>() {
    
        private lateinit var viewModel: FoodViewModel
    
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
            val view = LayoutInflater.from(parent.context).inflate(R.layout.sortitem, parent, false)
            return Holder(view)
        }
    
    
        override fun onBindViewHolder(holder: Holder, position: Int) {
            holder.sortName.text = list[position]
            holder.itemView.setOnClickListener {
                val m=list[position]
                viewModel.setQuery(m)
            }
        }
    
       fun setupViewModel(vm: FoodViewModel){
          viewModel = vm
       }
    }
    
    1. Create adapter in onCreate method, that should also work for you.

    Cheers