Room cannot load data directly

Viewed 49

I am an beginner. My experience when i create an apps, usually i using clean archi and mvvm for the architect, and when using room, it will be use live data also.

But when i create a simple apps don't want to use them, i have trouble with the data which is cannot load directly, please help me. Below is my code

WisataDao.kt

@Dao
interface WisataDao {
    @Query("SELECT * from wisata")
    fun getAll(): List<WisataEntity>

    @Query("SELECT * from wisata WHERE id = :id")
    fun getById(id: String): Boolean

    @Insert(onConflict = REPLACE)
    fun insert(wisata: WisataEntity)

    @Delete
    fun delete(wisata: WisataEntity)
}

WisataDatabase.kt

@Database(entities = [WisataEntity::class], version = 1)
abstract class WisataDatabase : RoomDatabase() {

    abstract fun wisataDao(): WisataDao
    companion object {
        private var INSTANCE: WisataDatabase? = null

        fun getInstance(context: Context): WisataDatabase? {
            if (INSTANCE == null) {
                synchronized(WisataDatabase::class) {
                    INSTANCE = Room.databaseBuilder(context.applicationContext,
                        WisataDatabase::class.java, "wisata.db")
                        .build()
                }
            }
            return INSTANCE
        }

        fun destroyInstance() {
            INSTANCE = null
        }
    }
}

FavoriteFrament.kt

class FavoriteFragment : Fragment() {
    private lateinit var binding: FragmentFavoriteBinding
    private lateinit var database: WisataDatabase

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        binding = FragmentFavoriteBinding.inflate(layoutInflater, container, false)
        return binding.root
    }

    @DelicateCoroutinesApi
    @SuppressLint("NotifyDataSetChanged")
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        database = WisataDatabase.getInstance(requireContext())!!

        binding.rvWisata.layoutManager = LinearLayoutManager(context)
        val list = ArrayList<WisataEntity>()

        var adapter = HomeAdapter(list)

        GlobalScope.launch {
            coroutineContext.run {
                list.addAll(database.wisataDao().getAll())
                adapter = HomeAdapter(list)
                adapter.notifyDataSetChanged()
            }
        }

        binding.rvWisata.adapter = adapter

        adapter.setOnItemClickCallback(object : HomeAdapter.OnItemClickCallback {
            override fun onItemClicked(data: WisataEntity) {
                val intent = Intent(context, DetailActivity::class.java)
                intent.putExtra("data", data)
                startActivity(intent)
            }
        })
    }
}

Please help me guys

1 Answers

The problem is you are initializing the adapter twice but only assigning it once.

    //Here 1st initialization
    var adapter = HomeAdapter(list)

    GlobalScope.launch {
        coroutineContext.run {
            list.addAll(database.wisataDao().getAll())
            //Here 2nd initialization
            //but no assignment now the RecyclerView has an adapter
            //that doesn't exist anymore because you overwrote it 
            adapter = HomeAdapter(list)
            adapter.notifyDataSetChanged()
        }
    }
    //Here 1 assignment
    //You assign the 1st initialized adapter
    //that has no data.
    binding.rvWisata.adapter = adapter

What you want to do is add a function to the Adapter that accepts a List and pass in the new List to the Adapter and notify the changes.

    GlobalScope.launch {
        coroutineContext.run {
            list.addAll(database.wisataDao().getAll())
            //Here 2nd initialization
            adapter.setList(list)
            adapter.notifyDataSetChanged()
        }
    } 
Related