Reputation: 119
talking about firestore persistent data, lets suppose the user does not have any connectivity the first time the app is launched. I add some data to Firestore Database (like userID..), I can get it back with get() method. Now user closes the app.
Next time he will open the app (still without connectivity), will he be able to retrieve data stored previously, just as if it was stored in the way of sharedprefs ? I cannot clearly figure out how to find a proper way to set up an init phasis with persistent data.
I have several fragments. Each time one of them is launched, I use "onResume" method to populate my components from data (previously stored in sharedpref). When I set Firestore getData, it takes time to be retrieved. So if the user changes from the current fragment to another one, I have errors about components being null or unreachable at the time the result from database is complete, when connectivity is ON.
What would be the best way to implement such "onResume" data refill ?
UPDATE :
Here is some piece of code in: MainAvtivity.kt
FirebaseFirestore.getInstance().firestoreSettings.isPersistenceEnabled
sightingsDatabase = FirebaseFirestore.getInstance()
docname=FireStoreSetup().setupFB(sightingsDatabase!!,this)
a kotlin object class to populate my document :
data class Sighting(var userID: String,
var sig_wit_situation_type: Int,
var sig_env_background_type: Int,
var sig_ground_type: Int,
var sig_YYYY: String,
var sig_MM: String,
var sig_DD: String,
var sig_time_start: String,
var sig_date_time: String,
var sig_duration_hms: String,
var sig_duration_milli: Int,
var sig_weather_full: Int,
var sig_temp: Int)
in FireStoreSetup class : when first init happens ->
val sighting = Sighting(deviceId!!,
0,
0,
0,
strDate.substring(0, 4),
strDate.substring(5, 7),
strDate.substring(8, 10),
strDate.substring(11),
strDate,
"00:00:00",
0,
0,
0)
db.collection("users").document(docname!!)
.set(sighting)
.addOnSuccessListener {
Log.d(_tag, "DocumentSnapshot successfully written!")
setShared(context,"doc_name",docname!!)}
.addOnFailureListener { e -> Log.w(_tag, "Error writing document", e) }
then a fun to write data to the server
fun addValue(key:String,value:Any?){
val docData = HashMap<String,Any?>()
docData.put(key, value)
FirebaseFirestore.getInstance().collection("users").document(docname!!)
.set(docData, SetOptions.merge())
}
and
fun readValue(){
val docRef = FirebaseFirestore.getInstance().collection("users").document(docname!!)
docRef.addSnapshotListener(object:EventListener<DocumentSnapshot> {
override fun onEvent(snapshot:DocumentSnapshot?, e:FirebaseFirestoreException?) {
if (e != null)
{
Log.w("firestore", "Listen failed.", e)
}
if (snapshot != null && snapshot.exists())
{
Log.d("firestore", "Current data: " + snapshot.getData())
FragmentHome.vars=snapshot.getData()
}
else
{
Log.d("firestore", "Current data: null")
}
}
})
}
in FragmentHome :
companion object {
val itemsMenu = ArrayList<MenuData>()
var vars: MutableMap<String,Any>? =null
fun newInstance(value: Int): FragmentHome {
val args = Bundle()
args.putInt("menu", value)
val fragment = FragmentHome()
fragment.arguments = args
return fragment
}
}
override fun onResume() {
super.onResume()
FireStoreSetup().readValue()
when (_menu){
0-> switchRecycler(1,0)
1-> switchRecycler(0,0)
}
}
and then from fragmentHome, replacing it with new fragment with firestore values :
val situ= vars!!["sig_wit_situation_type"].toString().toInt()
val env= vars!!["sig_env_background_type"].toString().toInt()
val grd= vars!!["sig_ground_type"].toString().toInt()
reFrag(FragmentSitu.newInstance(situ,env,grd), 1)
where in new FragmentSitu fragment we have :
companion object {
fun newInstance(situ: Int,env: Int,grd: Int): FragmentSitu {
val args = Bundle()
args.putInt("sig_wit_situation_type", situ)
args.putInt("sig_env_background_type", env)
args.putInt("sig_ground_type", grd)
val fragment = FragmentSitu()
fragment.arguments = args
return fragment
}
}
and it works with no delays, online and offline, thanks to Franck and docRef.addSnapshotListener.
** There must be a better way to catch snapshot.getData()
result from within onEvent(snapshot:DocumentSnapshot?)
,as I would have liked to set my fragment args FragmentSitu.newInstance(situ,env,grd) directly from snapshot.getData()["situ"]
, snapshot.getData()["env"]
...
Upvotes: 2
Views: 1309
Reputation: 598728
firebaser here
Firestore persists the data you write on a device to a local database. So the next time you start the application it will indeed be able to read that same data, even when the device has never been connected to the Firebase servers.
When your app first tries to read data from Firestore it tries to establish a connection to its servers. If you're using get()
calls to read the data Firestore will wait for that connection to be established or failed before it returns data. This means it may take quite some time for this initial call. We know that this may lead to unwanted behavior for the users of your app, so we're looking at ways to improve this behavior.
In the meantime, consider using realtime listeners to read the same data. These listener behave differently in this scenario and will/may provide a result twice:
Upvotes: 2
Reputation: 138824
As the offical documentation says,
Cloud Firestore supports offline data persistence. This feature caches a copy of the Cloud Firestore data that your app is actively using, so your app can access the data when the device is offline.
But in order to use this feature, you need at least one connection to the dabase. This means that your app must be connected to the internet at least once. After that, you'll be able to write, read, listen to, and query the cached data.
If you want to use data between activities or fragments, i recomand you using either an Intent
or either SharedPreferences
, which can hold your data across the whole app.
Upvotes: 0