0

I have an Android Fragment class that has a method to write something on an external firebase database after a button is clicked.

public class FR_Fragment extends Fragment implements View.OnClickListener {

    public void onClick(View view) {
        boolean writingSuccessfull = false;
        boolean writingNotSuccessfull = false;
        firebase_DB.child(id).setValue(currentOrder).addOnCompleteListener(new OnCompleteListener<Void>() {

            @Override
            public void onComplete(@NonNull Task<Void> task) {
                if (task.isSuccessful()) {
                    writingSuccessfull = true;
                    writingNotSuccessfull = false;
                    Log.e("dbTAG",  "Data successfully written.");
                }
                else {
                    writingSuccessfull = false;
                    writingNotSuccessfull = true;
                    Log.e("dbTAG", task.getException().getMessage());
                }
            }
        });
    }
}

However, I somehow can't access the boolean variables writingSuccessfull and writingNotSuccessfull and that I define in the method onClick in the OnCompleteListener. With the shown code I get an error "Variable 'writingSuccessfull' is accessed from within inner class, needs to be final or effectively final"

When I let Android Studio fix this problem the code looks like this:

public class FR_Fragment extends Fragment implements View.OnClickListener {

    public void onClick(View view) {
        final boolean[] writingSuccessfull = { false };
        final boolean[] writingNotSuccessfull = { false };
        firebase_DB.child(id).setValue(currentOrder).addOnCompleteListener(new OnCompleteListener<Void>() {

            @Override
            public void onComplete(@NonNull Task<Void> task) {
                if (task.isSuccessful()) {
                    writingSuccessfull[0] = true;
                    writingNotSuccessfull[0] = false
                    Log.e("dbTAG",  "Data successfully written.");
                }
                else {
                    writingSuccessfull[0] = false;
                    writingNotSuccessfull[0] = true
                    Log.e("dbTAG", task.getException().getMessage());
                }
            }
        });
    }
}

Now I can execute the code, but the values of the booleans do not change, even if the code inside the listener is executed. I also tried it without the "final" before the boolean variables. But this did not change anything. I can't modify the boolean variables inside this listener. But this is something that I need to do because I would like to know whether the data was written successfully into the database.

Any idea why I get this problem and how to solve it? I'll appreciate every comment.

Update: Here is the updated code with volatile and AtomicBooleas:

