One-to-many in Room with Kotlin - android

The task is to open an activity with notes attached to this diary when you select a single diary.
(one-to-many)
This is how entities in the database look like:
#Entity(tableName = "word_table")
data class Word(#ColumnInfo(name = "word") val word: String,
#ColumnInfo(name = "description") val description : String
)
{
#ColumnInfo(name = "id")
#PrimaryKey(autoGenerate = true)
var id : Long = 0
}
#Entity(tableName = "note_table")
data class Note(#ColumnInfo(name = "note_name") val note : String,
#ColumnInfo(name = "text") val text : String,
#ColumnInfo(name = "diaryId") val diaryId : Long
){
#PrimaryKey(autoGenerate = true)
var idNote : Long = 0
}
Using a data class in NoteRepository.kt
data class NotesAndWords (#Embedded val word : Word,
#Relation(parentColumn = "id", entityColumn = "diaryId")
val notes : List<Note>)
And a Query in WordDao.kt
#Transaction
#Query("SELECT * from word_table ")
fun getSomeNotes() : LiveData<List<NotesAndWords>>
I get the data and save it in the NoteRepository class:
class NoteRepository (private val wordDao : WordDao) {
var allNotes : LiveData<List<NotesAndWords>> = wordDao.getSomeNotes()
suspend fun insertNote(note : Note)
{
wordDao.insertNote(note)
}
}
Then via NoteViewModel.kt passing data to NoteActivity.kt:
class NoteViewModel(application: Application) : AndroidViewModel(application) {
private val repository: NoteRepository
val allNotes: LiveData<List<NotesAndWords>>
init {
val wordsDao = WordRoomDatabase.getDatabase(application, viewModelScope).wordDao()
repository = NoteRepository(wordsDao)
allNotes = repository.allNotes
}
fun insertNote(note: Note) = viewModelScope.launch {
repository.insertNote(note)
}
}
(NoteActivity.kt)
class NoteActivity : AppCompatActivity() {
private val newWordActivityRequestCode = 1
private lateinit var noteViewModel: NoteViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_note)
val adapter = NoteListAdapter(this, intent.getLongExtra("tag", -1) ){
val intent = Intent(this, ClickedActivity::class.java)
intent.putExtra("tag", it.note)
startActivity(intent)
}
recyclerview1.adapter = adapter
recyclerview1.layoutManager = LinearLayoutManager(this)
noteViewModel = ViewModelProvider(this).get(NoteViewModel::class.java)
noteViewModel.allNotes.observe(this, Observer {
adapter.setNotes(it)
})
val fab = findViewById<FloatingActionButton>(R.id.fab)
fab.setOnClickListener {
val intent = Intent(this, NewWordActivity::class.java)
startActivityForResult(intent, newWordActivityRequestCode)
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == newWordActivityRequestCode && resultCode == Activity.RESULT_OK)
{
data?.getStringArrayListExtra(NewWordActivity.EXTRA_REPLY)?.let {
val note = Note(it[0], it[1], intent.getLongExtra("tag", -1))
noteViewModel.insertNote(note)
}
}
else
{
Toast.makeText(applicationContext, R.string.empty_not_saved,
Toast.LENGTH_LONG).show()
}
}
Then, in the adapter, I use MutableMap to transform the list so that the key is the name id and the value is the notes selected on request (attached to a specific diary)
NoteListAdapter.kt:
class NoteListAdapter internal constructor(
context: Context,
val wordId: Long,
private val listener : (Note) -> Unit
) : RecyclerView.Adapter<NoteListAdapter.NoteViewHolder>() {
private val inflater: LayoutInflater = LayoutInflater.from(context)
//private val mContext = context
private var notes = emptyList<NotesAndWords>() // Cached copy of words
private var notesMapped = mutableMapOf<Long, List<Note>>()
inner class NoteViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val noteItemView: TextView = itemView.findViewById(R.id.textView1)
private val noteDescriptionView: TextView = itemView.findViewById(R.id.textView)
fun bindView(note: Note, listener : (Note) -> Unit) {
noteItemView.text = note.diaryId.toString()
noteDescriptionView.text = note.text
itemView.setOnClickListener {
listener(note)
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NoteViewHolder {
val itemView = inflater.inflate(R.layout.recyclerview_layout, parent,
false)
return NoteViewHolder(itemView)
}
override fun onBindViewHolder(holder: NoteViewHolder, position: Int) {
holder.bindView(notesMapped[wordId]!![position], listener)
}
internal fun setNotes(notes: List<NotesAndWords>) {
this.notes = notes
for (i in this.notes) {
notesMapped[i.word.id] = i.notes
}
notifyDataSetChanged()
}
override fun getItemCount() = notesMapped[wordId]!!.size
}
Database:
#Database(entities = [Word::class, Note::class], version = 2, exportSchema = false)
abstract class WordRoomDatabase : RoomDatabase() {
abstract fun wordDao(): WordDao
private class WordDatabaseCallback(private val scope: CoroutineScope) : RoomDatabase.Callback()
{
override fun onOpen(db: SupportSQLiteDatabase) {
super.onOpen(db)
INSTANCE?.let { database ->
scope.launch {
populateDatabase(database.wordDao())
}
}
}
suspend fun populateDatabase(wordDao: WordDao) {
//wordDao.deleteAll()
//wordDao.deleteAllNotes()
}
}
companion object {
#Volatile
private var INSTANCE: WordRoomDatabase? = null
fun getDatabase(context: Context, scope:CoroutineScope): WordRoomDatabase {
val tempInstance = INSTANCE
if (tempInstance != null) {
return tempInstance
}
val instance = Room.databaseBuilder(context.applicationContext,
WordRoomDatabase::class.java, "word_database")
.addCallback(WordDatabaseCallback(scope))
//.fallbackToDestructiveMigration()
.build()
INSTANCE = instance
return instance
}
}
}
I've created several diaries and one note in each of them, using the buttons to create new diaries and notes. Now, if you select several diaries in turn, then on some attempt to select a diary, a NullPointerException is issued in the adapter, in this line:
override fun getItemCount() = notesMapped[wordId]!!.size
Why is this exception thrown if notesMapped always has the wordId key?
NoteActivity is called from another activity and the diary id is passed to it
This repository on GitHub: https://github.com/Lomank123/RoomDatabase
Edit:
noteViewModel.allNotes.observe(this, Observer {
var getList = emptyList<Note>()
for(i in it)
{
if(i.word.id == wordId)
{
getList = i.notes
break
}
}
adapter.setNotes(getList)
})
I've changed the Observer in NoteActivity and changed setNotes() method in adapter, but now it returns nothing. With for() I get the right notes and give them to adapter.setNotes(). If it doesn't work, how can I get the correct list of notes?

Hi initially the map is empty and the map is returning a null value and you are checking size on a null object.
Also as a good practice do not use a map instead use a list of notes only and pass the list directly.

Related

App crashing while creating Dao object for room database

My app is crashing and the only thing I know for sure is that the main problem is this line ->
val placesDao = (application as HotspotBucketApp).placesDb.placesDao()
can any one tell please me why is this happening.
private fun getPlaceList() {
val placesDao = (application as HotspotBucketApp).placesDb.placesDao()
lifecycleScope.launch {
placesDao.fetchAllPlaces().collect {
placeList = ArrayList(it)
}
if (placeList.isNotEmpty()) {
lastId = placeList[placeList.size - 1].id
}
}
}
class HotspotBucketApp: Application() {
val placesDb by lazy {
PlacesDatabase.getInstance(this)
}
}
#Dao
interface PlacesDao {
#Query("select * from `placesTable`")
fun fetchAllPlaces(): Flow<List<PlaceEntity>>
#Insert
suspend fun insert(placeEntity: PlaceEntity)
#Delete
suspend fun delete(placeEntity: PlaceEntity)
}
#Database(entities = [PlaceEntity::class], version = 1)
abstract class PlacesDatabase: RoomDatabase() {
abstract fun placesDao(): PlacesDao
companion object {
#Volatile
private var INSTANCE: PlacesDatabase? = null
private const val PLACES_DB_NAME = "place_database"
fun getInstance(context: Context): PlacesDatabase {
synchronized(this) {
var instance = INSTANCE
if (instance == null) {
instance = Room.databaseBuilder(context.applicationContext, PlacesDatabase::class.java, PLACES_DB_NAME)
.fallbackToDestructiveMigration()
.build()
INSTANCE = instance
}
return instance
}
}
}
}
#Entity(tableName = "placesTable")
data class PlaceEntity(
#PrimaryKey
val id: Int,
val title: String,
val image: String,
val description: String,
val date: String,
val location: String,
val latitude: Double,
val longitude: Double
)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding?.root)
setSupportActionBar(binding?.addPlacesToolBar)
if (Build.VERSION.SDK_INT >= 33) {
onBackInvokedDispatcher.registerOnBackInvokedCallback(
OnBackInvokedDispatcher.PRIORITY_DEFAULT
) {
finish()
}
} else {
onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
finish()
}
})
}
getPlaceList()
binding?.fABAddPlaces?.setOnClickListener {
val intent = Intent(this, AddPlaceActivity::class.java)
intent.putExtra("lats_place_id", lastId)
startActivity(intent)
}
}

