В моем приложении Android я читаю данные из базы данных Firebase Realtime .
Редактировать: Я изменил это с помощью обратных вызовов, потому что это работает асинхронно .
Я пытаюсь использовать класс ViewModel для хранения данных из базы данных Firebase и для обновления моего пользовательского интерфейса Google Maps новыми маркерами.
Проблема заключается в том, что мне нужно подписаться на мой Объект LiveData в onCreate () , но мне нужно обновить интерфейс карты с помощью маркеров в onMapReady () .
Нужно ли использовать обратные вызовы здесь или, возможно, ViewModel здесь избыточен? Любые предложения могут быть полезны. Я пытаюсь решить это в течение нескольких дней без успеха, кроме того, я искал много вопросов и ответов в Интернете, и ничто не кажется полезным.
функция readData из DatabaseManager:
fun readFromDatabase(type: String, callBack: OwnerListCallBack) {
when (type) {
OWNERS -> {
ownerRef.addValueEventListener(object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
// This method is called once with the initial value and again
// whenever data at this location is updated.
for (snapshot: DataSnapshot in dataSnapshot.children) {
val owner = snapshot.getValue(Owner::class.java)
Log.d(TAG, "readFromDatabase: onDataChange: owner's name is ${owner?.name}")
if (owner != null)
owners.add(owner)
Log.d(TAG, "readFromDatabase: onDataChange: owner's name is ${owners[0].name}")
}
}
override fun onCancelled(error: DatabaseError) {
// Failed to read value
Log.w(TAG, "Failed to read value.", error.toException())
}
})
}
}
setRestaurantsOnMap функция, которая вызывается в onMapReady:
private fun setRestaurantsOnMap() {
Log.d(TAG, "setRestaurantsOnMap: called")
// Set markers on the map. The owner's restaurants.
database.readFromDatabase(OWNERS)
// Log.d(TAG, "setRestaurantsOnMap: ${owners[0]}")
if (database.owners.isNotEmpty()) {
for (owner in database.owners) {
try {
val ownerAddress = owner.getRestaurant().getAddress()
Log.d(TAG, "setRestaurantsOnMap: owner's address is: ${ownerAddress.getAddress()}")
Toast.makeText(this, "setRestaurantsOnMap: owner's address is: ${ownerAddress.getAddress()}", Toast.LENGTH_LONG).show()
val latlng = getLocationFromAddress(this, ownerAddress.getAddress())
Log.d(TAG, "setRestaurantsOnMap: latitude is - ${latlng?.latitude}, longitude is - ${latlng?.longitude} ")
Toast.makeText(this, "setRestaurantsOnMap: latitude is - ${latlng?.latitude}, longitude is - ${latlng?.longitude} ", Toast.LENGTH_LONG).show()
if (latlng != null) {
mMap.addMarker(MarkerOptions()
.position(latlng)
.title(owner.getRestaurant().getName())
.snippet(owner.getRestaurant().getAddress().getAddress())
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_CYAN))
)
mMap.moveCamera(CameraUpdateFactory.newLatLng(latlng))
} else {
Toast.makeText(this, "setRestaurantsOnMap: latlng is null", Toast.LENGTH_SHORT).show()
}
} catch (e: NullPointerException) {
e.printStackTrace()
} catch (e: IndexOutOfBoundsException) {
e.printStackTrace()
}
}
}
}
Мой класс ViewModel:
class MapsViewModel : ViewModel() {
private val db = DatabaseManager()
private val owners = MutableLiveData<List<Owner>>()
val ownerList: LiveData<List<Owner>>
get() = owners
init {
owners.postValue(loadOwners())
Log.d(TAG, "init: Owners are ${owners.value}")
}
override fun onCleared() {
Log.d(TAG, "onCleared: canceling pending downloads")
}
private fun loadOwners(): List<Owner> {
var ownerList = ArrayList<Owner>()
Log.d(TAG, "loadAddress: called")
// Set markers on the map. The owner's restaurants.
db.readFromDatabase(OWNERS, object : OwnerListCallBack {
@SuppressLint("RestrictedApi")
override fun onCallBack(owners: ArrayList<Owner>) {
if (owners.isNotEmpty()) {
ownerList = owners
Log.d(TAG, "Owners are ${ownerList[0]}, ${ownerList[1]}, ${ownerList[2]}")
} else {
throw DatabaseException("Loaded was not success. Number of owners is ${owners.count()}")
}
}
})
return ownerList
}