有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

我有一个Android Fragment类,它有一个方法,可以在单击按钮后在外部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());
                }
            }
        });
    }
}

但是,我不知何故无法访问布尔变量writingSuccessfullwritingNotSuccessfull,以及我在OnCompleteListener中的方法onClick中定义的布尔变量。通过显示的代码,我得到一个错误“变量'writingSuccessfull'是从内部类中访问的,需要是final或有效final”

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

现在我可以执行代码了,但是布尔值不会改变,即使监听器中的代码被执行了。我还尝试了在布尔变量之前不使用“final”的方法。但这并没有改变任何事情。我无法修改此侦听器中的布尔变量。但这是我需要做的事情,因为我想知道数据是否已成功写入数据库

你知道我为什么会遇到这个问题以及如何解决吗?我将感谢你的每一句评论

更新:以下是使用volatile和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

问题是onComplete方法的asnychronous调用。更改布尔值的代码不会像在异步调用的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 db中存储该项一次。如果这是成功的,循环应该停止,应该有一个祝酒词告诉它是成功的。如果未成功,循环应尝试10次(延迟1秒)。如果即使在10次尝试之后,该项仍无法存储在firebase数据库中,则应停止循环,并出现toast消息,告知无法存储该项


共 (2) 个答案

  1. # 1 楼答案

    也许你不应该使用布尔值,你可以在任务成功时使用return方法,并在while(true)或for循环中执行setValue(),这样当任务成功时,循环将停止工作,或者当循环达到她的极限时。 像这样:

    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);
    
  2. # 2 楼答案

    创建扩展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;
                 }
    
    
    
            }
    

    然后在片段中使用这个自定义viewmodel类来观察值的变化

        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体系结构的一个简单片段。希望它现在能起作用。谢谢