public class FR_Fragment extends Fragment implements View.OnClickListener {
    private volatile AtomicBoolean writingOrderToTheDatabaseWasSuccessful;
    private volatile AtomicBoolean writingOrderToTheDatabaseWasNotSuccessful;
...
public void onClick(View view) {

        int internalCounterAttempsWriteDataInTheFBDatabase =0;
        writingOrderToTheDatabaseWasSuccessful = new AtomicBoolean (false);
        writingOrderToTheDatabaseWasNotSuccessful = new AtomicBoolean (false);


        while(writingOrderToTheDatabaseWasSuccessful.get() == false && writingOrderToTheDatabaseWasNotSuccessful.get()==false) {
            internalCounterAttempsWriteDataInTheFBDatabase++;
            Log.e("LogTag", "internalCounterAttempsWriteDataInTheFBDatabase: " +internalCounterAttempsWriteDataInTheFBDatabase );
            Log.e("LogTag", "writingOrderToTheDatabaseWasSuccessful: " + writingOrderToTheDatabaseWasSuccessful.get());
            Log.e("LogTag", "writingOrderToTheDatabaseWasNotSuccessful: " + writingOrderToTheDatabaseWasNotSuccessful.get());


            DatabaseReference rootRef = FirebaseDatabase.getInstance("https://drink-server-db-default-rtdb.europe-west1.firebasedatabase.app").getReference();
            DatabaseReference ordersRef = rootRef.child("orders");
            String id =...;
            FirebaseDBItem_Order currentOrder = ...;

            ordersRef.child(id).setValue(currentOrder).addOnCompleteListener(new OnCompleteListener<Void>() {
                @Override
                public void onComplete(@NonNull Task<Void> task) {
                 if (task.isSuccessful()) {
                      writingOrderToTheDatabaseWasSuccessful.set(true);
                      writingOrderToTheDatabaseWasNotSuccessful.set(false);
                      Log.e("dbTAG",  "Data successfully written.");
                      Log.e("LogTag", "Listener: writingOrderToTheDatabaseWasSuccessful: " + writingOrderToTheDatabaseWasSuccessful.get());
                      Log.e("LogTag", "Listener: writingOrderToTheDatabaseWasNotSuccessful: " + writingOrderToTheDatabaseWasNotSuccessful.get());

                 } else {

                    Log.e("dbTAG", task.getException().getMessage());
                 }
                    }//end method onComplete
                });//end addOnCompleteListener
            if (internalCounterAttempsWriteDataInTheFBDatabase >=10) {
                writingOrderToTheDatabaseWasNotSuccessful.set(true);
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }//end while loop
        Log.e("LogTag", "EndWhile: writingOrderToTheDatabaseWasSuccessful: " + writingOrderToTheDatabaseWasSuccessful.get());
        Log.e("LogTag", "EndWhile: writingOrderToTheDatabaseWasNotSuccessful: " + writingOrderToTheDatabaseWasNotSuccessful.get());


        //Show a toast about the order
        if (writingOrderToTheDatabaseWasSuccessful.get() ==true) {
            int duration = Toast.LENGTH_LONG;
            Toast toast = Toast.makeText(getContext(), getString(R.string.message_orderSubmittedSuccessfully), duration);
            toast.setGravity(Gravity.CENTER, 0, 0);
            toast.show();
        }

        if (writingOrderToTheDatabaseWasNotSuccessful.get() ==true) {
            int duration = Toast.LENGTH_LONG;
            Toast toast = Toast.makeText(getContext(), getString(R.string.message_orderSubmittedNotSuccessfully), duration);
            toast.setGravity(Gravity.CENTER, 0, 0);
            toast.show();
        }



        Navigation.findNavController(...);

    }//end method onClick

}//end class

The problem is the asnychronous call of the onComplete method. The code to change the booleans is not called immediately as it is in the onComplete method that is called asynchronously. This means in my example that the code in the onComplete method is just called after the 10 while-loop iterations and not during the loop as intended. The biggest question now is how to call any code in the onComplete method during the while loop.

Update: Here is the (relevant) output from logcat when running the code:

E/LogTag: internalCounterAttempsWriteDataInTheFBDatabase: 1
    writingOrderToTheDatabaseWasSuccessful: false
    writingOrderToTheDatabaseWasNotSuccessful: false
E/LogTag: internalCounterAttempsWriteDataInTheFBDatabase: 2
E/LogTag: writingOrderToTheDatabaseWasSuccessful: false
    writingOrderToTheDatabaseWasNotSuccessful: false
E/LogTag: internalCounterAttempsWriteDataInTheFBDatabase: 3
    writingOrderToTheDatabaseWasSuccessful: false
    writingOrderToTheDatabaseWasNotSuccessful: false
E/LogTag: internalCounterAttempsWriteDataInTheFBDatabase: 4
E/LogTag: writingOrderToTheDatabaseWasSuccessful: false
    writingOrderToTheDatabaseWasNotSuccessful: false
E/LogTag: internalCounterAttempsWriteDataInTheFBDatabase: 5
E/LogTag: writingOrderToTheDatabaseWasSuccessful: false
    writingOrderToTheDatabaseWasNotSuccessful: false
E/LogTag: internalCounterAttempsWriteDataInTheFBDatabase: 6
    writingOrderToTheDatabaseWasSuccessful: false
    writingOrderToTheDatabaseWasNotSuccessful: false
E/LogTag: internalCounterAttempsWriteDataInTheFBDatabase: 7
E/LogTag: writingOrderToTheDatabaseWasSuccessful: false
    writingOrderToTheDatabaseWasNotSuccessful: false
E/LogTag: internalCounterAttempsWriteDataInTheFBDatabase: 8
    writingOrderToTheDatabaseWasSuccessful: false
E/LogTag: writingOrderToTheDatabaseWasNotSuccessful: false
E/LogTag: internalCounterAttempsWriteDataInTheFBDatabase: 9
    writingOrderToTheDatabaseWasSuccessful: false
    writingOrderToTheDatabaseWasNotSuccessful: false
E/LogTag: internalCounterAttempsWriteDataInTheFBDatabase: 10
E/LogTag: writingOrderToTheDatabaseWasSuccessful: false
E/LogTag: writingOrderToTheDatabaseWasNotSuccessful: false
E/LogTag: EndWhile: writingOrderToTheDatabaseWasSuccessful: false
    EndWhile: writingOrderToTheDatabaseWasNotSuccessful: true
E/dbTAG: Data successfully written.
E/LogTag: Listener: writingOrderToTheDatabaseWasSuccessful: true
    Listener: writingOrderToTheDatabaseWasNotSuccessful: false
E/dbTAG: Data successfully written.
E/LogTag: Listener: writingOrderToTheDatabaseWasSuccessful: true
    Listener: writingOrderToTheDatabaseWasNotSuccessful: false
E/dbTAG: Data successfully written.
E/LogTag: Listener: writingOrderToTheDatabaseWasSuccessful: true
    Listener: writingOrderToTheDatabaseWasNotSuccessful: false
E/dbTAG: Data successfully written.
E/LogTag: Listener: writingOrderToTheDatabaseWasSuccessful: true
E/LogTag: Listener: writingOrderToTheDatabaseWasNotSuccessful: false
E/dbTAG: Data successfully written.
E/LogTag: Listener: writingOrderToTheDatabaseWasSuccessful: true
    Listener: writingOrderToTheDatabaseWasNotSuccessful: false
E/dbTAG: Data successfully written.
E/LogTag: Listener: writingOrderToTheDatabaseWasSuccessful: true
    Listener: writingOrderToTheDatabaseWasNotSuccessful: false
E/dbTAG: Data successfully written.
E/LogTag: Listener: writingOrderToTheDatabaseWasSuccessful: true
    Listener: writingOrderToTheDatabaseWasNotSuccessful: false
E/dbTAG: Data successfully written.
E/LogTag: Listener: writingOrderToTheDatabaseWasSuccessful: true
E/LogTag: Listener: writingOrderToTheDatabaseWasNotSuccessful: false
E/dbTAG: Data successfully written.
E/LogTag: Listener: writingOrderToTheDatabaseWasSuccessful: true
E/LogTag: Listener: writingOrderToTheDatabaseWasNotSuccessful: false
E/dbTAG: Data successfully written.
E/LogTag: Listener: writingOrderToTheDatabaseWasSuccessful: true
    Listener: writingOrderToTheDatabaseWasNotSuccessful: false

The result is that the item is saved 10 times in the firebase database. What I want is to try to store the item once in the firebase db. If this is successfull, the loop should stop and there should be a toast telling that it was successfull. If it was not successfull the loop should try it 10 times (with a delay of 1 second). If even after 10 attemps the item could not be stored in the firebase database, the loop should be stopped and there should be a toast message telling that the item could not be stored.

VanessaF
  • 515
  • 11
  • 36
  • Thanks for your answer a_local_nobody. Is there not a more direct way of doing this without the interface and the callback functions? Basically I only want to modify the values of a boolean variable. – VanessaF Sep 28 '21 at 11:03
  • Thanks for your answer a_local_nobody. I can't do the things in the scope because basically I have a loop that tries to send the data multiple times to firebase if the writing was not successfull. So I need this information of the boolean values to stop the loop of sending. You wrote "you ARE changing the boolean variables, but they're not changed by the time you're trying to use them"--> Can I just pause the current Thread such that the variables are changed before I use them or is there another way of telling Java to wait some time before using those variables? – VanessaF Sep 28 '21 at 11:26
  • Thanks for your answer a_local_nobody and your effort. I really appreciate it. Well, when using Firebase DB you need a Internet connection. Sometime my Wireless Lan network does not work for a couple of seconds and then it works again. Because of this I would like to try to send it 5 times with a delay of 2 seconds and pause the UI thread in between. If after those 5 tries the information is not written, a Toast should tell the user/customer to ask for help. If I ask the user to retry as you suggested, he or she could get mutiple errors before a successfull try. – VanessaF Sep 28 '21 at 11:58
  • @a_local_nobody: You wrote "you ARE changing the boolean variables, but they're not changed by the time you're trying to use them"--> Can I just pause the current Thread such that the variables are changed before I use them or is there another way of telling Java to wait some time before using those variables? Or do you think that static boolean variables can be used for my purpose? – VanessaF Sep 28 '21 at 19:04
  • @a_local_nobody: Any comments to my last comment? I'll highly appreciate every further comment from you. – VanessaF Sep 29 '21 at 20:19
  • @a_local_nobody: Thanks for your answer and effort. I commented on the live data approach below your answer. Maybe just comming back to my idea of just delaying the current Thread such that the variables are changed before I use them. Is thsi possible according to your point of view or not? – VanessaF Sep 30 '21 at 07:54
  • You could use an `AtomicBoolean` instead of a `boolean[]`, for I think that's neater. Regarding the booleans not being updated – you may want to read about [the `volatile` keyword](https://stackoverflow.com/questions/106591/what-is-the-volatile-keyword-useful-for). – MC Emperor Oct 01 '21 at 07:48
  • @MCEmperor: Thanks for your answer. Can I use only the AtomicBoolean without the volatile keyword or do I have to use it in combination? – VanessaF Oct 01 '21 at 08:32
  • You *have* to use `volatile` in order to make sure that the variable updates are visible to all threads. `AtomicBoolean` instead of `boolean[]` is just preference of style. – MC Emperor Oct 01 '21 at 08:37
  • You may want to read [more about `volatile`](https://www.baeldung.com/java-volatile). – MC Emperor Oct 01 '21 at 08:45
  • @MCEmperor: Thanks for your comments. I will try to use volatile and see if it works or not in my example. – VanessaF Oct 01 '21 at 09:00
  • @MCEmperor: I tried your suggested solution but unfortunately it does not work. I think the problem is that the listener command `firebase_DB.child(id).setValue(currentOrder).addOnCompleteListener(new OnCompleteListener() {` is executed asychnchronosly. Because of that everything that comes after this command will be executed even before that command. So the changes made by the listener will not be made immediately but after the higher-level method has been executed. – VanessaF Oct 02 '21 at 08:37
  • @MCEmperor: I updated the code that I use now in my answer. From the logTags that I set I can see that the code inside the listener is just exectuted after the while loop and not during the while loop as I intended – VanessaF Oct 02 '21 at 08:45
  • @MCEmperor: Any comments to my last comments about the problems when using your suggested approach? I'll highly appreciate every further comment from you. – VanessaF Oct 04 '21 at 07:34
  • Well, indeed, you set two variables (`writingSuccessfull` and `writingNotSuccessfull`) to a certain value within the `onComplete` method, but then you read those values *outside* of the `onComplete` method. You need to move your code showing the Toasts to inside the `onComplete` method. – MC Emperor Oct 04 '21 at 08:26
  • @MCEmperor: Thanks MC for your answer and effort. I have 3 remarks. 1) I want to have different tries writing the data into the db (5 tries with a delay of 2 sec). So do I have to put the loop also inside the oncreate method? 2) if I put the code of the toas inside the onCreate method I could have done this before even without the AtomicBoolean and the volatile variables. What do I gain from the Atomic and volatile booleans then? 3) The general problem is that the onCreate methods is weirdly executed asychronously. I have to find a way to write boolean variables in asychronous code. – VanessaF Oct 04 '21 at 10:32
  • @MCEmperor: Any comments to my last comment? I'll highly appreciate any further comment from you. The big problem is that the method onComplete is unfortunately executed asynchronously and I don't know how to change the booleans in asynchronously exectued methods. – VanessaF Oct 06 '21 at 08:04
  • @MCEmperor: Any comments to my last comments? I'll highly appreciate any further comment from you. – VanessaF Oct 07 '21 at 08:12
  • @MCEmperor Any comments to my last comments? I'll highly appreciate any further comment from you as I tried many different approaches without any success. Do you have any further idea? – VanessaF Oct 08 '21 at 10:48
  • Well, your code is fairly difficult to reason about, because your indentation is poor and the code contains a lot of surplus statements. Please try to narrow your code down, so it is better readable. You could also try to use `firebase_DB.child(id).setValue(currentOrder, new OnCompleteListener<>() { ... })`. You also need to provide a little more information. You say "even if the code inside the listener is executed", but does the output confirm that? – MC Emperor Oct 11 '21 at 08:53
  • Thanks for your answer MC Emperor. I slightly changed the code hoping that you can now understand it better. Opposed to what you mentioned, there are no surplus statements in it. All of them are solely related to my problem (or to get information about it). I also tried what you suggested with `firebase_DB.child(id).setValue(currentOrder, new OnCompleteListener<>() { ... })` but this leads to the following error message "Class 'Anonymous class derived from OnCompleteListener' must either be declared abstract or implement abstract method 'onComplete(Task)' in 'OnCompleteListener'" – VanessaF Oct 16 '21 at 09:34
  • @MCEmperor: Any comments on my last comment MC. I'll highly appreciate every further comment from you. – VanessaF Oct 20 '21 at 16:45
  • Well, having a variable for both writingSuccessfull and writingNotSuccessfull is what I would call "surplus". – MC Emperor Oct 21 '21 at 09:39
  • Further, you haven't answered my question: You say "even if the code inside the listener is executed", but does the output confirm that? You need to provide more details. Do the values of your *writing (un)successful* variables ever update? – MC Emperor Oct 21 '21 at 09:41
  • @MCEmperor: Thanks for your comment. I added the output of the code. There you can see the values of the boolean variables for each iteration. – VanessaF Oct 21 '21 at 16:51
  • @MCEmperor: Any further idea? Or do you think that what I want to do (try to write something to the firebase database several times if it is not successfull) is just not possible? – VanessaF Oct 23 '21 at 14:04

