I'm trying to get a RecyclerView to update once I have downloaded some data from Firestore but it doesn't seem to update the UI when the data changes. Here is the main activity:
class MainActivity : AppCompatActivity() {
private lateinit var dbService: DatabaseManager
private var mBound: Boolean = false
private val restaurantListModel: RestaurantList by viewModels()
val data = ArrayList<RestaurantCardModel>()
val adapter = RestaurantListAdapter(data)
/** Defines callbacks for service binding, passed to bindService() */
private val connection = object : ServiceConnection {
override fun onServiceConnected(className: ComponentName, service: IBinder) {
// We've bound to LocalService, cast the IBinder and get LocalService instance
val binder = service as DatabaseManager.LocalBinder
dbService = binder.getService()
mBound = true
dbService.read_restaurants(object: MyCallback {
override fun onCallback(value: MutableList<Restaurant>) {
restaurantListModel.restList.value = value
updateView()
}
})
}
override fun onServiceDisconnected(arg0: ComponentName) {
mBound = false
}
}
fun updateView(){
for (rest in restaurantListModel.restList.value!!){
data.add(RestaurantCardModel(R.drawable.pizza_express_logo, rest.name, 5, rest.review, rest.no_review,
R.color.colorPrimary))
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Bind to LocalService
Intent(this, DatabaseManager::class.java).also { intent ->
bindService(intent, connection, Context.BIND_AUTO_CREATE)
}
// getting the recyclerview by its id
val recyclerview = findViewById<RecyclerView>(R.id.restaurant_recyclerview)
// this creates a vertical layout Manager
recyclerview.layoutManager = LinearLayoutManager(this)
// Setting the Adapter with the recyclerview
recyclerview.adapter = adapter
if(mBound) { updateView() }
}
override fun onResume() {
super.onResume()
if (mBound) { updateView() }
}
override fun onStart() {
super.onStart()
}
override fun onStop() {
super.onStop()
unbindService(connection)
mBound = false
}
}
Then you have my database manager for fetching the data from firebase:
class DatabaseManager : Service() {
// Binder given to clients
private val binder = LocalBinder()
var db = FirebaseFirestore.getInstance()
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
return super.onStartCommand(intent, flags, startId)
}
fun upload_review(review_data: String){
}
fun read_restaurants(myCallback : MyCallback): MutableList<Restaurant> {
var restList : MutableList<Restaurant> = mutableListOf()
db.collection("restaurant")
.get()
.addOnCompleteListener { task ->
if (task.isSuccessful) {
restList = updateRestaurantList(task.result!!)
myCallback.onCallback(restList)
} else {
Log.w(TAG, "Error getting documents.", task.exception)
}
}
return restList
}
private fun updateRestaurantList(restaurants: QuerySnapshot): MutableList<Restaurant> {
var restList : MutableList<Restaurant> = mutableListOf()
for (doc in restaurants.documents){
Log.d(TAG, doc.toString())
var tempRest : Restaurant? = doc.toObject(Restaurant::class.java)?.withId(doc.id)
if (tempRest != null) {
restList.add(tempRest)
}
}
return restList
}
/**
* Class used for the client Binder. Because we know this service always
* runs in the same process as its clients, we don't need to deal with IPC.
*/
inner class LocalBinder : Binder() {
// Return this instance of LocalService so clients can call public methods
fun getService(): DatabaseManager = this@DatabaseManager
}
override fun onBind(intent: Intent): IBinder {
return binder
}
}
The recycler view works fine when I add the data manually in the onCreate() method but doesn't update the view once firebase is finished, any help would be appreciated.
CodePudding user response:
The recycler view works fine when I add the data manually in the onCreate() method but doesn't update the view
That's the expected behavior since you are using a .get()
call, which basically means that you are getting the data only once. What you are looking for is listening for real-time updates. So you have to use addSnapshotListener()
call for that.
Besides that, there is also a useful library called FirebaseUI for Android that has a specific usage for Cloud Firestore.