How can i delete something from cloud firestore database? - android

i'm trying to delete a document in my firestore database
i'm using a listview to list some things of my data base, the items of this listview have a delete button, what i want is: when the user presses the delete button, this thing gets deleted from the list and from the firestore, there what i'm trying:
this is my entire activity to do this:
class RigBuilderActivity : AppCompatActivity() {
lateinit var botaoAddPc: FloatingActionButton
lateinit var pcName:EditText
lateinit var infoButton:FloatingActionButton
lateinit var pcListView: ListView
companion object{
const val TAG = "RigBuilderActivity"
}
var pc = arrayListOf<PC>()
val pcAdapter = PcAdapter()
val db = Firebase.firestore
val userId = FirebaseAuth.getInstance().currentUser!!.uid
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_rig_builder)
botaoAddPc = findViewById(R.id.rig_builder_button_add_pc)
pcName = findViewById(R.id.rig_builder_text_input)
infoButton = findViewById(R.id.rig_builder_button_info)
pcListView = findViewById(R.id.rig_builder_pc_list)
botaoAddPc.setOnClickListener{
var pc_text :String = pcName.text.toString()
val computer = PC(UUID.randomUUID().toString(),pc_text)
db.collection("users").document(userId).collection("PC").add(computer.toHashmapPC()).addOnSuccessListener { task->
Log.d(TAG, "DocumentSnapshot added with ID: ${task.id}")
Toast.makeText(this,"Pc added",Toast.LENGTH_SHORT).show()
}.addOnFailureListener{ e->
Log.w(TAG,"Error Adding PC",e)
Toast.makeText(this,"Failed",Toast.LENGTH_SHORT).show()
}
}
pcListView.adapter = pcAdapter
db.collection("users").document(userId).collection("PC").addSnapshotListener{ value, e->
if (e!=null){
Log.w(TAG,"Listen failed.",e)
return#addSnapshotListener
}
pc.clear()
for (doc in value!!){
val pc = PC.fromQueryDoc(doc)
this.pc.add(pc)
}
pcAdapter.notifyDataSetChanged()
}
}
fun getPcName():String{
return pcName.toString()
}
inner class PcAdapter : BaseAdapter() {
override fun getCount(): Int {
return pc.size
}
override fun getItem(p0: Int): Any {
return pc[p0]
}
override fun getItemId(p0: Int): Long {
return 0
}
override fun getView(p0: Int, p1: View?, p2: ViewGroup?): View {
val rootView = layoutInflater.inflate(R.layout.pc_item_layout, p2,false )
val textViewPcName = rootView.findViewById<TextView>(R.id.pc_name)
val editButton = rootView.findViewById<ImageButton>(R.id.pc_edit_button)
val deleteButton = rootView.findViewById<FloatingActionButton>(R.id.pc_delete_button)
textViewPcName.text = pc[p0].counter.toString()
deleteButton.setOnClickListener{
val ref : DocumentReference = db.collection("users").document(userId).collection("PC").document(pc[p0].getPcId())
ref.delete().addOnSuccessListener {
Log.d(TAG,"Pc deleted with success")
Toast.makeText(this#RigBuilderActivity,"Deleted with success",Toast.LENGTH_SHORT).show()
}
pcAdapter.notifyDataSetChanged()
}
editButton.setOnClickListener{
}
textViewPcName.text = pc[p0].name
return rootView
}
}
}
in case of needing, this is my PC class, i'm just using one of the constructors to test the list and make the delete works:
class PC {
var id:String
var name : String? = null
var counter : Long? = null
lateinit var cpu :CPU
lateinit var gpu: GPU
lateinit var motherBoard: MotherBoard
/**
* Construtor de teste
*/
constructor(id:String, name:String?){
this.id = id
this.name = name
}
/**
* Construtor ainda a implementar
*/
constructor(id:String, name:String?, cpu: CPU,gpu: GPU,motherBoard: MotherBoard){
this.id = id
this.name = name
this.cpu = cpu
this.gpu = gpu
this.motherBoard = motherBoard
}
fun toHashmapPC() : HashMap <String, Any?>{
return hashMapOf(
"id" to id,
"name" to name
)
}
fun getPcId():String{
return id
}
companion object{
fun fromQueryDoc(documentSnapshot: DocumentSnapshot):PC{
return PC(
documentSnapshot["id"] as String,
documentSnapshot["name"] as String
)
}
}
}

