如何在Java for Android中修改新创建的监听器中的外部布尔值

我有一个Android片段类,它有一个在单击按钮后在外部Firebase数据库上写入内容的方法。

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());
                }
            }
        });
    }
}
但是,我不知何故无法访问我在OnCompleteListener的onClick方法中定义的布尔变量writingSuccessfullwritingNotSuccessfull。在显示的代码中,我得到了一个错误&变量‘WritingSuccessFull’是从内部类内部访问的,需要是最终的或有效的最终的

当我让Android Studio解决此问题时,代码如下所示:

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());
                }
            }
        });
    }
}

现在我可以执行代码了,但是布尔值不会更改,即使执行了侦听器中的代码。我也尝试了一下,在布尔变量前没有加上&最终&。但这并没有改变任何事情。我不能修改此监听程序中的布尔变量。但这是我需要做的事情,因为我想知道数据是否已成功写入数据库。

知道我为什么会遇到这个问题吗?如何解决它?我将感谢您的每条评论。

更新:以下是更新后的代码,其中包含Volatile和AericBoolas:

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

问题在于onComplete方法的异步调用。更改布尔值的代码不会立即调用,因为它是在异步调用的onComplete方法中调用的。这意味着在我的示例中,onComplete方法中的代码是在10次While循环迭代之后调用的,而不是在循环期间调用的。现在最大的问题是如何在While循环期间调用onComplete方法中的任何代码。

更新:以下是运行代码时来自logcat的(相关)输出:

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

结果是该项在FireBase数据库中保存了10次。我想要的是尝试在Firebase数据库中存储该项目一次。如果这是成功的,循环应该停止,并且应该有一个祝酒词告诉它是成功的。如果不成功,则循环应尝试10次(延迟1秒)。如果尝试10次后仍无法将该项目存储在FireBase数据库中,则应停止循环,并且应显示一条吐司消息,告知无法存储该项目。


解决方案

创建扩展Android视图模型的自定义类

        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;
             }



        }

然后在片段中使用此自定义视图模型类来观察值的更改

    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());
                                            }
                                        }
                                });


                    }




                }

这是MVVM体系结构的一个简单片段。希望它现在起作用了。谢谢。

相关文章