How can i unit test my repository and viewmodel?

I want to unit test my viewmodel and repository but I don't know how I can achieve that. I have made a start wit the viewmodeltestclass but I don't know how I can go further and what the best approach is. Should I also test my endpoint class and mainactivity? can someone help me please?
This is my endpoint class:
interface VenuesEndpoint {
#GET("v2/venues/search")
suspend fun get(
#Query("near") city: String,
#Query("limit") limit: String = Constants.LIMIT,
#Query("radius") radius: String = Constants.RADIUS,
#Query("client_id") id: String = Constants.CLIENT_ID,
#Query("client_secret") secret: String = Constants.CLIENT_SECRET,
#Query("v") date: String
): VenuesMainResponse
}
My repository class:
private val _data: MutableLiveData<VenuesMainResponse?> = MutableLiveData(null)
val data: LiveData<VenuesMainResponse?> get() = _data
suspend fun fetch(city: String, date: String) {
val retrofit = ApiClient()
val api = retrofit.retro.create(VenuesEndpoint::class.java)
try {
val response = api.get(
city = city,
date = date
)
_data.value = response
} catch (e: Exception) {
Log.d(TAG, e.message.toString())
_data.value = null
}
}
}
My viewmodel class:
class VenueViewModel() : ViewModel() {
private val repository = VenuesRepository()
val data: LiveData<VenuesMainResponse?> = repository.data
fun getData(city: String, date: String) {
viewModelScope.launch {
repository.fetch(city, date)
}
}
}
My mainActivity class:
class MainActivity : AppCompatActivity() {
private val viewModel by viewModels<VenueViewModel>()
private lateinit var adapter: HomeAdapter
private var searchData: List<Venue>? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val editText = findViewById<EditText>(R.id.main_search)
viewModel.getData(
city = Constants.CITY,
date = Constants.DATE
)
viewModel.data
.observe(this, Observer {
it.let {
initAdapter()
rv_home.visibility = View.VISIBLE
if (it != null) {
adapter.setData(it.response.venues.sortedBy { myObject -> myObject.name })
searchData = it.response.venues.sortedBy { myObject -> myObject.name }
} else {
Toast.makeText(this, Constants.ERROR_MESSAGE_API, Toast.LENGTH_SHORT).show()
}
}
})
}
My ViewModelTest class:
#RunWith(AndroidJUnit4::class)
class VenueViewModelTest : TestCase() {
private lateinit var viewModel: VenueViewModel
#Before
public override fun setUp() {
super.setUp()
viewModel = VenueViewModel()
}
#Test
fun testVenueViewModel()
{
}
}