Related

RecyclerView is not updated when an update occurs in Room

I have a RecyclerView where an item can be edited via a DialogFragment, so when an item is clicked a Dialog is shown, then I can change some properties of that item, the issue is that RecyclerView is not updated with the updated properties and I have to force a notifyItemChanged when the Dialog is closed.
When an item in RecyclerView is clicked I set a MutableLiveData in my ViewModel so then it can be manipulated in the Dialog.
My ViewModel looks like this:
#HiltViewModel
class DocumentProductsViewModel #Inject constructor(private val repository: DocumentProductsRepository) :
ViewModel() {
val barcode = MutableLiveData<String>()
private val _selectedProduct = MutableLiveData<DocumentProduct>()
val selectedProduct: LiveData<DocumentProduct> = _selectedProduct
private val _selectedDocumentId = MutableLiveData<Long>()
val selectedDocumentId: LiveData<Long> = _selectedDocumentId
val products: LiveData<List<DocumentProduct>> = _selectedDocumentId.switchMap { documentId ->
repository.getDocumentProducts(documentId).asLiveData()
}
fun insert(documentProduct: DocumentProduct) = viewModelScope.launch {
repository.insert(documentProduct)
}
fun setProductQuantity(quantity: Float) {
_selectedProduct.value = _selectedProduct.value.also {
it?.timestamp = System.currentTimeMillis()
it?.quantity = quantity
}
update()
}
fun start(documentId: Long?) = viewModelScope.launch{
if (documentId == null) {
_selectedDocumentId.value = repository.getHeaderByType("Etichette")?.id
}
documentId?.let { documentId ->
_selectedDocumentId.value = documentId
}
}
fun select(product: DocumentProduct) {
_selectedProduct.value = product
}
fun delete() = viewModelScope.launch {
_selectedProduct.value?.let { repository.delete(it) }
}
private fun update() = viewModelScope.launch {
_selectedProduct.value?.let { repository.update(it) }
}
}
And in my fragment I'm subscribed to products as this:
private fun initRecyclerView() {
binding.rvProducts.adapter = adapter
viewModel.products.observe(viewLifecycleOwner) { products ->
val productsCount = products.count()
binding.tvProductsCount.text =
resources.getQuantityString(R.plurals.articoli, productsCount, productsCount)
// TODO: create amount string and set it with resources
binding.tvProductsAmount.text = productsCount.toEuro()
adapter.submitList(products)
binding.rvProducts.smoothScrollToPosition(adapter.itemCount - 1)
}
initSwipe(adapter)
}
When setProductQuantity is called the RecyclerView remains unchanged until notify is called while delete works fine without the necessity of calling any notify on RecyclerView.
UPDATE:
The item position is actually changed in RecyclerView as it's sorted by it's last changed timestamp BUT not the quantity field.
Here is my Adapter:
class DocumentProductsListAdapter : ListAdapter<DocumentProduct, DocumentProductsListAdapter.ViewHolder>(ProductDiffCallback) {
override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): ViewHolder {
val view: View = LayoutInflater.from(viewGroup.context)
.inflate(R.layout.layout_item, viewGroup, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val product = getItem(position)
holder.bind(product)
}
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val barcode: TextView = itemView.findViewById(R.id.barcode)
val quantity: TextView = itemView.findViewById(R.id.quantity)
val description: TextView = itemView.findViewById(R.id.description)
val unitOfMeasure: TextView = itemView.findViewById(R.id.unitOfMeasure)
fun bind(product: DocumentProduct) {
barcode.text = product.barcode
quantity.text = product.quantity.formatForQta().replace(".", ",")
if (product.labelType != null && product.labelType != "") {
unitOfMeasure.text = product.labelType
} else {
unitOfMeasure.text = product.unitOfMeasure?.lowercase(Locale.ITALIAN)
}
description.text = product.description ?: "-"
}
}
}
object ProductDiffCallback : DiffUtil.ItemCallback<DocumentProduct>() {
override fun areItemsTheSame(oldItem: DocumentProduct, newItem: DocumentProduct): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(oldItem: DocumentProduct, newItem: DocumentProduct): Boolean {
return oldItem == newItem
}
}
data class DocumentProduct(
#PrimaryKey(autoGenerate = true)
var id: Long,
var barcode: String,
#Json(name = "desc")
var description: String?,
#ColumnInfo(defaultValue = "PZ")
#Json(name = "um")
var unitOfMeasure: String?,
#Json(name = "qta")
var quantity: Float,
#Json(name = "id_testata")
var documentId: Long,
#Json(name = "tipo_frontalino")
var labelType: String?,
var timestamp: Long?
) {
constructor(barcode: String, documentId: Long, labelType: String?) : this(
0,
barcode,
null,
"PZ",
1f,
documentId,
labelType,
null
)
override fun equals(other: Any?): Boolean {
return super.equals(other)
}
override fun hashCode(): Int {
return super.hashCode()
}
}
You have the implementations of areContentsTheSame() and areItemsTheSame() swapped.
areContentsTheSame() is asking if everything in the two items being compared is the same. Therefore, if the class has a proper equals()/hashcode() for all properties used by the ViewHolder, you can use oldItem == newItem. If you use a data class with all relevant properties in the primary constructor, then you don't need to manually override equals()/hashcode().
areItemsTheSame() is asking if the two items represent the same conceptual row item, with possible differences in their details. So it should be oldItem.id == newItem.id.
The problem with your data class is that you are overriding equals()/hashcode() without providing any implementation at all. This is effectively disabling the proper implementations that are provided by the data modifier by calling through to the super implementation in the Any class. You should not override them at all when you use data class.