2 Answers2

0

maybe you should not use boolean, you can use return method when the task succeeded and execute setValue() inside while(true) or for loop so when the task is successful the loop will stop working or when the loop reached to her limit. like this:

for (int i=0;i<5;i++) {
        firebase_DB.child("id").setValue("currentOrder").addOnCompleteListener(new OnCompleteListener<Void>() {
            @Override
            public void onComplete(@NonNull Task<Void> task) {
                if (task.isSuccessful()) {
                    Log.e("dbTAG", "Data successfully written.");
                    return;

                }
            }
        });
    }
    Toast.makeText(MainActivity.this, "ask for help",Toast.LENGTH_LONG);
Roy Katz
  • 26
  • 2
  • Thanks for your answer Roy. I think with your suggested code the Toast at the end will always be displayed `Toast.makeText(MainActivity.this, "ask for help",Toast.LENGTH_LONG);`. This is not what I want. Depending on whether the writing was successfull or not the toast should be displayed. Further, after the loop there is still some code that should be executed when clicking on a button. – VanessaF Sep 28 '21 at 19:03
  • Any comments to my last comment? I'll highly appreciate every further comment from you. – VanessaF Sep 29 '21 at 20:19
  • 1
    @Roy Using `return` there absolutely does not make sense, as the body of the method ends there anyway. – MC Emperor Oct 01 '21 at 07:44