RecycleViewer not showing anything in the list after update in Firebase database

I got a problem and I can't see an error in my code, maybe You'll help me. I've got an application in Android Studio that uses connection with Firebase. I add products to the database by a button and in the activity that holds RecycleViever, it lists that product there. The problem is that RecycleViewer shows nothing, even though that my button adds product to the Firebase. That RecycleViewer should list products from Firebase. I add product with It's structure:
data class Product(var name: String, var price: Double, var quantity: Long, var bought: Boolean) {
var id: String = ""
companion object {
fun fromContentValues(values: ContentValues?): Product {
values?.let{
return Product(
values.getAsString("name"),
values.getAsDouble("price"),
values.getAsLong("amount"),
values.getAsBoolean("bought"))
} ?: throw IllegalArgumentException()
}
}
#Exclude
fun toMap(): Map<String, Any?> {
return mapOf(
"id" to id,
"name" to name,
"price" to price,
"quantity" to quantity,
"bought" to bought
)
}
}
Product Repository:
class ProductRepository(private val dbRef: DatabaseReference) {
fun insert(product: Product) {
val key = dbRef.push().key
if (key == null) {
Log.w("error", "Couldn't get push key for posts")
return
}
product.id = key
val productValues = product.toMap()
val childUpdates = hashMapOf<String, Any>(
key to productValues
)
dbRef.updateChildren(childUpdates)
}
fun update(product: Product){
val productValues = product.toMap()
val childUpdates = hashMapOf<String, Any>(
product.id to productValues
)
dbRef.updateChildren(childUpdates)
}
fun delete(key: String){
dbRef.child(key).removeValue()
}
}
Product ViewModel:
class ProductViewModel(app: Application) : AndroidViewModel(app) {
private val repo: ProductRepository
val allProducts: MutableList<Product>
init {
allProducts = arrayListOf()
val database = FirebaseDatabase.getInstance()
val reference : DatabaseReference = database.getReference("database/products")
var name: String
var price: Double
var amount: Long
var bought: Boolean
reference.addValueEventListener(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
for (product in snapshot.children) {
name = product.child("name").value as String
price = product.child("price").value as Double
amount = product.child("amount").value as Long
bought = product.child("bought").value as Boolean
val newProduct = Product(name, price, amount, bought)
allProducts.add(newProduct)
}
}
override fun onCancelled(error: DatabaseError) {
Log.w("error", "loadPost:onCancelled", error.toException())
}
})
repo = ProductRepository(reference)
}
fun insert(product: Product) {
repo.insert(product)
}
fun update(product: Product) {
repo.update(product)
}
fun delete(product: Product) {
repo.delete(product.id)
}
}
My Adapter:
class ProductsAdapter(val productViewModel: ProductViewModel) : RecyclerView.Adapter<ProductsAdapter.ViewHolder>() {
private var products = mutableListOf<Product>()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProductsAdapter.ViewHolder {
val inflater = LayoutInflater.from(parent.context)
val view = ListElementBinding.inflate(inflater)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ProductsAdapter.ViewHolder, position: Int) {
val currentProduct = products[position]
holder.binding.rvTv1.text = currentProduct.name
holder.binding.rvTv2.text = currentProduct.price.toString()
holder.binding.rvTv3.text = currentProduct.amount.toString()
holder.binding.rvCb1.isChecked = currentProduct.bought
holder.binding.bted.setOnClickListener {
currentProduct.name = holder.binding.rvTv1.text.toString()
currentProduct.price = holder.binding.rvTv2.text.toString().toDouble()
currentProduct.amount = holder.binding.rvTv3.text.toString().toLong()
currentProduct.bought = holder.binding.rvCb1.isChecked
productViewModel.update(currentProduct)
}
holder.binding.btdel.setOnClickListener {
productViewModel.delete(currentProduct)
products.remove(currentProduct)
notifyDataSetChanged()
}
}
override fun getItemCount(): Int = products.size
inner class ViewHolder(val binding: ListElementBinding) : RecyclerView.ViewHolder(binding.root)
fun setProducts() {
this.products = productViewModel.allProducts
notifyDataSetChanged()
}
fun addProduct(product: Product) {
productViewModel.insert(product)
notifyDataSetChanged()
}
}
And finally activity that Lists it all:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = ActivityListBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.rv1.layoutManager = LinearLayoutManager(baseContext)
binding.rv1.addItemDecoration(DividerItemDecoration(baseContext, DividerItemDecoration.VERTICAL))
val productViewModel = ProductViewModel(this.application)
binding.rv1.adapter = ProductsAdapter(productViewModel)
(binding.rv1.adapter as ProductsAdapter).setProducts()
binding.bt5.setOnClickListener() {
val name = et1.text.toString()
val price = et3.text.toString().toDouble()
val amount = et2.text.toString().toLong()
val bought = false
val product = Product(name, price, amount, bought)
(binding.rv1.adapter as ProductsAdapter).addProduct(product)
et1.text.clear()
et2.text.clear()
et3.text.clear()
}
binding.rv1.adapter = ProductsAdapter(productViewModel)
}
}
I literally have no idea, why it's not showing anything. Maybe You can help me.

