#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»