0

Create a custom class that extends AndroidViewModel

        public class MyViewModel extends AndroidViewModel{

        private MutableLiveData<Boolean> writingSuccessful=new MutableLiveData<>();

            public MyViewModel(@NonNull Application application)
            {
                // you can do any other stuff here if you want
               }


            public void setBooleanWritingSuccessful(Boolean b)
            {
                writingSuccessful.setValue(b);
             }


            public LiveData<Boolean> getBooleanWritingSuccessful()
            {
               return writingSuccessful;
             }



        }

And then use this custom viewmodel class in your fragment for observing changes to the values

    public class FR_Fragment extends Fragment implements View.OnClickListener {
       

       private MyViewModel myViewModel;
       private boolean writingSuccessfull= false;



                @Override
                public void onCreate(Bundle savedInstanceState)
                {
                    // your stuffs

                    // initialize viewmodel

                    myViewModel=new ViewModelProvider(this,ViewModelProvider.AndroidViewModelFactory.getInstance(getActivity().getApplication())).get(MyViewModel.class);




                }





                @Override
                public void onCreateView(LayoutInflater inflater, ViewGroup container,
                                             Bundle savedInstanceState)
                {
                    
                        
                        // set your viewmodel for observing the changes in boolean values.

                        myViewModel.getBooleanWritingSuccessful().observe(getViewLifecycleOwner(),new Observer<Boolean>(){

                            @Override
                            public void onChanged(Boolean b)
                            {

                                // update your writingSuccessful variable here.
                                writingSuccessfull=b;

                            }
                        });



                }



    // In onClick update your viewmodel's mutablelivedata;

                    public void onClick(View view) {
                    ...

                    firebase_DB.child(id).setValue(currentOrder).addOnCompleteListener(new OnCompleteListener<Void>() {
                                     @Override
                                        public void onComplete(@NonNull Task<Void> task) {
                                         if (task.isSuccessful()) {


                                             //writingSuccessfull=true;
                                             //writingNotSuccessfull= false;

                                             //update the viewmodel's mutableLiveData 
                                             myViewModel.setBooleanWritingSuccessful(true);



                                             Log.e("dbTAG",  "Data successfully written.");

                                            } else {


                                             //writingSuccessfull=false;
                                             //writingNotSuccessfull= true;



                                             //update the viewmodel's mutableLiveData 
                                             myViewModel.setBooleanWritingSuccessful(false);


                                             Log.e("dbTAG", task.getException().getMessage());
                                            }
                                        }
                                });


                    }




                }

