Somehow I see in the app messages I sent, but can't see those which should be received from others. Also when I'm sending a message it's sent to all users. Here I'm sending two classes, adapter and main chat activity. I tried using inner classes, different types of getItemViewType functions but nothing works.
MessageAdapter
class MessageAdapter(val context: Context, val messageList: ArrayList<Message>):
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
val ITEM_RECIEVE = 1
val ITEM_SENT = 2
class SentViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
{
val sentMessage = itemView.findViewById<TextView>(R.id.txt_sent_message)
}
class RecieveViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
{
val recieveMessage = itemView.findViewById<TextView>(R.id.txt_recieve_message)
}
override fun getItemViewType(position: Int): Int {
val currentMessage = messageList[position]
if (FirebaseAuth.getInstance().currentUser?.uid.equals(currentMessage.senderId)) {
return ITEM_SENT
}
else {
return ITEM_RECIEVE
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
if (viewType == 1)
{
val view = LayoutInflater.from(context).inflate(R.layout.recieve, parent, false)
Log.d("tag2", "testrecieveviewholderview11")
return RecieveViewHolder(view)
}
else
{
val view = LayoutInflater.from(context).inflate(R.layout.sent, parent, false)
Log.d("tag", "testsentviewholderview22")
return SentViewHolder(view)
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val currentMessage = messageList[position]
if(holder.javaClass == SentViewHolder::class.java)
{
val viewHolder = holder as SentViewHolder
holder.sentMessage.text = currentMessage.message
}
else
{
val viewHolder = holder as RecieveViewHolder
holder.recieveMessage.text = currentMessage.message
}
}
override fun getItemCount(): Int {
return messageList.size
}
}
And ChatActivity
var firebaseUser: FirebaseUser? = null
private lateinit var messageRecyclerView: RecyclerView
private lateinit var messageBox: EditText
private lateinit var sendButton: ImageButton
private lateinit var messageAdapter: MessageAdapter
private lateinit var messageList: ArrayList<Message>
private lateinit var mRef: DatabaseReference
var recieverRoom: String? = null
var senderRoom: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_chat)
val intent = Intent()
val name = intent.getStringExtra("name")
val recieverUid = intent.getStringExtra("uid")
val senderUid = FirebaseAuth.getInstance().currentUser?.uid
mRef = FirebaseDatabase.getInstance().reference
senderRoom = recieverUid + senderUid
recieverRoom = senderUid + recieverUid
messageRecyclerView = findViewById(R.id.RecyclerViewChat)
messageBox = findViewById(R.id.messageBox)
sendButton = findViewById(R.id.sendButton)
messageList = ArrayList()
messageAdapter = MessageAdapter(this, messageList)
messageRecyclerView.layoutManager = LinearLayoutManager(this)
messageRecyclerView.scrollToPosition(messageAdapter.itemCount-1)
messageRecyclerView.adapter = messageAdapter
mRef.child("chats").child(senderRoom!!).child("messages")
.addValueEventListener(object : ValueEventListener{
override fun onDataChange(snapshot: DataSnapshot) {
messageList.clear()
for (postSnapshot in snapshot.children)
{
val message = postSnapshot.getValue(Message::class.java)
messageList.add(message!!)
}
messageAdapter.notifyDataSetChanged()
}
override fun onCancelled(error: DatabaseError) {
}
})
sendButton.setOnClickListener {
if (messageBox.text.toString().isEmpty() || messageBox.text.toString().isBlank())
{
messageBox.setText("")
}
else {
val message = messageBox.text.toString()
val messageObject = Message(message, senderUid)
mRef.child("chats").child(senderRoom!!).child("messages").push()
.setValue(messageObject).addOnSuccessListener {
mRef.child("chats").child(recieverRoom!!).child("messages").push()
.setValue(messageObject)
}
messageBox.setText("")
}
}
}
}
The error coming in this code is "Unresolved reference: message" and "Unresolved reference: senderId" in MessageAdapter. MessageAdapter is not able to take variables that are declared in Message class(message and senderId).
Related
When I use my Original Device where I'll upload Text and Images to the Firebase
and When I View it I can See the Images, but when I use Different Device I can see the Text but not the uploaded Image instead I can seethe Iclauncher, but the Image is still on Realtime Database as well as on Storage. I think my problem is if I use another device the Images from Firebase is not Loading or Downloading and I don't know what to do
This Is My Code
DetailsActivity.kt
class DetailsActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_details)
val intss = intent
var nameT = intss.getStringExtra("NAMET")
var locaT = intss.getStringExtra("LOCAT")
var imgT = intss.getStringExtra("IMGURI")
var desT = intss.getStringExtra("DEST")
var serT = intss.getStringExtra("SERT")
var acoT = intss.getStringExtra("ACOT")
var conT = intss.getStringExtra("CONT")
nameDetailTextView.text = nameT
locationDetailTextView.text = locaT
descriptionDetailTextView.text = desT
servicesDetailTextView.text = serT
accommodationDetailTextView.text = acoT
contactDetailTextView.text = conT
hotelDetailImageView.loadImage(imgT)
}
}
ItemsActivity.kt
class ItemsActivity : AppCompatActivity() {
private var mStorage:FirebaseStorage? = null
private var mDatabaseRef:DatabaseReference? = null
private var mDBListener:ValueEventListener? = null
private lateinit var mHotels:MutableList<HotelandInns>
private lateinit var listAdapter: ListAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_items)
/**set adapter*/
mRecyclerView.setHasFixedSize(true)
mRecyclerView.layoutManager = LinearLayoutManager(this#ItemsActivity)
myDataLoaderProgressBar.visibility = View.VISIBLE
mHotels = ArrayList()
listAdapter = ListAdapter(this#ItemsActivity,mHotels)
mRecyclerView.adapter = listAdapter
/**set Firebase Database*/
mStorage = FirebaseStorage.getInstance()
mDatabaseRef = FirebaseDatabase.getInstance().getReference("hotels_uploads")
mDBListener = mDatabaseRef!!.addValueEventListener(object : ValueEventListener{
override fun onCancelled(error: DatabaseError) {
Toast.makeText(this#ItemsActivity,error.message, Toast.LENGTH_SHORT).show()
myDataLoaderProgressBar.visibility = View.INVISIBLE
}
override fun onDataChange(snapshot: DataSnapshot) {
mHotels.clear()
for (teacherSnapshot in snapshot.children){
val upload = teacherSnapshot.getValue(HotelandInns::class.java)
upload!!.key = teacherSnapshot.key
mHotels.add(upload)
}
listAdapter.notifyDataSetChanged()
myDataLoaderProgressBar.visibility = View.GONE
}
})
}
override fun onDestroy() {
super.onDestroy()
mDatabaseRef!!.removeEventListener(mDBListener!!)
}
}
ListAdapter.kt
class ListAdapter (var mContext:Context,var hotelsList:List<HotelandInns>):
RecyclerView.Adapter<ListAdapter.ListViewHolder>()
{
inner class ListViewHolder(var v:View): RecyclerView.ViewHolder(v){
var imgT = v.findViewById<ImageView>(R.id.hotelImageView)
var nameT = v.findViewById<TextView>(R.id.nameTextView)
var locaT = v.findViewById<TextView>(R.id.locationTextView)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ListViewHolder {
var infalter = LayoutInflater.from(parent.context)
var v = infalter.inflate(R.layout.row_item,parent,false)
return ListViewHolder(v)
}
override fun getItemCount(): Int =hotelsList.size
override fun onBindViewHolder(holder: ListViewHolder, position: Int) {
var newList = hotelsList[position]
holder.nameT.text = newList.name
holder.locaT.text = newList.location
holder.imgT.loadImage(newList.imageUrl)
holder.v.setOnClickListener {
val desT = newList.description
val name = newList.name
val serT = newList.services
val acoT = newList.accommodation
val locat = newList.location
val imgUri = newList.imageUrl
val conT = newList.contact
val mIntent = Intent(mContext, DetailsActivity::class.java)
mIntent.putExtra("NAMET",name)
mIntent.putExtra("DEST",desT)
mIntent.putExtra("ACOT",acoT)
mIntent.putExtra("SERT",serT)
mIntent.putExtra("LOCAT",locat)
mIntent.putExtra("CONT", conT)
mIntent.putExtra("IMGURI",imgUri)
mContext.startActivity(mIntent)
}
}
}
Uitel.kt
fun ImageView.loadImage(url: String?){
val option = RequestOptions().placeholder(R.mipmap.ic_launcher)
.error(R.mipmap.ic_launcher)
Glide.with(context)
.setDefaultRequestOptions(option)
.load(url)
.into(this)
}
I need to develop an app from university.
When I start the app, the RecyclerView is displayed correctly. However, when I refresh the RecyclerView or switch to another TAP, the card layouts are no longer displayed.
I get all the events from Firebase using an Event data class and pass them to the RecyclerAdapter.
Can you help me so that the refresh works?
Thanks a lot
Augustin
RecyclerAdapter:
class RecyclerAdapter(val events: List<Event>) :
RecyclerView.Adapter<RecyclerAdapter.ViewHolder>() {
private lateinit var navController: NavController
private lateinit var events_id : String
var countEventId = mutableListOf<String>()
var count = 0
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view =
LayoutInflater.from(parent.context).inflate(R.layout.view_cardlayout, parent, false)
return ViewHolder(view)
}
override fun getItemCount() = events.size
override fun onBindViewHolder(holder: RecyclerAdapter.ViewHolder, position: Int) {
holder.bind(events[position])
}
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bind(event: Event) {
itemView.headlineTV.text = event.name
itemView.placeHolderTV.text = event.location
itemView.dateHolderTV.text = event.date
itemView.timeHolderTV.text = "${event.starttime} Uhr"
itemView.dataHolderVotes.text = event.votes.toString()
itemView.dataHolderVotes.text = event.votesUser?.size.toString()
countEventId.add(event.eventId)
count++
}
init {
itemView.setOnClickListener {
val pos: Int =
bindingAdapterPosition
navController = findNavController(itemView)
val action_HomeToData1 =
HomeFragmentDirections.actionHomeFragmentToData1Fragment(countEventId[pos])
navController.navigate(action_HomeToData1)
}
}
}
}
HomeFragment:
class HomeFragment : Fragment(R.layout.fragment_home) {
private lateinit var firestoneDb: FirebaseFirestore
private lateinit var events: MutableList<Event>
//private lateinit var adapter: RecyclerAdapter
private var layoutManager: RecyclerView.LayoutManager? = null
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
var auth = FirebaseAuth.getInstance()
var user = auth.currentUser
var uid = user?.uid
firestoneDb = FirebaseFirestore.getInstance()
events = mutableListOf()
recyclerView.adapter = RecyclerAdapter(events)
recyclerView.layoutManager = LinearLayoutManager(activity)
val eventsReference = firestoneDb.collection("events")
eventsReference
.whereEqualTo("creator", uid)
.addSnapshotListener { snapshot, exception ->
if (exception != null || snapshot == null) {
Log.e(TAG, "Exception when querying events", exception)
return#addSnapshotListener
}
var eventList = snapshot.toObjects(Event::class.java)
events.clear()
events.addAll(eventList)
for (event in eventList) {
Log.i(TAG, "Event ${event}")
}
}
refreshHome()
}
override fun onResume() {
super.onResume()
}
private fun refreshHome() {
refresherHome.setOnRefreshListener {
Toast.makeText(activity, "Page has been refreshed", Toast.LENGTH_SHORT).show()
refresherHome.isRefreshing = false
val action_HomeToSelf = HomeFragmentDirections.actionHomeFragmentSelf()
findNavController().navigate(action_HomeToSelf)
}
}
}
Data class Event:
data class Event (
var description: String = "",
#get: PropertyName("start_time") #set:PropertyName("start_time") var starttime: String = "",
var creator: String = "",
#get: PropertyName("event_id") #set:PropertyName("event_id")var eventId: String = "",
var location: String = "",
var name: String = "",
var questions: List<String>? = null,
var date: String = "",
#get: PropertyName("votes") #set:PropertyName("votes") var votes: Int = 0,
#get: PropertyName("creationTimeMs") #set:PropertyName("creationTimeMs")var creationTimeMs: Long = 0,
#get: PropertyName("votes_user") #set:PropertyName("votes_user")var votesUser: List<String>? = null
)
After you change the events in the list, you need to tell the adapter that its data has change so that it knows to refresh the view. To do this call adapter.notifyDataSetChanged(), inside the snapshot listener after you're done modifying events.
Here RecyclerView loads only one item however the loops works prefect but with RecyclerView loads only one item and not load all items
.........................................................................................................................................................................................................................................
GetJson.kt
class GetJson : AppCompatActivity() {
lateinit var recyclerView: RecyclerView
var arrayList = ArrayList<JsonModel>()
private var requestQueue : RequestQueue? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_get_json)
recyclerView = findViewById(R.id.recyclerView2)
recyclerView.layoutManager = LinearLayoutManager(this)
val getButton : Button = findViewById(R.id.ShowButtonJson)
requestQueue = Volley.newRequestQueue(this)
getButton.setOnClickListener {
getFromServer()
}
}
fun getFromServer(){
val url = "http://..../testapp/getjson.php"
val request = JsonObjectRequest(Request.Method.GET,url,null, {
response -> try {
val jsonArray = response.getJSONArray("names")
for (i in 0 until jsonArray.length()){
val name = jsonArray.getJSONObject(i)
val firstname = name.getString("firstname")
val middlename = name.getString("middlename")
val lastname = name.getString("lastname")
arrayList.add(JsonModel(firstname,middlename,lastname))
}
val namesAdapter = jsonAdapter(arrayList)
recyclerView.adapter = namesAdapter
namesAdapter.notifyDataSetChanged()
} catch (e: JSONException){
e.printStackTrace()
}
}, { response -> response.printStackTrace()
})
requestQueue?.add(request)
}
}
jsonAdapter.kt
class jsonAdapter(val data : List<JsonModel>) : RecyclerView.Adapter<jsonAdapter.ViewHolder>() {
class ViewHolder(view : View) : RecyclerView.ViewHolder(view) {
val firstnameText : TextView = view.findViewById(R.id.firstnameView)
val middlenameText : TextView = view.findViewById(R.id.middleNameView)
val lastnameText : TextView = view.findViewById(R.id.lastNameView)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): jsonAdapter.ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.jsonlist,parent,false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: jsonAdapter.ViewHolder, position: Int) {
val namesModel = data[position]
holder.firstnameText.text = namesModel.firstname
holder.middlenameText.text = namesModel.middlename
holder.lastnameText.text = namesModel.lastname
}
override fun getItemCount(): Int {
return data.size
}
}
I have added firebase database and the data also gets saved into the firebase realtime database, but it doesnot gets shown into the spinner, my spinner is showing no value.If theres some other way?
This is the code of my fragment:
class IncomeFragment: Fragment(){
//FAB
lateinit var addBankFab: FloatingActionButton
lateinit var addBankText: TextView
//Spinner
lateinit var spinner: Spinner
lateinit var dropDown: TextView
//Firebase Database
lateinit var mAuth: FirebaseAuth
lateinit var mIncomeDatabase: DatabaseReference
lateinit var mBankDatabase: DatabaseReference
lateinit var helper: FirebaseHelper
//Recycler View
lateinit var recyclerView: RecyclerView
//TextView
lateinit var incomeTotal : TextView
//Update Edit Text
lateinit var editAmount: EditText
lateinit var editType: EditText
lateinit var editNote: EditText
lateinit var editBankName:EditText
//Button for update and delete
lateinit var btnUpdate: Button
lateinit var btnDelete: Button
lateinit var btnSave : Button
lateinit var btnCancel:Button
//Data item Value
lateinit var type: String
lateinit var note: String
var amount: Int = 0
lateinit var post_key:String
lateinit var name:String
lateinit var ac:String
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
val myview= inflater.inflate(R.layout.fragment_income, container, false)
mAuth= FirebaseAuth.getInstance()
val mUser = mAuth.currentUser
val uid = mUser?.uid
addBankFab=myview.findViewById(R.id.add_bank_fab)
addBankText=myview.findViewById(R.id.add_bank_text)
spinner=myview.findViewById(R.id.incomeSpinner)
mIncomeDatabase =
FirebaseDatabase.getInstance().reference.child("IncomeData").child(uid.toString())
incomeTotal=myview.findViewById(R.id.income_txt_result)
mBankDatabase= FirebaseDatabase.getInstance().reference.child("BankData").child(uid.toString())
helper = FirebaseHelper(mBankDatabase)
spinner.setAdapter(
activity?.let {
ArrayAdapter<String>(
it,
android.R.layout.simple_list_item_1,
helper.retrieve()
)
}
)
recyclerView=myview.findViewById(R.id.incomeRecyclerView)
val layoutManager = LinearLayoutManager(activity)
layoutManager.reverseLayout = true
layoutManager.stackFromEnd = true
recyclerView.setHasFixedSize(true)
recyclerView.layoutManager = layoutManager
mIncomeDatabase.addValueEventListener(object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
var totalvalue :Int = 0
for (ds in dataSnapshot.children) {
val data: Data = ds.getValue<Data>(Data::class.java)!!
totalvalue+=data.amount
val stTotalValue:String = valueOf(totalvalue)
incomeTotal.text = stTotalValue+".00"
}
}
override fun onCancelled(databaseError: DatabaseError) {}
})
return myview
}
private fun insertBank() {
val bankdialog = AlertDialog.Builder(activity)
val inflater = LayoutInflater.from(activity)
val view: View = inflater.inflate(R.layout.add_bank_layout, null)
bankdialog.setView(view)
val dialog = bankdialog.create()
dialog.setCancelable(false)
val BankName = view.findViewById<EditText>(R.id.account_bank)
val BankAc = view.findViewById<EditText>(R.id.account_number)
val btnSaveBank = view.findViewById<Button>(R.id.btn_save_bank)
val btnCancelBank = view.findViewById<Button>(R.id.btn_cancel_bank)
btnSaveBank.setOnClickListener {
val name = BankName.text.toString().trim()
val ac = BankAc.text.toString().trim()
if (TextUtils.isEmpty(name)) {
BankName.error = "Required Field..."
return#setOnClickListener
}
if (TextUtils.isEmpty(ac)) {
BankAc.error = "Required Field..."
return#setOnClickListener
}
val bankacno = ac.toInt()
val id: String? = mBankDatabase.push().key
val mDate: String = DateFormat.getDateInstance().format(Date())
val bankdata = EmiData(bankacno, name, id, mDate)
mBankDatabase.child(id.toString()).setValue(bankdata)
Toast.makeText(activity, "DATA ADDED", Toast.LENGTH_SHORT).show()
dialog.dismiss()
}
btnCancelBank.setOnClickListener {
dialog.dismiss()
}
dialog.show()
}
override
fun onStart() {
super.onStart()
val options = FirebaseRecyclerOptions.Builder<Data>()
.setQuery(mIncomeDatabase, Data::class.java)
.setLifecycleOwner(this)
.build()
val firebaseRecyclerAdapter: FirebaseRecyclerAdapter<Data, MyViewHolder> =
object : FirebaseRecyclerAdapter<Data, MyViewHolder>(options) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
return MyViewHolder(
LayoutInflater.from(parent.context)
.inflate(R.layout.income_recycler_data, parent, false)
)
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int, model: Data) {
holder.setType(model.type)
holder.setAmount(model.amount)
holder.setDate(model.date)
holder.setNote(model.note)
holder.mView.setOnClickListener {
post_key= getRef(position).key.toString()
type=model.type
note=model.note
amount=model.amount
updateDataItem()
}
}
}
recyclerView.adapter = firebaseRecyclerAdapter
}
class MyViewHolder(itemView: View) : ViewHolder(itemView) {
val mView = itemView
fun setType(type: String) {
val mType = mView.findViewById<TextView>(R.id.type_txt_income)
mType.text = type
}
fun setNote(note: String) {
val mNote = mView.findViewById<TextView>(R.id.note_txt_income)
mNote.text = note
}
fun setDate(date: String) {
val mDate = mView.findViewById<TextView>(R.id.date_txt_income)
mDate.text = date
}
fun setAmount(amount: Int) {
val mAmount = mView.findViewById<TextView>(R.id.amount_txt_income)
val stAmount = valueOf(amount)
mAmount.text = stAmount
}
}
private fun updateDataItem() {
val mydialog = AlertDialog.Builder(activity)
val inflater = LayoutInflater.from(activity)
val myView: View = inflater.inflate(R.layout.update_data_item, null)
mydialog.setView(myView)
val dialog = mydialog.create()
val editAmount = myView.findViewById<EditText>(R.id.amount_edit)
val editType = myView.findViewById<EditText>(R.id.type_edit)
val editNote = myView.findViewById<EditText>(R.id.note_edit)
//Set data to edit text..
editType.setText(type)
editType.setSelection(type.length)
editNote.setText(note)
editNote.setSelection(note.length)
editAmount.setText(valueOf(amount))
editAmount.setSelection(valueOf(amount).length)
val btnUpdate = myView.findViewById<Button>(R.id.btn_update)
val btnDelete = myView.findViewById<Button>(R.id.btn_delete)
btnUpdate.setOnClickListener {
type = editType.text.toString().trim()
note = editNote.text.toString().trim()
var mdAmount = amount.toString()
mdAmount = editAmount.text.toString().trim { it <= ' ' }
val myAmount = mdAmount.toInt()
val mDate: String = DateFormat.getDateInstance().format(Date())
val data = Data(myAmount, type, note, post_key, mDate)
mIncomeDatabase.child(post_key).setValue(data)
dialog.dismiss()
}
btnDelete.setOnClickListener {
mIncomeDatabase.child(post_key).removeValue()
dialog.dismiss()
}
dialog.show()
}
}
This is my firebase helper:
class FirebaseHelper(val db: DatabaseReference) {
private var saved: Boolean? = null
//SAVE
fun save(bankData: BankData?): Boolean? {
saved = if (bankData == null) {
false
} else {
try {
db.child("name").push().setValue(bankData)
true
} catch (e: DatabaseException) {
e.printStackTrace()
false
}
}
return saved
}
//READ
fun retrieve(): ArrayList<String> {
val bankNames = ArrayList<String>()
db.addChildEventListener(object : ChildEventListener {
override fun onChildAdded(
dataSnapshot: DataSnapshot,
s: String?
) {
fetchData(dataSnapshot, bankNames)
}
override fun onChildChanged(
dataSnapshot: DataSnapshot,
s: String?
) {
fetchData(dataSnapshot, bankNames)
}
override fun onChildRemoved(dataSnapshot: DataSnapshot) {}
override fun onChildMoved(
dataSnapshot: DataSnapshot,
s: String?
) {
}
override fun onCancelled(databaseError: DatabaseError) {}
})
return bankNames
}
private fun fetchData(
snapshot: DataSnapshot,
bankData: ArrayList<String>
) {
bankData.clear()
val name: BankData? = snapshot.getValue(BankData::class.java)
bankData.add(bankData.toString())
}
}
Your spinner shows no value because the data is not retrieved yet from the DB.
So what you should do is create a callback from FirebaseHelper to IncomeFragment
First, create a callback
interface FirebaseHelperCallback {
fun dataRetrievedFromDB(data: List<String>)
}
Second, create a variable, setter function and call dataRetrievedFromDB function in FirebaseHelper class
class FirebaseHelper(val db: DatabaseReference) {
private lateinit var firebaseHelperCallback: FirebaseHelperCallback
fun setFirebaseHelperCallback(firebaseHelperCallback: FirebaseHelperCallback) {
this.firebaseHelperCallback = firebaseHelperCallback
}
...
private fun fetchData(snapshot: DataSnapshot, bankData: ArrayList<String>) {
bankData.clear()
val name: BankData? = snapshot.getValue(BankData::class.java)
bankData.add(bankData.toString())
firebaseHelperCallback.dataRetrievedFromDB(bankData)
}
}
Lastly, implement the callback in IncomeFragment
class IncomeFragment: Fragment(), FirebaseHelperCallback {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
...
helper.setFirebaseHelperCallback(this)
}
...
override fun dataRetrievedFromDB(data: List<String>) {
spinner.setAdapter(
activity?.let {
ArrayAdapter<String>(
it,
android.R.layout.simple_list_item_1,
data
)
}
)
}
}
I have backend firebase which i am using to populate the listview , i was implementing the search functionality suddenly i found a weird behavior in listview ,it is creating duplicates in numbers like 30-40 and above.
Please help me i was batteling for it from 3 days. i am very new to development so any suggestions to code optimizing will also be taken as help!
class Menu : AppCompatActivity(){
private var prevKey : String? = null
var listAdapter : CustomAdapter ? = null
private val listItemArrayList = ArrayList<ListItem>()
var rootRef : FirebaseDatabase? = null
var adminRef : DatabaseReference? = null
var mAuth : FirebaseAuth? = null
var helper : CustomAdapter?=null
private var user : String?=null
var mAuthListener: FirebaseAuth.AuthStateListener? = null
var Items = ArrayList<String>()
var isSectionBoolean = ArrayList<Boolean>()
var ItemCategory= ArrayList<String>()
var ItemCost = ArrayList<Int>()
var listView : ListView? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_menu)
mAuth = FirebaseAuth.getInstance()
mAuthListener = FirebaseAuth.AuthStateListener { }
rootRef = FirebaseDatabase.getInstance()
user =mAuth!!.currentUser!!.phoneNumber as String
adminRef = rootRef!!.getReference("AdminCafe").child(user!!)
listView = findViewById(R.id.admindynamiclist)
listAdapter = CustomAdapter(listItemArrayList,this)
listView!!.adapter = listAdapter
listView!!.isTextFilterEnabled = true
SearchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener{
override fun onQueryTextSubmit(query: String?): Boolean {
return false
}
override fun onQueryTextChange(newText: String?): Boolean {
listAdapter!!.filter(newText.toString())
return false
}
})
getData()
}
fun addAct(v:View)
{
val intent = Intent(applicationContext,AddActivity::class.java)
startActivity(intent)
}
private fun getData() {
println("getData")
var menucatRef = adminRef!!.child("MenuItem")
menucatRef.addValueEventListener(object : ValueEventListener{
override fun onCancelled(p0: DatabaseError) {
}
override fun onDataChange(p0: DataSnapshot) {
for(Snap in p0.children)
{
println("wtfff")
println("Child"+Snap.childrenCount)
getDataFromKey(Snap.key.toString(),Snap.childrenCount.toInt())
}
}
})
}
private fun getDataFromKey(key: String, child :Int) {
listItemArrayList.clear()
println("called")
var count = 0
var counter = 0
var Category = CategoryHeader()
var menuRef = adminRef!!.child("MenuItem").child(key)
menuRef.addListenerForSingleValueEvent(object : ValueEventListener{
override fun onCancelled(p0: DatabaseError) {
}
override fun onDataChange(p0: DataSnapshot) {
var catKey = p0.key.toString()
for(snap in p0!!.children)
{
if(count == 0)
{
Category!!.setheader(catKey)
listItemArrayList!!.add(Category)
println("Seperator will be added")
}
else
{
var hashMap = snap.value as HashMap<String,String>
var itemName = snap.key
var isVeg = hashMap["isVeg"]
var itemCost = hashMap["itemCost"]!!.toInt()
var isSig = hashMap["isSig"]
var ItemHelper = Item()
if(itemName!=null)
{
ItemHelper.setItemName(itemName)
}
if(itemCost!=null)
{
ItemHelper.setItemCost(itemCost)
}
listItemArrayList!!.add(ItemHelper)
}
count++
}
listAdapter!!.notifyDataSetChanged()
}
})
}
interface ListItem {
fun isHeader(): Boolean
fun getName(): String
fun getItemCost() : Int
}
fun editAct(v:View)
{
println("Inside edit")
}
}
And Adapter class
class CustomAdapter(private var listItem : ArrayList<Menu.ListItem>, private val context: Activity) : BaseAdapter() {
var orig = ArrayList<Menu.ListItem> ()
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
orig.addAll(listItem)
println("List Item is"+listItem)
println("List Item is"+orig)
var holder = ViewHolder()
var customView = convertView
var flag = true
if (convertView == null) {
val layoutInflater = context.layoutInflater
if(listItem.get(position).isHeader()) {
println("position"+position)
customView = layoutInflater.inflate(R.layout.seperator, null)
holder.tvLabel = customView.categoryText
} else {
println("position"+position)
customView = layoutInflater.inflate(R.layout.list_item, null)
holder.tvLabel = customView.itemad
holder.itemCost = customView.cost
flag = false
}
customView.setTag(holder)
}
else
{
customView = convertView
holder = convertView!!.tag as ViewHolder
}
if(flag) {
println("Custoom Flag is"+flag)
holder!!.tvLabel!!.text = listItem.get(position).getName()
}
else {
println("Custoom Flag is"+flag)
holder!!.tvLabel!!.text = listItem.get(position).getName()
holder.itemCost!!.text = listItem.get(position).getItemCost().toString()
}
return customView!!
}
override fun getItem(position: Int): Any {
return listItem.get(position)
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
override fun getCount(): Int {
return listItem.size
}
private inner class ViewHolder {
var tvLabel: TextView? = null
var itemCost: TextView? = null
}
fun filter(query : String)
{
println("called")
listItem.clear()
var search = query
search = search.toLowerCase(Locale.getDefault())
if(search.isEmpty())
{
listItem.addAll(orig!!)
println("Inside size 0")
}
else
{
var counter = 0
for(result in orig!! )
{
if(result.getName().toLowerCase().contains(search))
{
println("Result is "+result.getName())
println("listItem"+listItem)
}
}
}
}
}