I'm populating a realm
database table with information from a Cloud Firestore collection. On the first load, the application opens and saves the information but does not display it until I close and open the application.
I need the information to be displayed after it's been written to the realm database. ie without having to close and open the app. I tried doing this by putting them in methods and in order in the onCreate method.
So after it has written all the information to the realm database I want the recyclerview to populate but I don't know how to do that, please help?
ScreenShots
First launch(left) and second launch(right)
OnCreate:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_edit_import_user);
RelativeLayout = findViewById(R.id.contentuserimport);
// initialize realm
Realm.init(getApplicationContext());
//SETUP REEALM
RealmConfiguration defaultConfig = new RealmConfiguration.Builder()
.schemaVersion(0)
.build();
realm=Realm.getInstance(defaultConfig);
Intent intent = getIntent();
moduleID = intent.getStringExtra("moduleID");
moduleName = intent.getStringExtra("moduleName");
ButterKnife.bind(this);
init();
getAssessList();
}
Init():
private void init(){
linearLayoutManager = new LinearLayoutManager(getApplicationContext(), LinearLayoutManager.HORIZONTAL, false);
friendList.setLayoutManager(linearLayoutManager);
db = FirebaseFirestore.getInstance();
textView1.setText("Assessments - "+moduleName);
db.collection("assessment").whereEqualTo("module","xbIpNiDXGsIPmb5sTwbH").get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
@Override
public void onComplete(@NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (QueryDocumentSnapshot document : task.getResult()) {
//GET DATA
Assessment a=new Assessment(Double.parseDouble(document.get("achieved").toString()),
document.get("date").toString(),document.get("desc").toString(),document.get("module").toString(),
document.get("time").toString(),Double.parseDouble(document.get("total").toString()),document.get("type").toString(),
document.get("weight").toString());
//SAVE
RealmHelper helper=new RealmHelper(realm);
helper.save(a);
}
}
}
});
//READ
RealmHelper helper=new RealmHelper(realm);
Assessment=helper.retrieve();
//BIND
adapter=new AssessAdapter(this,Assessment);
friendList.setAdapter(adapter);
adapter.notifyDataSetChanged();
friendList.setAdapter(adapter);
}
getAssessList():
private void getAssessList(){
//RETRIEVE
RealmHelper helper=new RealmHelper(realm);
Assessment=helper.retrieve();
//BIND
adapter=new AssessAdapter(this,Assessment);
friendList.setAdapter(adapter);
adapter.notifyDataSetChanged();
friendList.setAdapter(adapter);
}
Trying to retrieve the data outside the callback in the way you do, will not work since the onComplete()
method has an asynchronous behavior. So you cannot simply use the following line of code:
Assessment=helper.retrieve();
And expect to retrieve and use the data like so. Firebase APIs are asynchronous
, meaning that onComplete()
method returns immediately after it's invoked, and the callback from the Task
it returns, will be called some time later. There are no guarantees about how long it will take. So it may take from a few hundred milliseconds to a few seconds before that data is available. Because that method returns immediately, the value of your Assessment
object you're trying to use it outside the onComplete()
method, will not have been populated from the callback yet.
Basically, you're trying to return a value synchronously from an API that's asynchronous. That's not a good idea. You should handle the APIs asynchronously as intended.
A quick solve for this problem would be to use the a
object that you get from the database only inside the onComplete()
method, otherwise I recommend you see the last part of my anwser from this post in which I have explained how it can be done using a custom callback. You can also take a look at this video for a better understanding.