Android kotlin: i have retrieved data successfully from url and i want to store those data to room database category wise

i want to store name,price,image And productid, category id
model class
#Entity(tableName = "productlisttable")
data class ProductList_Data(
#PrimaryKey
val uid: Int = 0,
#ColumnInfo(name = "_name")
var name: String? = "",
#ColumnInfo(name = "_price")
var price: String? = ""
)
Dao
#Dao
interface ProductListDao {
#Query("SELECT * FROM productlisttable")
fun getAll(): List<ProductList_Data>
#Insert
fun insert(productListData: ProductList_Data)
}
Appdatabase
#Database(entities = arrayOf(ProductList_Data::class), version = 1)
abstract class ProductlistAppDatabase: RoomDatabase() {
abstract fun productListDao(): ProductListDao
}
here's the productlistactivity
class ProductListActivity : AppCompatActivity() {
private val TAG = ProductListActivity::class.java.simpleName
lateinit var imageView: ImageView
lateinit var iVwishls: ImageView
lateinit var iVCart: ImageView
lateinit var productlistAdapter: ProductlistAdapter
lateinit var viewModelJob: Job
lateinit var coroutineScope: CoroutineScope
lateinit var data: String
lateinit var catId: String
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_product_list)
viewModelJob = Job()
coroutineScope = CoroutineScope(viewModelJob + Dispatchers.Default)
catId = intent.getStringExtra("cat_id").toString()
imageView = findViewById(R.id.imageViewBackFromPluductlist)
iVwishls = findViewById(R.id.imageViewWishls)
iVCart = findViewById(R.id.imageViewCart)
iVwishls.setOnClickListener {
startActivity(
Intent(
applicationContext,
WishlistActivity::class.java
)
)
}
iVCart.setOnClickListener {
startActivity(
Intent(
applicationContext,
CartActivity::class.java
)
)
}
imageView.setOnClickListener { onBackPressed() }
getProductList()
getFromRoom()
}
private fun getFromRoom() {
val db = Room
.databaseBuilder(
applicationContext,
ProductlistAppDatabase::class.java,
"productlistDB"
)
.build()
}
private fun getProductList() {
coroutineScope.launch {
val response =
ServiceApi.retrofitService.getProductList(Rare.getProductList(catId))
if (response.isSuccessful) {
val model = response.body()
productlistAdapter = ProductlistAdapter(this#ProductListActivity, model)
withContext(Dispatchers.Main) {
recyclerviewPlist.layoutManager = LinearLayoutManager(this#ProductListActivity)
recyclerviewPlist.adapter = productlistAdapter
}
} else {
Log.d(TAG, "getProductList: error")
}
}
val db = Room
.databaseBuilder(
applicationContext,
ProductlistAppDatabase::class.java,
"productlistDB"
)
.build()
val data = ProductList_Data(1, "firsrproduct", "100")
db.productListDao().insert(data)
}
}
here's the screenshot of the actual application/as you can see i am able to get data from server like this...
so what i should change or add i tried to define room db and all that bt failed totally

LiveData not updating after inserting into Room database

My project basically allows the user to create a list of products, where different products can be added. So in my case, the relation existing between my entities is many to many: I have a table for all the products that are added when the app is installed, I have a table with the lists the user creates and finally I have a table that records when the user add a product to a list.
The problem I´m getting, is that after a user add a product to a list, the LiveData that is being observed in the activity does not update the list and I cannot figure out why.
The activity (the product code is introduced by the user in another activity started for result):
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_list_of_products)
// Get the listname from the bundle
listName = intent.extras.getString(resources.getString(R.string.INTENT_EXTRA_LISTNAME))
// Set up the ViewModel
viewModel = ViewModelProviders.of(this, ListOfProductsViewModelFactory(application, listName)).get(ListOfProductsViewModel::class.java)
// RecyclerView setup
val recyclerView = findViewById<RecyclerView>(R.id.productRecyclerView)
val mAdapter = ProductAdapter(this)
recyclerView.adapter = mAdapter
recyclerView.layoutManager = LinearLayoutManager(this)
viewModel!!.getProductsInProductList().observe(this, Observer {
products -> mAdapter.setProducts(products!!)
})
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if(requestCode == NEW_PRODUCT_ACTIVITY_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
val code = data!!.extras.getString(resources.getString(R.string.ADD_MANUALLY_ACTIVITY_REPLY))
val resultOfInsertion = viewModel!!.insertProductInProductList(code)
if(resultOfInsertion) {
Toast.makeText(applicationContext, "${code} successful added",
Toast.LENGTH_LONG).show()
} else {
Toast.makeText(applicationContext, "${code} was not added",
Toast.LENGTH_LONG).show()
}
}
else {
Toast.makeText(applicationContext, "Insertion cancelled",
Toast.LENGTH_LONG).show()
}
}
The ViewModel:
private var mRepo = ProductsInProductListRepository(application, listName)
private val productsInProductList = mRepo.getProductsInProductList()
fun getProductsInProductList() : LiveData<List<Product>> {
return productsInProductList
}
fun insertProductInProductList(code: String) : Boolean {
return mRepo.insertProductInProductList(code)
}
The repository:
private var productsInProductListDao : ProductsInProductListDao
private var productsInProductList : LiveData<List<Product>>
private val listName : String
constructor(application : Application, listName: String) {
val db = ProductDatabase.getProductDatabase(application)
this.productsInProductListDao = db!!.productsInProductListDao()
this.listName = listName
this.productsInProductList = productsInProductListDao.getProducstForProductList(listName)
}
fun getProductsInProductList() : LiveData<List<Product>> {
return productsInProductList
}
fun insertProductInProductList(productCode : String) : Boolean {
if(isProductAlreadyAdded(productCode)) {
return false
}
InsertProductInProductListAsync(productsInProductListDao, listName).execute(productCode)
return true
}
private fun isProductAlreadyAdded(productCode : String): Boolean {
return productsInProductListDao.getProductAddedToCertainList(listName, productCode).isNotEmpty()
}
The DAO:
#Dao
interface ProductsInProductListDao {
#Insert(onConflict = OnConflictStrategy.FAIL)
fun insertProductInProductList(productInProductList: ProductsInProductList)
#Query("SELECT code, model, pvpr, qtr, segmentation FROM product_table INNER JOIN products_in_productlist_table ON code=productCode WHERE listName=:listName")
fun getProducstForProductList(listName : String) : LiveData<List<Product>>
#Query("SELECT code, model, pvpr, qtr, segmentation FROM product_table INNER JOIN products_in_productlist_table ON code=productCode WHERE listName=:listName and code=:productCode")
fun getProductAddedToCertainList(listName : String, productCode: String) : List<Product>
}
The Entity:
#Entity(
indices = [Index("productCode")],
tableName = "products_in_productlist_table",
primaryKeys = ["listName", "productCode"],
foreignKeys = [
ForeignKey( onDelete = ForeignKey.CASCADE,
entity = ProductList::class,
parentColumns = ["name"],
childColumns = ["listName"]),
ForeignKey( entity = Product::class,
parentColumns = ["code"],
childColumns = ["productCode"])
]
)
class ProductsInProductList {
#NonNull
#ColumnInfo(name = "listName")
val listName : String
#NonNull
#ColumnInfo(name = "productCode")
val productCode : String
constructor(listName: String, productCode: String) {
this.listName = listName
this.productCode = productCode
}
}
Product adapter:
private val mInflater = LayoutInflater.from(context)
private val context = context
private var mProducts : List<Product>? = null
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProductViewHolder {
val itemView = mInflater.inflate(R.layout.product_item, parent, false)
return ProductViewHolder(itemView)
}
fun setProducts(products : List<Product>) {
this.mProducts = products
}
override fun getItemCount(): Int {
if(mProducts != null)
return mProducts!!.size
return 0
}
override fun onBindViewHolder(holder: ProductViewHolder, position: Int) {
if(mProducts != null) {
val current = mProducts!!.get(position)
holder.setText(current.code)
} else {
holder.setText(context.resources.getString(R.string.lbl_no_list_created))
}
}
fun getProductAtPosition(position: Int) : Product {
return mProducts!!.get(position)
}
ProductViewHolder:
private var productItemView : TextView = itemView.findViewById(R.id.productItemRecyclerView)
fun setText(current: String) {
productItemView.text = current
}
Any idea why when creating a new row in the products_in_productlist_table table, the LiveData is not being updated?
Add the notifyDataSetChange() in your method in your AdapterClass :
fun setProducts(products : List<Product>) {
this.mProducts = products
notifyDataSetChange()
}

Categories

Resources