I am trying to display some data from my real time DB into a recycler adapter with no luck. I have made the FirebaseRecyclerAdapter work on another activity(java) but on this one it just does not work(kotlin). The strange thing is that if I use a ValueEventListener the data return just fine, but the FirebaseRecyclerAdapter do not work.
CLASS:
class FriendsActivity : AppCompatActivity() {
private lateinit var friendsDb: DatabaseReference
private var currentUser: FirebaseUser? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_friends)
supportActionBar?.title = "Friends"
friends_main_rec.layoutManager = LinearLayoutManager(this)
friends_main_rec.setHasFixedSize(true)
currentUser = FirebaseAuth.getInstance().currentUser
friendsDb = FirebaseDatabase.getInstance().reference.child("FRIENDS")
.child(currentUser!!.uid)
val friendsRecyclerViewAdapter = object : FirebaseRecyclerAdapter<Friends, FriendsViewHolder>(
Friends::class.java,
R.layout.friend_single,
FriendsViewHolder::class.java,
friendsDb) {
override fun populateViewHolder(viewHolder: FriendsViewHolder, model: Friends, position: Int) {
Log.d("FriendsList", model.toString())
viewHolder.setDate(model.date)
}
}
friends_main_rec.adapter = friendsRecyclerViewAdapter
}
class FriendsViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun setDate(date: String) {
itemView.friend_single_date.text = date
Log.d("FriendsList", date)
}
}
POJO:
data class Friends(var date: String)
The code seems fine to me, but obviously it is not correct.
There seems to be some problem in this line
friendsDb = FirebaseDatabase.getInstance().reference.child("FRIENDS")
.child(currentUser!!.uid)
Here it will get value from "FRIENDS/currentUser.uid",
which is either of
NBHxxxxxxxxxxxxxxxON2
it3xxxxxxxxxxxxxxxfj1
You can not directly access date object from here, as date is under freind user id
Related
This is my OnCreateActivity(I didn't put any more to avoid confusion)............................................................................................................................
auth= FirebaseAuth.getInstance()
adapters= ImageAdp(ArrayList())
binding.idRLWallpapers.adapter=adapters
getUsers(null)
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
var linearLayoutManager:LinearLayoutManager= recyclerView.layoutManager as LinearLayoutManager
var currentItems=linearLayoutManager.childCount
total_item=linearLayoutManager.itemCount
var lastVisibleitem=linearLayoutManager.findFirstVisibleItemPosition()
if(!isLoadingEDMT&&total_item<=lastVisibleitem+ITEM_COUNT){
// misLoad=true
getUsers(adapters.lastItemId())
isLoadingEDMT=true
binding.bottomPB.visibility=View.GONE
isLoad=false
}
}
})
This is how i am fetching data from firebase database .
private fun getUsers(nodeId:String?) {
if (nodeId==null){
Query = database.orderByKey().limitToFirst(ITEM_COUNT)
}
else{
Query = database.orderByKey().startAfter(nodeId).limitToFirst(ITEM_COUNT)
}
Query.addValueEventListener(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
var arrayLists=ArrayList<imagemodel>()
if (snapshot.hasChildren()) {
for (data in snapshot.children) {
val image = data.child("url2").value.toString()
val name = data.child("voice1").value.toString()
val childname = data.child("childname").value.toString()
val id = data.child("id").value.toString()
val model = imagemodel(image, name,
arrayLists.add(model)
}
//adapters= ImageAdp(arrayList)
//binding.idRLWallpapers.adapter=adapters
adapters.addAll(arrayLists)
This is my RecyclerView Adapter(I didn't put any more to avoid confusion)
fun addAll(emp:List<imagemodel>){
var initialSize= myarraylist.size
myarraylist.addAll(emp)
notifyDataSetChanged()
}
fun lastItemId(): String? {
return myarraylist.get(myarraylist.size-1).uid
}
Thank you for your time
As i understand, you are initializing your adapter in OnCreate and trying to initialize again for every 10 element in down below, and last one replaces the previous one.
Initialize adapter with empty arraylist in OnCreate:
auth= FirebaseAuth.getInstance()
//binding.idRLWallpapers.adapter= ImageAdp(arrayList)
adapters= ImageAdp(ArrayList()) // like this
binding.idRLWallpapers.adapter=adapters
getUsers(null)
Turn your arrayList to local list to become empty for every 10 item.
Query.addValueEventListener(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
var arrayList=ArrayList<imagemodel>() // like this
Delete below 2 lines to prevent recreate:
//adapters= ImageAdp(arrayList) // You did this in OnCreate
//binding.idRLWallpapers.adapter=adapters // remove these 2 lines
//inside Query.addValueEventListener
adapters.addAll(arrayList)
These should work, if not i am gonna need more of your code to understand it properly.
Declare your array list here .Then Add it to adapter
Query.addValueEventListener(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
var arrayList=ArrayList<imagemodel>()
//your codes as it is
if (snapshot.hasChildren()) {
for (data in snapshot.children) {
val image = data.child("url2").value.toString()
val name = data.child("voice1").value.toString()
val childname =
data.child("childname").value.toString()
val id = data.child("id").value.toString()
val model = imagemodel(image, name, childname, id)
arrayList.add(model)
}
}
adapter.addAll(arrayList)
adapter.notyfyDataSetHasChanged()
}
I've been struggling with the problem for a long time and I can't solve it.I'm in EditActivity trying to add a key to the data from the firebase that I get from it with the help of Ad and process it using the AdsManager.
The key should not be equal to zero. In this line I check if the key is zero, then the Firebase writes data to empty.db.child (ad.key?: "Empty"). SetValue (ad). When I load the data to the Firebase, it shows them empty. Without displaying the key. You know what the problem is?
Ad
data class Ad(
var user_id : String? = null ,
var name : String? = null ,
var button1 : String? = null ,
val textTex : String? = null ,
val textk : String? = null ,
val description : String? = null,
val name_ads: String?=null,
val key :String? =null
)
AdsManager
class AdsManager(val readDataColbak : ReadDataColbak?) {
private lateinit var auth: FirebaseAuth
val db =Firebase.database.getReference("main")
fun pubilshAd(ad :Ad) {
db.child(ad.key?: "empty").setValue(ad)
}
fun ReadDataDb() {
db.addListenerForSingleValueEvent(object :ValueEventListener{
override fun onDataChange(snapshot : DataSnapshot) {
val adArray =ArrayList<Ad>()
for (item in snapshot.children){
val ad =item.children.iterator().next().child("ad").getValue(Ad::class.java)
adArray.add(ad !!)
}
readDataColbak?.readData(adArray)
}
override fun onCancelled(error : DatabaseError) {
}
})
}
}
EditActivity1
class EditActivity1: AppCompatActivity(), FfragmentInterfes{
lateinit var mBinder : ActivityEdit1Binding
private var dialog=D()
private var chooseImageFrog:FragmentList? =null
val adsManager = AdsManager(null)
public override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
imageAdapter = ImageAdapter()
mBinder=ActivityEdit1Binding.inflate(layoutInflater)
setContentView(mBinder.root)
init()
}
fun onClickPublish(view : View) {
adsManager.pubilshAd(fillAd())
}
private fun fillAd() : Ad {
var ad : Ad
mBinder.apply {
ad= Ad(
name_ads.text.toString(),
user_id.text.toString(),
name.text.toString(),
button1.text.toString(),
description.text.toString(),
textk.text.toString(),
adsManager.db.push().key
)
}
return ad
}
I'm trying to fetch edittext value from one activity and displaying that text in recycleview and storing using room DB....
Basically the idea is adding the address in activity address when clicks on plus it will redirect to next page where the user gets the address form onsubmit it will fetch address and add to previous activity recycleview.
here is my code for room:
table:---
#Entity(tableName = "address")
class Address {
#PrimaryKey
var id = 0
#ColumnInfo(name = "address")
var address: String? = null
}
Database:-
#Database(entities = [Address::class], version = 1)
abstract class Database : RoomDatabase() {
abstract fun AddressDao(): AddressDao
}
AddressDao:
#Dao
interface AddressDao {
#Insert
suspend fun addData(address: Address)
#Query("select * from address")
fun getAddressesWithChanges() :LiveData<List<Address>>
#Query("SELECT EXISTS (SELECT 1 FROM address WHERE id=:id)")
suspend fun isAddressAdded(id: Int): Int
#Delete
suspend fun delete(address: Address)
}
AddAddressActivity activity:
class AddAddressActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.addaddress)
val editText: EditText = findViewById(R.id.longaddress)
val application = application as CustomApplication
saveaddress.setOnClickListener {
val address = Address()
address.address = editText.getText().toString()
lifecycleScope.launch {
application.addressDao.addData(address)
finish()
}
}
}
}
AddressActivity:-
class AddressActivity : AppCompatActivity() {
private val adapter = AddressAdapter()
private lateinit var data: LiveData<List<Address>>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.address)
addbutton.findViewById<View>(R.id.addbutton).setOnClickListener {
val intent = Intent(this, AddAddressActivity::class.java)
startActivity(intent)
}
val recyclerView = findViewById<RecyclerView>(R.id.recyclerview)
recyclerView.setHasFixedSize(true)
recyclerView.layoutManager = LinearLayoutManager(this,
LinearLayoutManager.VERTICAL, false)
recyclerView.adapter = adapter
val application = application as CustomApplication
data = application.database.AddressDao().getAddressesWithChanges()
data.observe(this, Observer { words1 ->
// Update the cached copy of the words in the adapter.
words1?.let { adapter.updateData(it) }})
}
}
AddressAdapter activity:-
class AddressAdapter: RecyclerView.Adapter<AddressAdapter.ViewHolder>() {
private var addresses: List<Address> = Collections.emptyList()
override fun onCreateViewHolder(viewGroup: ViewGroup, itemViewType: Int):
ViewHolder =
ViewHolder(LayoutInflater.from(viewGroup.context)
.inflate(R.layout.address_item, viewGroup, false) )
override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
val fl: Address = addresses[position]
viewHolder.tv.setText(fl.address)
}
override fun getItemCount(): Int = addresses.size
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var tv: TextView
init {
tv = itemView.findViewById(R.id.ftv_name)
} }
fun updateData(addresses:
List<Address>) {
this.addresses = addresses
notifyDataSetChanged() // TODO: use ListAdapter if animations are needed
}
}
CustomApplication:
class CustomApplication: Application() {
lateinit var database: Database
private set
lateinit var addressDao: AddressDao
private set
override fun onCreate() {
super.onCreate()
this.database = Room.databaseBuilder<Database>(
applicationContext,
Database::class.java, "database"
).build()
}
}
list is not displaying recycleview is empty when came back to address activity
please help ..I'm new to kotlin and room db..
abstract fun AddressDao(): AddressDao?
Why is this nullable?
val favoriteData: List<Table>?
Why is this nullable?
fun addData(favoriteList: Table?)
Why is this nullable?
fun delete(favoriteList: Table?)
Why is this nullable?
Typed nullability is to enable you to represent where a given value can be null, in the sense that it makes sense for it to be absent.
Neither of the above cases represent such a scenario. Room will never return you null instead of an actual dao.
Kotlin's null safety is to allow you to eliminate potential error cases by making it part of the type system, it shouldn't be used to create "false" error cases such as these. If you're trying to add null to a database instead of a real object, you've probably got a bug in your code, and Kotlin should be able to help you eliminate that possibility.
As for your actual question, you're misusing Room.
.allowMainThreadQueries() is a way to disable an error check, but that error is there for a reason. You're not supposed to be reading the data on the UI thread, because with enough data, your app will freeze (ANR).
The code is supposed to look something like this:
#Entity(tableName = "address")
class Address {
#PrimaryKey
var id = 0
#ColumnInfo(name = "address")
var address: String? = null
}
Database:-
#Database(entities = [Address::class], version = 1)
abstract class Database : RoomDatabase() {
abstract fun addressDao(): AddressDao
}
AddressDao:
#Dao
interface AddressDao {
#Insert
suspend fun addData(address: Address)
#Query("select * from address")
fun getAddressesWithChanges(): LiveData<List<Address>>
#Query("SELECT EXISTS (SELECT 1 FROM address WHERE id=:id)")
suspend fun isAddressAdded(id: Int): Int
#Delete
suspend fun delete(address: Address)
}
class CustomApplication: Application() {
lateinit var database: Database
private set
lateinit var addressDao: AddressDao
private set
override fun onCreate() {
super.onCreate()
this.database = Room.databaseBuilder<Database>(
applicationContext,
Database::class.java, "database"
).build()
addressDao = database.addressDao()
}
}
AndroidManifest.xml
<application android:name=".CustomApplication"
...
Address activity:
import androidx.lifecycle.observe
class AddressActivity : AppCompatActivity() {
private val adapter = AddressAdapter()
private lateinit var data: LiveData<List<Address>>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.address_activity)
findViewById<View>(R.id.addButton).setOnClickListener {
val intent = Intent(this, AddAddressActivity::class.java)
startActivity(intent)
}
val recyclerView = findViewById<RecyclerView>(R.id.recyclerview)
recyclerView.setHasFixedSize(true)
recyclerView.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
recyclerView.adapter = adapter
val application = application as CustomApplication
val addressDao = application.addressDao
data = addressDao.getAddressesWithChanges()
data.observe(this) {
adapter.updateData(it)
}
}
}
AddressAdapter:
class AddressAdapter: RecyclerView.Adapter<AddressAdapter.ViewHolder>() {
private var addresses: List<Table> = Collections.emptyList()
override fun onCreateViewHolder(viewGroup: ViewGroup, itemViewType: Int): ViewHolder =
ViewHolder(LayoutInflater.from(viewGroup.context).inflate(R.layout.address_item, viewGroup, false))
override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
val address = addresses[position]
viewHolder.tv.setText(address.address)
}
override fun getItemCount(): Int = addresses.size
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val tv = itemView.findViewById(R.id.ftv_name)
}
fun updateData(addresses: List<Address>) {
this.addresses = addresses
notifyDataSetChanged() // TODO: use ListAdapter if animations are needed
}
}
AddAddress activity:-
class AddAddressActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.addaddress)
val editText: EditText = findViewById(R.id.longaddress)
val application = application as CustomApplication
val addressDao = application.addressDao
saveaddress.setOnClickListener {
val address = Address()
address.address = editText.getText().toString()
lifecycleScope.launch {
addressDao.addData(address)
finish()
}
}
}
}
You can potentially also refer to https://codelabs.developers.google.com/codelabs/android-room-with-a-view-kotlin/#6
Please replace your line with
val rv=findViewById<RecyclerView>(R.id.recyclerview)
You have passed the wrong id addressrecyclerview that's why it was assigning null
with provinceCode database screenshot
This is the database screenshot
this is the json file from firebase
3: https://i.stack.imgur.com/3RTFj.png this is the file
dreference =
FirebaseDatabase.getInstance().reference.child("provinsi").child("0")
if I do like this just got one list only
Source code
class MainActivity : AppCompatActivity() {
lateinit var dreference : DatabaseReference
private var datalist: ArrayList<String> = ArrayList()
private var adapter: ArrayAdapter<String>? = null
private var listener : ValueEventListener?= null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val prov = findViewById<Spinner>(R.id.provinsi)
val listProv: MutableList<String> = ArrayList() // menampung nama provinsi
adapter = ArrayAdapter(this,android.R.layout.simple_list_item_1)
//SETUP DB
dreference = FirebaseDatabase.getInstance().reference.child("provinsi")
dreference?.addValueEventListener(object : ValueEventListener{
override fun onCancelled(p0: DatabaseError) {
}
override fun onDataChange(task: DataSnapshot) {
if(task.exists()){
val provname=task.child("provinceName").value.toString()
listProv.add(provname)
initSpinner(prov,listProv)
}
}
})
}
fun initSpinner(obj : Spinner, arr : MutableList<String>){
var adapter = ArrayAdapter(
this,
android.R.layout.simple_spinner_dropdown_item,
arr
)
obj.adapter = adapter
}
}
I want to get all the province name from Provinsi array
Thanks
class MainActivity : AppCompatActivity() {
var adapter : MyTrackers.ContactAdapter?=null
var listOfContact = ArrayList<UserContact>()
var databaseRef:DatabaseReference?=null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
var userData = UserData(this)
userData.loadPhoneNumber()
databaseRef = FirebaseDatabase.getInstance().reference
//For debug only
//dummyData()
adapter = MyTrackers.ContactAdapter(this, listOfContact)
lvContactList.adapter = adapter
lvContactList.onItemClickListener = AdapterView.OnItemClickListener{
parent, view, position, id ->
val userInfo = listOfContact[position]
UserData.myTrackers.remove(userInfo.phoneNumber)
}
}
override fun onResume() {
super.onResume()
refereshUsers()
}
fun refereshUsers(){
val userData = UserData(this)
if(userData.loadPhoneNumber()=="empty"){ //FirstTIme activity Starts
return
}
databaseRef!!.child("Users").child(userData.loadPhoneNumber())
.child("Finders").addValueEventListener(object : ValueEventListener{
override fun onDataChange(dataSnapshot: DataSnapshot) {
val td = dataSnapshot!!.value as HashMap<String,Any>
listOfContact.clear()
if(td==null){
listOfContact.add(UserContact("NO_USERS","Nothing"))
adapter!!.notifyDataSetChanged()
return
}
for (key in td.keys){
listOfContact.add(UserContact("NO_NAME",key))
}
}
I always get the above java.lang.String cannot be cast to java.util.HashMap in my td declaration in my onDataChange method. Whenever I try to debug based on previous stackoverflow solutions it still doesnt work can someone show me what error I am making and how will be able to make neccessary corrections.
Here is The Structure of my Database
"Users" : {
"7151418" : {
"Finders" : "2018/03/26 20:03:02",
"request" : "2018/03/26 20:03:02"
}
}
}
As the documentation states:
getValue() returns the data contained in this snapshot as native
types. The possible types returned are:
Boolean
String
Long
Double
Map<String, Object>
List<Object>
So, in your case dataSnapshot!!.value returns a String.
To solve this, please change the following line of code:
val td = dataSnapshot!!.value as HashMap<String,Any>
with
val td = dataSnapshot!!.value as String
The value of Finders property is actually a String and not HashMap.