Search code examples
androidgetgoogle-cloud-firestore

Delay getting data from FireStore when offline (Android)


I'm having an issue with FireStore offline persistence when getting information from a single document.

The below method of filling form works fine when online, but I'm seeing a long delay (filling data into a simple EditText form) when I test the app offline (sometimes three or four seconds):

    private void importFirestoreData() {
        dbDocument = dbFirestore.collection("sites").document(siteId);
        dbDocument.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
            @Override
            public void onComplete(@NonNull Task<DocumentSnapshot> task) {
                if (task.isSuccessful()) {
                    DocumentSnapshot document = task.getResult();
                    if (document.exists()) {
                        Log.d(TAG, "DocumentSnapshot data: " + document.getData());
                        companyNameEditText.setText(document.getString("companyName"));
                        siteLocationEditText.setText(document.getString("siteLocation"));
                        siteAddressEditText.setText(document.getString("siteAddress"));
                        companyWebsiteEditText.setText(document.getString("companyWebsite"));
                    } else {
                        Log.d(TAG, "No such document");
                    }
                } else {
                    Log.d(TAG, "get failed with ", task.getException());
                }
            }
        });
    }

The rest of the code is here:

public class SiteAddEditActivity extends AppCompatActivity implements View.OnClickListener {

    private static final String TAG = "SiteAddEditActivity";
    public static final String KEY_SITE_ID = "key_site_id";

    private TextView mainTitleTextView;
    private EditText companyNameEditText, siteLocationEditText, siteAddressEditText, companyWebsiteEditText;
    private Button saveButton, cancelButton;
    private String siteId;

    // Database declarations
    private FirebaseAuth mAuth;
    private FirebaseUser mUser;
    private FirebaseFirestore dbFirestore;
    private DocumentReference dbDocument;
    private Query dbQuery;
    private boolean newDoc;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);

        setContentView(R.layout.site_add_edit_activity);

        setUpViews();
        setUpListeners();
        setUpFirestore();
        getIDfromExtras();
    }
    private void setUpViews() {
        mainTitleTextView = findViewById(R.id.textViewMainHeading);
        companyNameEditText = findViewById(R.id.editTextCompanyName);
        siteLocationEditText = findViewById(R.id.editTextSiteLocation);
        siteAddressEditText = findViewById(R.id.editTextSiteAddress);
        companyWebsiteEditText = findViewById(R.id.editTextCompanyWebsite);
        saveButton = findViewById(R.id.buttonSave);
        cancelButton = findViewById(R.id.buttonCancel);
    }

    private void setUpListeners() {
        saveButton.setOnClickListener(this);
        cancelButton.setOnClickListener(this);
    }

    private void setUpFirestore() {
        mAuth = FirebaseAuth.getInstance();
        mUser = mAuth.getCurrentUser();

        dbFirestore = FirebaseFirestore.getInstance();
    }

    private void getIDfromExtras() {

        newDoc = true;

        // Get site ID from extras
        siteId = getIntent().getExtras().getString(KEY_SITE_ID);

        if (siteId == null) {
            throw new IllegalArgumentException("Must pass extra " + KEY_SITE_ID);
        }
        else {
            newDoc = false;
            mainTitleTextView.setText(R.string.app_edit_site);
            importFirestoreData();
        }
    }

    private void importFirestoreData() {
        dbDocument = dbFirestore.collection("sites").document(siteId);
        dbDocument.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
            @Override
            public void onComplete(@NonNull Task<DocumentSnapshot> task) {
                if (task.isSuccessful()) {
                    DocumentSnapshot document = task.getResult();
                    if (document.exists()) {
                        Log.d(TAG, "DocumentSnapshot data: " + document.getData());
                        companyNameEditText.setText(document.getString("companyName"));
                        siteLocationEditText.setText(document.getString("siteLocation"));
                        siteAddressEditText.setText(document.getString("siteAddress"));
                        companyWebsiteEditText.setText(document.getString("companyWebsite"));
                    } else {
                        Log.d(TAG, "No such document");
                    }
                } else {
                    Log.d(TAG, "get failed with ", task.getException());
                }
            }
        });
    }

    @Override
    public void onClick(View view) {

        int i = view.getId();
        if(i == R.id.buttonSave){
            if (newDoc){
                saveSite();
            }

            else {
                updateSite();
            }

            startActivity(new Intent(SiteAddEditActivity.this, SiteActivity.class));


        } else if (i == R.id.buttonCancel) {
            FirebaseAuth mAuth = FirebaseAuth.getInstance();
            Toast.makeText(this, "User (" + mAuth.getUid() + ") Signed Out!", Toast.LENGTH_LONG).show();
            mAuth.signOut();
            startActivity(new Intent(SiteAddEditActivity.this,LoginMainActivity.class));
        }

    }

    private void updateSite() {

        SitePOJO updateSite = new SitePOJO(
                companyNameEditText.getText().toString().trim(),
                siteLocationEditText.getText().toString().trim(),
                siteAddressEditText.getText().toString(),
                companyWebsiteEditText.getText().toString().trim()
        );
        dbDocument.set(updateSite);

    }

    private void saveSite() {

        SitePOJO newSite = new SitePOJO(
                companyNameEditText.getText().toString().trim(),
                siteLocationEditText.getText().toString().trim(),
                siteAddressEditText.getText().toString(),
                companyWebsiteEditText.getText().toString().trim()
        );
        dbDocument = dbFirestore.collection("sites").document();
        String thisDoc = dbDocument.getId();
        dbDocument.set(newSite);

        Toast.makeText(this, "New site created (document ref: " + thisDoc + ")", Toast.LENGTH_LONG).show();
    }
}

I'm guessing it is how I am getting the data - I'm wondering if it is better to handle the data in some sort of adapter (separate to the activities?)..


Solution

  • Thank you to Reaz - yes this post did help..

    My simple mind got confused between.get().addOnCompleteListener and .addSnapshotListener..

    Correct working code below:

        private void importFirestoreData() {
            dbDocument = dbFirestore.collection("sites").document(siteId);
            dbDocument.addSnapshotListener(new EventListener<DocumentSnapshot>() {
                @Override
                public void onEvent(@javax.annotation.Nullable DocumentSnapshot documentSnapshot, @javax.annotation.Nullable FirebaseFirestoreException e) {
                    if (e != null) {
                        Log.w(TAG, "Listen failed.", e);
                        return;
                    }
    
                    if (documentSnapshot != null && documentSnapshot.exists()) {
                        Log.d(TAG, "Current data: " + documentSnapshot.getData());
    
                        companyNameEditText.setText(documentSnapshot.getString("companyName"));
                        siteLocationEditText.setText(documentSnapshot.getString("siteLocation"));
                        siteAddressEditText.setText(documentSnapshot.getString("siteAddress"));
                        companyWebsiteEditText.setText(documentSnapshot.getString("companyWebsite"));
    
                    } else {
                        Log.d(TAG, "Current data: null");
                    }
                }
            });
        }