0
public class MainActivity extends AppCompatActivity {


    private static final String TAG = "100";
    FirebaseFirestore db;

    String checkCode;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        db= FirebaseFirestore.getInstance();

        db.collection("Users")
                .whereEqualTo("level", "admin")
                .get()
                .addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
                    @Override
                    public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
                        if (!queryDocumentSnapshots.isEmpty()) {
                            List<DocumentSnapshot> list = queryDocumentSnapshots.getDocuments();
                            for (DocumentSnapshot d : list) {
                                checkCode = (String) d.get("kode");
                                Toast.makeText(MainActivity.this, "From inside : "+checkCode, Toast.LENGTH_LONG).show();
                                }
                            }
                        }
                    });
        Toast.makeText(MainActivity.this, "From outside : "+checkCode, Toast.LENGTH_LONG).show();
    }
}

I still confuse how to get data from cloud firestore. So i tried making a simple code to get a data from there. I put 1111 code.

After i run the program, The toast from inside give me:

From inside : 1111 

But the toast from outside give me:

From outside : null

Why is that? And how i can fix it?

aldi nugraha
  • 105
  • 8
  • 1
    https://stackoverflow.com/questions/57330766/how-to-get-data-from-any-asynchronous-operation-in-android/57330767#57330767 check my answer here if you want some ways to deal with this – a_local_nobody Aug 02 '19 at 17:19

4 Answers4

1

The answer is simple, you declared the checkCode variable globally and it doesn't have any value. so it will be null value and this value toasted there. But while OnSuccessListener executing its value will be assigned by the code checkCode = (String) d.get("kode");, so you get 1111 as its value.

Shalu T D
  • 3,921
  • 2
  • 26
  • 37
  • https://stackoverflow.com/questions/57330766/how-to-get-data-from-any-asynchronous-operation-in-android/57330767#57330767 I made this as easy reference to others in future :) – a_local_nobody Aug 02 '19 at 17:22
1

The code inside onSuccess(QuerySnapshot queryDocumentSnapshots){} is an Asynchronous Callback see this answer for an explanation because the call to Firebasemay take some time to complete. Because of this the line Toast.makeText(MainActivity.this, "From outside : "+checkCode, Toast.LENGTH_LONG).show(); will always execute before the callback does.

Ivan Wooll
  • 4,145
  • 3
  • 23
  • 34
  • Thank you, i little bit understand about it now. But is there is a way to get the value for it? – aldi nugraha Aug 02 '19 at 16:25
  • https://stackoverflow.com/questions/57330766/how-to-get-data-from-any-asynchronous-operation-in-android/57330767#57330767 hopefully this helps others in future – a_local_nobody Aug 02 '19 at 17:22
1

To transform QuerySnapshot to list of your objects use:

querySnapshot.toObjects(YourObject.class)

The line with Tost FromOutside is triggered before assigning value to the checkCode because the query to firebase is asynchronous. It is the reason that FromOutside is null.

Artur Gniewowski
  • 470
  • 7
  • 17
  • i made this as an easy reference for these types of problems in future https://stackoverflow.com/questions/57330766/how-to-get-data-from-any-asynchronous-operation-in-android/57330767#57330767 – a_local_nobody Aug 02 '19 at 17:35
1

You are making an asynchronous call to Firestore. OnSuccessListener's onSuccess() method is called when data is retrieved, after you showed your Toast while checkCode is still null. You can move toast inside onSuccess() or just use Log to print to console.

Mehmed
  • 2,880
  • 4
  • 41
  • 62
  • I want to save the value, not print it, can Log do that? – aldi nugraha Aug 02 '19 at 16:02
  • What do you mean by saving? If you have a function `a()` that needs `checkCode` to run, you can call it after you assign value to `checkCode` in `onSuccess()`. – Mehmed Aug 02 '19 at 16:23
  • What i mean by saving is that i need to have the value from 'onSuccess()' and use it. Im sorry, i cant explain ti very well, but what i want to do is this: I want to run the Toast 'From outside; and have the value of 1111 and not 'null'. – aldi nugraha Aug 02 '19 at 16:33
  • 1
    I get it but that's not possible, your logic should continue from `onSuccess()`. Or you can switch to MVP or MVVM pattern for a more decent structure. – Mehmed Aug 02 '19 at 16:50
  • so that why i cant get an answer in a few day, it just impossible. Thanks anyway. – aldi nugraha Aug 02 '19 at 16:56
  • And 1 more question. Let said i use my logic on `onSucces()` and the do some thing like `setText`, it still Asynchronous Callback and making `getText` not possible right? – aldi nugraha Aug 02 '19 at 17:03
  • 1
    @Mehmed i made an answer specifically for these types of questions now, hopefully it helps others in future :D https://stackoverflow.com/questions/57330766/how-to-get-data-from-any-asynchronous-operation-in-android/57330767#57330767 – a_local_nobody Aug 02 '19 at 17:21
  • 1
    @aldinugraha Your Firestore call is done in another thread (thus without blocking UI) and the result is passed over to UI thread (main thread in Android) when the response is ready via `onSuccess()`. Therefore, you should be able to manipulate your Views in `onSuccess()`. But if you `setText()` inside onSuccess but try to `getText()` before `onSuccess()` is called, you will not get your text properly, as you get null on the outer Toast. – Mehmed Aug 02 '19 at 23:22