This is a simple snippet of the MVVM Architecture. Hope now it works. Thank you.

Preetam Pal
  • 256
  • 2
  • 7
  • Thanks Preetam for your answer. Actually I already declared the variables as instance variables on a class level (see my updated code). I even declared them as volatile and AtomicBoolean like "MCEmperor" suggested. But this did not solve the problem unfortunately. – VanessaF Oct 03 '21 at 07:18
  • Try using MutableLiveData and you can use setValue() or postValue() for updating its values. Hope that could help. – Preetam Pal Oct 03 '21 at 08:03
  • Thanks Preetam for your answer and effort. I really appreciate it. How can I use MutableLiveData in my example? Further, I think the problem is that the listener command `firebase_DB.child(id).setValue(currentOrder).addOnCompleteListener(new OnCompleteListener() {` is executed asychnchronosly. Because of that everything that comes after this command will be executed even before that command. So the changes made by the listener will not be made immediately but after the higher-level method has been executed. How can MutableLiveData help with that problem? – VanessaF Oct 03 '21 at 08:13
  • My answer has been updated. Please check and try if its working. – Preetam Pal Oct 03 '21 at 10:02
  • Thanks Preetam for your answer. When I use your suggested code I get a lot of errors: 1) In the constructor of MyViewModel "There is no default constructor available in 'androidx.lifecycle.AndroidViewModel'" 2) In the line `myViewModel.getBooleanWritingSuccessful.observe(getViewLifecycleOwner,new Observer(){` ... "Cannot resolve symbol 'getBooleanWritingSuccessful" and in the same line 3) "Cannot resolve symbol 'getViewLifecycleOwner". – VanessaF Oct 04 '21 at 07:31
  • Further more I have 2 comment: 4) What shall I do where you write " // update your writingSuccessful variable here." 5) In the onClick method the boolean should not be sent immediately to false if it does not succeed in writing to the database. There is a loop that tries to do this 5 time with a delay of 2 seconds. – VanessaF Oct 04 '21 at 07:33
  • its getViewLifecycleOwner() , extremely sorry about that. – Preetam Pal Oct 04 '21 at 12:41
  • Also as you are extending AndroidViewModel, so you have to provide a default constructor. So just follow context actions provided by android studio, it will create a default constructor for you. – Preetam Pal Oct 04 '21 at 12:42
  • also its myViewModel.getBooleanWritingSuccessful(), and not myViewModel.getBooleanWritingSuccessful, my mistake again. – Preetam Pal Oct 04 '21 at 12:48
  • "5) In the onClick method ....", Actually you can do anything you want as you have now view model and the observer. In your onClickView() method, just check all the areas where your boolean value is getting updated or might get updated in future. In all these places, you just call "myViewModel.setBooleanWritingSuccessful(true or false depending on you)". As there is observer in the onCreatView() method of fragment. It will automatically call onChanged(Boolean b){} method and there in the onChanged() method you place your instance variable "writingSuccessful" and update it. – Preetam Pal Oct 04 '21 at 12:59
  • Thanks for your answers and effort. I really appreciate it. I tried your suggested code but it did not change anything. The big problem is that the method `onComplete` is unfortunately executed asynchronously. This means that my programm first runs the loop 10 times without executing the `onComplete` method and then afterwards executes the `onComplete` method. This is the basic problem that I have been facing from the very beginning and the reason why I asked this question. – VanessaF Oct 06 '21 at 08:03
  • Any comments to my last comments? I'll highly appreciate any further comment from you. – VanessaF Oct 07 '21 at 08:13
  • The solution that I suggested is basically based on the observer( that has been set in the onCreateView() method) and updates in the value of MutableLiveData that gets updated when you call "myViewModel.setBooleanWritingSuccessful(false or true);". It should work well even in the asynchronous operations as you are observing the changes in the values with the help of observer. – Preetam Pal Oct 07 '21 at 14:35
  • But as you said it didn't work that means either the observer is not perfectly working. Maybe you can call "myViewModel.getBooleanWritingSuccessful().observe(getViewLifecycleOwner(),new Observer(){ @Override public void onChanged(Boolean b) { // update your writingSuccessful variable here. writingSuccessfull=b; } });" again in the onComplete method. – Preetam Pal Oct 07 '21 at 14:39
  • Note in onComplete, first update your viewmodel' s MutableLiveData by calling "myViewModel.setBooleanWritingSuccessful(true or false depending on your situation);" and then call the above stated method (stated in above comment). Give one more try, else we will search for an alternative. – Preetam Pal Oct 07 '21 at 14:39
  • Thanks Preetam for your answer. As expected it does not work. First of all I get an error " java.lang.IllegalStateException: Can't access the Fragment View's LifecycleOwner when getView() is null i.e., before onCreateView() or after onDestroyView()". Moreover, and more importantly, the method is still called in an asynchronous way. The boolean variables are changed but only after the outer loop is exectued several times. The fundamental problem is the onComplete method that is exectued in an asynchronous way meaning that the code inside it is not directly executed. – VanessaF Oct 08 '21 at 07:39
  • Maybe you are doing some mistake that I can't figure out. Viewmodel's observers are generally set in the onCreateView() method. If you could update this question and add your attempt with this viewmodel's code, I would to try to find if there is any wrong in this code. – Preetam Pal Oct 09 '21 at 06:31
  • The same type of problem occurred with me when I was making string request using Volley library for getting the string responses to the requests made to the api. For this I created a method of return type LiveData and in that method I created a MutableLiveData and updated the values of mutableLiveData using postValue() in the onResponse() and other inner class methods and finally returned this mutableLiveData. I called this method in the fragment or activity using my viewModel and observe the changes in the value returned (liveData) and finally update my instance variables. – Preetam Pal Oct 09 '21 at 06:43
  • Thanks for your answer Preetam. The problem is not the mutable live data but the asnychronous call of the onComplete method. The code to change the mutable live data is not called immediately as it is in the onComplete method that is called asynchronously. This means in my example that the code in the onComplete method is just called after the loop and not during the loop as intended. The biggest question now is how to call any code in the onComplete method during the while loop – VanessaF Oct 09 '21 at 14:26
  • Thanks for your answers. Unfortunately your suggested live data approach does not work and can't fix the problem. Do you have any other idea how to solve the problem? – VanessaF Oct 16 '21 at 09:36
  • Pardon for late reply, I tried to find some alternative approach but couldn't get any till now. – Preetam Pal Oct 19 '21 at 15:54
  • If possible try out creating a container class for your boolean variable. Instantiate this class in your fragment and try changing the value of this container in your inner anonymous classes. I found it here- https://stackoverflow.com/questions/5977735/setting-outer-variable-from-anonymous-inner-class – Preetam Pal Oct 19 '21 at 16:12
  • Thanks Preetam for your answer and effort. I am quite sure that this will not work as the problem is that the onComplete method is called asychronously. Maybe it is just generally not possible to do what I inted to do which is kind of strange but it seems to be like this and I have to find another approach – VanessaF Oct 19 '21 at 18:03