Retrieve data from Room using Column Value - Room

I have two tables in my Room DB - Events and Notes. For each event I have displayed in the RecycleView - I have a link to launch a note for that event. On first click - Note is created. On the second time the note is clicked, I would like to retrieve the previous note and then edit. Also, I am using the same activity to already edit/create new notes by passing on appropriate values, which works but uses parcelized note.
For editing an existing event Note - I am sending across the event ID (which is also stored in the Note table - not as a Foreign key) using the putExtra method. DB structure below (assocId refers to eventId)
ViewModel
fun setNotesByAssocEventId(assocEventId: String): Note {
return dao.getByAssocEventId(assocEventId)
}
DAO
#Query("SELECT * FROM notes WHERE assocEventId = :assocEventId")
fun getByAssocEventId(assocEventId: String): Note
NoteEntity
#Entity(tableName = "notes")
#Parcelize
data class Note(
//PrimaryKey annotation to declare primary key with auto increment value
//ColumnInfo annotation to specify the column's name
#PrimaryKey(autoGenerate = true) #ColumnInfo(name = "id") var id: Int = 0,
#ColumnInfo(name = "assocEventId") var assocEventId: String = "",
#ColumnInfo(name = "title") var title: String = "",
#ColumnInfo(name = "label") var label: String = "",
#ColumnInfo(name = "date") var date: String = "",
#ColumnInfo(name = "time") var time: String = "",
#ColumnInfo(name = "updatedDate") var updatedDate: String = "",
#ColumnInfo(name = "updatedTime") var updatedTime: String = "",
#ColumnInfo(name = "body") var body: String = ""
) : Parcelable
I am using the below code to edit/create new notes. While I am able to create/Edit notes. I am unable to retrieve a node for a particular event using the eventId. One of the errors I am getting is Note object has not been initialized when I am assigning the note object returned from the ViewModel. What could be the issue?
assocID is the event ID obtained using putExtra and the corresponding event note is to be retrieved...
private lateinit var binding: ActivityEditNoteBinding
private lateinit var notesViewModel: NotesViewModel
private lateinit var note: Note
private var assocId: String? = ""
private var isUpdate = false
private val dateChange = DateChange()
var refUsers: DatabaseReference? = null
var firebaseUser: FirebaseUser? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityEditNoteBinding.inflate(layoutInflater)
setContentView(binding.root)
assocId = intent.getStringExtra("eventId").toString()
initView()
initListener()
}
private fun initView() {
firebaseUser = FirebaseAuth.getInstance().currentUser
initViewModel()
if (assocId != null) {
findViewById<TextView>(R.id.editNote).text = "Edit Event Note"
Toast.makeText(this, "EvetnId received", Toast.LENGTH_SHORT).show()
isUpdate = true
binding.editNoteDelete.visibility = View.VISIBLE
notesViewModel.getNotes()
note = notesViewModel.setNotesByAssocEventId("%${assocId}%")
binding.editTextTitle.setText(note.title)
binding.editTextBody.setText(note.body)
binding.editTextTitle.setSelection(note.title.length)
//set spinner position
val compareValue = note.label
val adapter = ArrayAdapter.createFromResource(
this, R.array.NoteSpinnerVals,
android.R.layout.simple_spinner_item
)
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
binding.spLabel.adapter = adapter
val spinnerPosition = adapter.getPosition(compareValue)
binding.spLabel.setSelection(spinnerPosition)
}
}
private fun initViewModel() {
notesViewModel = ViewModelProvider(this).get(NotesViewModel::class.java)
}
private fun initListener() {
// binding.editNoteBack.setOnClickListener(this)
binding.editNoteSave.setOnClickListener(this)
binding.editNoteDelete.setOnClickListener(this)
}
private fun deleteNote(note: Note) {
notesViewModel.deleteNote(note)
Toast.makeText(this#EditNote, "Note removed", Toast.LENGTH_SHORT).show()
}
private fun showDialog() {
AwesomeDialog.build(this)
.position(AwesomeDialog.POSITIONS.CENTER)
.title("Delete the note?")
.icon(R.drawable.ic_delete_black)
.background(R.drawable.background_dialog)
.onPositive(
"Yes, delete",
buttonBackgroundColor = R.drawable.button_bg,
textColor = ContextCompat.getColor(this, R.color.white)
) {
deleteNote(note)
val intent = Intent(this, MainActivity::class.java)
startActivity(intent)
finish()
}
.onNegative(
"Cancel",
buttonBackgroundColor = R.drawable.button_bg,
textColor = ContextCompat.getColor(this, R.color.white)
) {
}
}
Code of the ViewModel
class NotesViewModel(application: Application) : AndroidViewModel(application) {
private val context = getApplication<Application>().applicationContext
private val listNotes = MutableLiveData<ArrayList<Note>>()
private var dao: NoteDao
init {
val database = AppDatabase.getDatabase(context)
dao = database.getNoteDao()
}
fun setNotes() {
val listItems = arrayListOf<Note>()
listItems.addAll(dao.getAll())
listNotes.postValue(listItems)
}
fun setNotesByType(label: String) {
val listItems = arrayListOf<Note>()
listItems.addAll(dao.getByLabel(label))
listNotes.postValue(listItems)
}
fun setNotesByTitle(title: String) {
val listItems = arrayListOf<Note>()
listItems.addAll(dao.getByTitle(title))
listNotes.postValue(listItems)
}
fun setNotesByAssocEventId(assocEventId: String): Note {
return dao.getByAssocEventId(assocEventId)
}
fun insertNote(note: Note) {
dao.insert(note)
}
fun updateNote(note: Note) {
dao.update(note)
}
fun deleteNote(note: Note) {
dao.delete(note)
}
fun getNotes(): LiveData<ArrayList<Note>> {
return listNotes
}
}
The method in the DAO need to be changed a little
#Query("SELECT * FROM notes WHERE assocEventId = :assocEventId")
fun getByAssocEventId(assocEventId: String): Note
should be
#Query("SELECT * FROM notes WHERE assocEventId LIKE :assocEventId")
fun getByAssocEventId(assocEventId: String): LiveData<List<Note>>
In order to support wild character search, "%${assocId}%", LIKE keyword.
To get one Note only
#Query("SELECT * FROM notes WHERE assocEventId LIKE :assocEventId LIMIT 1")
fun getByAssocEventId(assocEventId: String): LiveData<Note>
in view model
fun setNotesByAssocEventId(assocEventId: String): LiveData<Note>{
return dao.getByAssocEventId(assocEventId)
}
in the activity
notesViewModel.setNotesByAssocEventId("%${assocId}%").observe(this, {
if(it!=null){
//if you using for single note only
}
//if(it.isNotEmpty()){
//if you using for list
//}
})

RecyclerView make endless scrolling with JSON

I'm trying to make my Android App (I'm only experienced in iOS).
I created a RecyclerView that gets the data from a web. I tried everything to implement endless scrolling to load more items, but when I call the function to get the items, the entire RecyclerView loads again and no attach the new results on the bottom.
This is my code:
ConversationUser.kt
data class ConversationUser(
val message_nickname: String,
val message_image_thumb: String,
val message_large_thumb: String,
val message_modified: String,
val message_status: String,
val message_unread: Int,
val conv_id: String,
val message_dest: String) {
}
ConversacionesActivity.kt
class ConversacionesActivity : AppCompatActivity() {
// MARK: Variables
var user_token = ""
var user_id = ""
override fun onCreate(savedInstanceState: Bundle?) {
// User Defaults
val sharedPreferences = getSharedPreferences("Preferences", Context.MODE_PRIVATE)
user_token = sharedPreferences.getString("user_token", "")!!
user_id = sharedPreferences.getString("user_id", "")!!
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_conversaciones)
recyclerConv.addItemDecoration(DividerItemDecoration(this, LinearLayoutManager.VERTICAL))
getConversationsData()
recyclerConv.setLoadingListener(object : LoadingListener {
override fun onRefresh() {
//refresh data here
}
override fun onLoadMore() {
// load more data here
getConversationsData()
}
})
}
fun getConversationsData() {
val httpAsync = "https://mywebsite.com/conversations/${user_token}"
.httpPost()
.responseString { request, response, result ->
when (result) {
is Result.Failure -> {
val ex = result.getException()
println(ex)
}
is Result.Success -> {
val data = result.get()
runOnUiThread {
val conversaciones = processJson(data)
show(conversaciones)
return#runOnUiThread
}
}
}
}
httpAsync.join()
}
fun processJson(json: String): List<ConversationUser> {
val gson: Gson = GsonBuilder().create()
val conversaciones: List<ConversationUser> = gson.fromJson(
json,
Array<ConversationUser>::class.java
).toList()
return conversaciones
}
fun show(conversaciones: List<ConversationUser>) {
recyclerConv.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
recyclerConv.adapter = AdaptadorConv(conversaciones, this, user_token, user_id)
}
AdaptadorConv.kt
class AdaptadorConv(
val conversaciones: List<ConversationUser> = ArrayList(),
val context: Context,
val user_token: String,
val user_id: String) : RecyclerView.Adapter<AdaptadorConv.ConvViewHolder>() {
override fun onBindViewHolder(holder: ConvViewHolder, position: Int) {
holder.convName.text = conversaciones[position].message_nickname
holder.convTime.text = conversaciones[position].message_modified
}
override fun getItemCount(): Int {
return conversaciones.size - 1
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ConvViewHolder {
val view: View = LayoutInflater.from(parent.context).inflate(
R.layout.conversaciones,
parent,
false
)
return ConvViewHolder(view)
}
class ConvViewHolder(vista: View): RecyclerView.ViewHolder(vista) {
val convImg: ImageView = itemView.findViewById(R.id.convImg)
val convStatus: ImageView = itemView.findViewById(R.id.convStatus)
val convName: TextView = itemView.findViewById(R.id.convName)
val convUnread: TextView = itemView.findViewById(R.id.convUnread)
val convTime: TextView = itemView.findViewById(R.id.convTime)
}
Thanks for any help or hint.
Please check your show () method, you are creating new Adapter every time with the new dataset. You have to append the new items to the adapter's list and adapter should be set to list once. Helpful tutorial can be found at here.

How to show query to database in ListView in kotlin with android studio?

I am learning to develop in kotlin with android studio, so I don't have any experience.
I am wanting to insert data into a local database using room database, so far I think I'm doing fine. Now I need to be able to consult those data but I cannot do it, I have searched the internet but I have not been able to solve my problem.
I attach the code.
Class #Entity
class TablasBdApp {
#Entity(tableName = TblConteo.TABLE_NAME)
data class TblConteo(
#PrimaryKey(autoGenerate = true) #ColumnInfo(name = "linea_id") val Linea_Id: Int = 0,
#ColumnInfo (name = "articulo") val Articulo : String?
)
{
companion object {
const val TABLE_NAME = "TablaConteo"
}
}
}
Class #Dao
#Dao
public interface ItblConteoDao {
#Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertArticulo(taskTblConteo: TablasBdApp.TblConteo);
#Query("SELECT * FROM " + TablasBdApp.TblConteo.TABLE_NAME + " ORDER BY Linea_Id desc")
fun getConteoArticulos(): LiveData<List<TablasBdApp.TblConteo>>
}
Class #DataBase
class BaseDeDatos {
#Database(entities = [TablasBdApp.TblConteo::class], version = 1)
abstract class PortatilDataBase : RoomDatabase() {
abstract fun itblconteoDao () : ItblConteoDao
companion object {
private const val DATABASE_NAME = "portatildb"
#Volatile
private var INSTANCE: PortatilDataBase? = null
fun getInstance(context: Context): PortatilDataBase? {
INSTANCE ?: synchronized(this) {
INSTANCE = Room.databaseBuilder(
context.applicationContext,
PortatilDataBase::class.java,
DATABASE_NAME
).build()
}
return INSTANCE
}
}
}
}
Class #Repository
class ConteoRepository(application: Application) {
private val itblConteoDao: ItblConteoDao? = BaseDeDatos.PortatilDataBase.getInstance(application)?.itblconteoDao()
fun insert (tblconteo: TablasBdApp.TblConteo){
if(itblConteoDao != null) InsertAsyncTask(itblConteoDao).execute(tblconteo)
}
fun getConteo(): LiveData<List<TablasBdApp.TblConteo>> {
return itblConteoDao?.getConteoArticulos() ?: MutableLiveData<List<TablasBdApp.TblConteo>>()
}
private class InsertAsyncTask(private val itblConteoDao: ItblConteoDao) :
AsyncTask<TablasBdApp.TblConteo, Void, Void>() {
override fun doInBackground(vararg tblconteos: TablasBdApp.TblConteo?): Void? {
for (tblconteo in tblconteos) {
if (tblconteo != null) itblConteoDao.insertArticulo(tblconteo)
}
return null
}
}
}
Class #CustomAdapter
class CustomAdapter(context: Context): BaseAdapter() {
private val mContext: Context
init{
mContext = context
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
//val repository = ConteoRepository(application = Application())
var textView = TextView(mContext)
val observer = Observer<List<TablasBdApp.TblConteo>> { conteos ->
if (conteos != null) {
var text = ""
for (conteo in conteos) {
text += conteo.Linea_Id.toString() + " " + conteo.Articulo
}
textView.text = text
}
}
//repository.getConteo().observe(this, observer)
return textView
}
override fun getItem(position: Int): Any {
return "Test Articulo"
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
override fun getCount(): Int {
TODO("Not yet implemented")
}
}
Class #Fragment
class CapturaConteoFragment() : Fragment() {
private lateinit var capturaConteoViewModel: CapturaConteoViewModel
#SuppressLint("ResourceType")
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
capturaConteoViewModel =
ViewModelProviders.of(this).get(CapturaConteoViewModel::class.java)
val root = inflater.inflate(R.layout.fragment_capturaconteo, container, false)
//val textView: TextView = root.findViewById(R.id.text_capturaconteo)
capturaConteoViewModel.text.observe(viewLifecycleOwner, Observer {
//textView.text = it
val botonGuardar: Button = root.findViewById(R.id.btn_guardar)
val textoArticulo : EditText = root.findViewById(R.id.edit_art_upc)
var listview: ListView = root.findViewById(R.id.list_conteo)
botonGuardar.setOnClickListener {
if(textoArticulo.getText().toString().trim().isEmpty()){
Toast.makeText(activity, "Captura un articulo", Toast.LENGTH_LONG).show()
textoArticulo.requestFocus()
}
else{
saveConteo(TablasBdApp.TblConteo(Articulo = textoArticulo.text.trim().toString()))
Toast.makeText(activity, "Articulo guardado", Toast.LENGTH_LONG).show()
//var listaconteo = arrayOf(muestraConteo())
var prodAdapter = CustomAdapter(**this**) **<- This is where it marks error.**
listview?.adapter = prodAdapter
}
}
})
return root
}
private fun saveConteo(tblConteo: TablasBdApp.TblConteo) {
val repository = ConteoRepository(application = Application())
repository.insert(tblConteo)
val conteo = repository.getConteo()
}
private fun showConteo (){
val repository = ConteoRepository(application = Application())
repository.getConteo()
}
}
Thanks for your help.
Regards.
In your DAO you are returning LiveData that means you need to observe it and best practice would be through ViewModel which implies you should MVVM architecture, there are plenty of tutorials and courses on it.
Here is something from google Codelabs
Other way would would be to return just list rather than live data of a list. This is bad practice because you will have to refresh it all the time and do a lot of extra work.
PS your adapter needs fixing too my suggestion is follow codelabs or watch complete tutorial on Room + MVVM.
Hope this helps

Could not complete scheduled request to refresh entries. ClientErrorCode: 3 Android Kotlin

Let me get straight to the point here the error in the logcat is:
Could not complete scheduled request to refresh entries. ClientErrorCode: 3
I have tested the Realm() part of the code and it fetched the right data. Basically, the app just crashes when it loads that Activity. All Im trying to do right now is post the itemName in each cell. If you guys need the logcat, just say so and I'll post it. Any other details needed too.
This is the code for my Activity with a recyclerView with just an ImageView and a TextView in each cell.:
class EssentialsActivity : AppCompatActivity() {
var category: String? = null
val realmtypeFunctions = RealmTypeFunctions()
var realmResults: RealmResults<ChattRItem>? = null
var chattRItemList = mutableListOf<ChattRItem>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_essentials)
//init realm
Realm.init(this)
category = "People"
recyclerView_Essentials.setBackgroundColor(Color.CYAN)
recyclerView_Essentials.layoutManager = GridLayoutManager(this, 3)
// AsyncTask.execute {
category?.let {
loadFromRealm(it)
}
// }
this.runOnUiThread {
recyclerView_Essentials.adapter = EssentialsAdapter(chattRItemList)
}
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
val inflater = menuInflater
inflater.inflate(R.menu.categories, menu )
return super.onCreateOptionsMenu(menu)
}
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
val intent: Intent?
intent = Intent(this, AddItemActivity::class.java)
intent.putExtra("category", category)
startActivity(intent)
// when (item?.itemId) {
// R.id.essentials_menu_item -> {
// intent = Intent(this, EssentialsActivity::class.java)
// startActivity(intent)
// }
// R.id.addItem_menu_item -> {
// intent = Intent(this, AddItemActivity::class.java)
// startActivity(intent)
// }
// else -> return false
// }
return super.onOptionsItemSelected(item)
}
private fun loadFromRealm(category: String){
val realm = Realm.getDefaultInstance()
try {
val query: RealmQuery<ChattRItem>? = realm.where(ChattRItem::class.java).equalTo("itemCategory", category)
val result: RealmResults<ChattRItem>? = query?.findAll()
result?.let {
for (i in it) {
println(i.itemName)
chattRItemList.add(i)
}
println(chattRItemList.count())
}
} finally {
realm.close()
}
}
}
class EssentialsAdapter(private val chattRItemList: List<ChattRItem>): RecyclerView.Adapter<CustomViewHolder>(){
//realm class variable here to be displayed
/* var essentials = array of realm essential item */
// var essentialsActivity = EssentialsActivity()
//number of items
override fun getItemCount(): Int {
// return 12 //return realm items count
return this.chattRItemList.size
}
override fun onBindViewHolder(holder: CustomViewHolder, position: Int) {
// holder.itemView.textView_essentials_name.text = "Essentials Item"
val chattRItem = chattRItemList.get(position)
// holder.itemView.textView_essentials_name.text = chattRItem.itemName
holder.bind(chattRItem)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CustomViewHolder{
// how do we create a cell view
val layoutInflater = LayoutInflater.from(parent.context)
val cellForRow = layoutInflater.inflate(R.layout.essentials_cells_layout, parent, false)
return CustomViewHolder(view = cellForRow)
}
}
class CustomViewHolder(view: View): RecyclerView.ViewHolder(view) {
fun bind(chattRitem: ChattRItem) {
itemView.textView_essentials_name.text = chattRitem.itemName
}
}
So basically I figured it out. This was not the right error from LogCat. There was another set of errors from Logcat many lines above this. The error was the result list was a #Realm object. My recyclerView was asking for a non RealmClass object. So i had to make a similar object except not a RealmClass.
#RealmClass
open class ChattRItem: RealmModel {
#PrimaryKey var itemId: String = ""
var itemName: String = ""
var itemCategory: String = ""
var itemImageFileName: String = ""
var itemAudioFileName: String = ""
}
class ChattRBoxItems(val itemId: String, val itemName: String, val itemCategory: String, val itemImageFileName: String, val itemAudioFileName: String)
then I mapped the result into this new class then applied it to my recyclerView.

Categories

Resources