Данные о помещении не отображаются в списке переработчиков

#android #kotlin #android-room #android-mvvm

Вопрос:

Это первый раз, когда используются данные о помещении, а также используется шаблон MVVM. Цель состоит в том, что я хочу, чтобы мои данные появлялись в списке переработчиков, но он не закрывается и не показывает мне никаких ошибок, он просто кажется пустым.

Вот мой класс базы данных:

 @Database(entities = [Plant::class, Plant_Category::class], version = 1)
abstract class PlantDatabase:RoomDatabase() {
    abstract fun plantDao(): PlantOperations
    abstract fun plantCategoryDao(): PlantCategoryOperations

    companion object {
        private var INSTANCE: PlantDatabase? = null
             
        fun getDatabase(context: Context): PlantDatabase {
            if (INSTANCE == null) {

                INSTANCE = Room.databaseBuilder(
                    context.applicationContext,
                    PlantDatabase::class.java, DB_NAME // contains directory of sqlite database
                ) 
                    .fallbackToDestructiveMigration()
                    .build()
            }

            return INSTANCE!!
        }
    }
}
 

Мой класс дао:

 @Dao
interface PlantOperations {
    @Query("SELECT * FROM Plant")
    fun getAll(): Flow<List<Plant>>

    @Insert
    fun insertPlant( plant: Plant)

    @Delete
    fun delete(plant:Plant)

    @Update
    fun updatePlant(plant:Plant)}
 

Это мой класс репозитория:

 class PlantRepository(application:Application){
    private var allPlants = MutableLiveData<List<Plant>>()

    private val plantDAO = PlantDatabase.getDatabase(application).plantDao()

    init {
        CoroutineScope(Dispatchers.IO).launch {
            val plantData = plantDAO.getAll()
            plantData.collect{
                allPlants.postValue(it)
            }
        }
    }
    fun getAllPlants(): MutableLiveData<List<Plant>> {
        return allPlants
    }
    

}
 

Мой класс Viewmodel:

 class PlantViewModel(
            application: Application
    ): AndroidViewModel(application) {

        private var repository = PlantRepository(application)

        private var _allPlants = repository.getAllPlants()

        val allPlants: MutableLiveData<List<Plant>>
            get() = _allPlants
    }

 

My Recycler in Fragment:

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

        lateinit var  photoAdapter: Photo_Adapter
        lateinit var plantViewModel: PlantViewModel

       
        val view: View = inflater.inflate(R.layout.fragment_edit__form, container, false)
        val fab = view.findViewById(R.id.floatingActionButton) as FloatingActionButton
        val recyclerView = view.findViewById(R.id.recyclerView) as RecyclerView
          
      

        recyclerView.layoutManager = GridLayoutManager(context, 2)
        photoAdapter = Photo_Adapter(context)
        recyclerView.adapter = photoAdapter

         plantViewModel = ViewModelProvider(this).get(PlantViewModel::class.java)
        plantViewModel.allPlants.observe(viewLifecycleOwner, androidx.lifecycle.Observer {
            photoAdapter.setDataList(it)
        })

       // photoAdapter.setDataList(dataList)
        //Floating button that opens the Form in order to add plant
        fab?.setOnClickListener {

            val intent = Intent(view.context, Edit_Form::class.java)
           startActivity(intent);
        }
        return view
    }


 

Это мой класс адаптера:

 class Photo_Adapter(var context: Context?) : RecyclerView.Adapter<Photo_Adapter.ViewHolder>() {

        var dataList = emptyList<Plant>()

        internal fun setDataList(dataList: List<Plant>) {
            this.dataList = dataList
            notifyDataSetChanged()
        }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        // Get the data model based on position
        var data = dataList[position]


        holder.title.text = data.name
        holder.desc.text = data.type.toString()


        holder.image.setImageResource(data.image)
        holder.relativeLayout.setOnClickListener { view -> //Toast.makeText(view.getContext(),"click on item: " model.getTitle(),Toast.LENGTH_LONG).show();
            val intent = Intent(view.context, PlantDetails::class.java)
            intent.putExtra("plant_name", data.name)
            intent.putExtra("plant_image",data.image)
            intent.putExtra("plant_type", data.type.type)
            intent.putExtra("plant_water", data.type.water_time)
            intent.putExtra("plant_details", data.type.details)
            view.context.startActivity(intent)
    }

}
        // Provide a direct reference to each of the views with data items

        class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
            var image: ImageView
            var title: TextView
            var desc: TextView
            var relativeLayout: CardView

            init {
                image = itemView.findViewById(R.id.image)
                title = itemView.findViewById(R.id.title)
                desc = itemView.findViewById(R.id.desc)
                relativeLayout = itemView.findViewById<View>(R.id.relativeLayout) as CardView
            }

        }

        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Photo_Adapter.ViewHolder {

            // Inflate the custom layout
            var view = LayoutInflater.from(parent.context).inflate(R.layout.photo_layout, parent, false)
            return ViewHolder(view)
        }


        //  total count of items in the list
        override fun getItemCount() = dataList.size

}

 

Может быть, я забыл что-то добавить? В любом случае я буду благодарен вам за помощь.

Комментарии:

1. android-studio тег используется, когда вы задаете вопрос о самой среде разработки, похоже, что любой ответ, который вы получите здесь, будет зависеть от среды разработки, поэтому я удалил его из вашего поста, нет необходимости добавлять его, если вы не спрашиваете об среде разработки

Ответ №1:

Вы не должны просматривать данные в своем репозитории, ваша активность/представление должны отслеживать эти данные. Взгляните на это:

Во-первых, добавьте эту зависимость в свой класс:

 implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1"
 

Затем в вашем хранилище

 class PlantRepository(application:Application){
     private val plantDAO = PlantDatabase.getDatabase(application).plantDao()
     fun getAllPlants(): Flow<List<Plant>> = plantDAO.getAll()
}
 

В вашей модели представления:

 class PlantViewModel(
        application: Application
): AndroidViewModel(application) {
    private var repository = PlantRepository(application)
    val allPlants = repository.getAllPlants()
                   .flowOn(Dispatchers.IO)
                   .asLiveData()
}
 

И ваша активность в порядке, но проверьте свой адаптер, убедитесь, что вы уведомляете свой адаптер о том, что ваш список изменился.
Вы также можете работать (собирать) потоки на своем представлении, но это зависит от вас

Комментарии:

1. Я последовал вашему совету, и это не сработало, я также добавил свой адаптер в код.

2. В коде нет ничего плохого, вы уверены, что у вас есть данные в вашей базе данных? Если вы установите точку останова в photoAdapter.setDataList(…) вашего фрагмента, он будет вызван?

3. Я проверил, что у меня есть данные в базе данных, думаю, я сделаю точку останова

4. это показывает мне, что размер списка равен 0, даже если база данных содержит данные

5. Итак, что-то не так с вашим dao я вижу, что вы используете поток в качестве возвращаемого типа, проверьте, есть ли у вас эти 3 зависимости: реализация «androidx.room:room-время выполнения:2.3.0» реализация «androidx.room:room-ktx:2.3.0» kapt «androidx.room:room-компилятор:2.3.0»