Android for循环不循环?火基

Android for循环不循环?火基,android,for-loop,firebase,firebase-realtime-database,Android,For Loop,Firebase,Firebase Realtime Database,我对以下代码有一个问题:我不明白为什么我的for循环在调用if(gameExists[0]==false){…之前不循环 Button playButton = (Button) findViewById(R.id.play_button); playButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) {

我对以下代码有一个问题:我不明白为什么我的for循环在调用
if(gameExists[0]==false){…
之前不循环

    Button playButton = (Button) findViewById(R.id.play_button);
    playButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

            user = mFirebaseAuth.getCurrentUser();

            final String gameCateg = String.valueOf(categorySelected[0]);

            DatabaseReference allExistingGamesToMatchKeys = mFirebaseDatabase.getReference().child("gamestomatchkeys");
              allExistingGamesToMatchKeys.addListenerForSingleValueEvent(new ValueEventListener() {
                @Override
                public void onDataChange(DataSnapshot dataSnapshot) {
                    final boolean[] gameExists = {false};
                    Log.d("gameExists before loop ", String.valueOf(gameExists[0]));

                    for (DataSnapshot postSnapshot: dataSnapshot.getChildren()) {
                        final String currentKey = postSnapshot.getKey();
                        //check player 2 is not the same as player 1 so that we don't match the same player
                        if(gameCateg.equals(postSnapshot.getValue().toString())){
                            mFirebaseDatabase.getReference().child("games").child(currentKey).child("player1").addListenerForSingleValueEvent(new ValueEventListener() {
                                @Override
                                public void onDataChange(DataSnapshot dataSnapshot) {
                                    String namePlayer1 = dataSnapshot.getValue(String.class);
                                    if(!(user.getUid().toString().equals(namePlayer1))){
                                        mFirebaseDatabase.getReference().child("gamestomatchkeys").child(currentKey).removeValue();
                                        mFirebaseDatabase.getReference().child("games").child(currentKey).child("player2").setValue(user.getUid());
                                    gameExists[0] = true;
                                    Log.d("gameExists in for loop ", String.valueOf(gameExists[0]));


                                    Intent intent = new Intent(getApplicationContext(), Game.class);
                                        intent.putExtra("gameIdKey", currentKey);
                                        startActivity(intent);
                                    }
                                }

                                @Override
                                public void onCancelled(DatabaseError databaseError) {
                                }
                            });
                            break;
                        }
                    }
                    if (gameExists[0] == false){
                        Log.d("gameExists in if", String.valueOf(gameExists[0]));
这是我在日志中得到的信息,顺序如下:

循环之前存在游戏:false

游戏存在于if:false中

游戏存在于for循环中:true

我不明白为什么我会

游戏存在于if:false中

以前

游戏存在于for循环中:true

我希望在
之前调用并完全循环我的循环如果(gameExists[0]==false){…
,我应该修改什么

谢谢!

这是因为“gameExists in for loop”实际上不在for循环中,而是在for循环中创建的回调中

                       mFirebaseDatabase.getReference().child("games").child(currentKey).child("player1").addListenerForSingleValueEvent(new ValueEventListener() {
                            @Override
                            public void onDataChange(DataSnapshot dataSnapshot) {
                                String namePlayer1 = dataSnapshot.getValue(String.class);
                                if(!(user.getUid().toString().equals(namePlayer1))){
                                    mFirebaseDatabase.getReference().child("gamestomatchkeys").child(currentKey).removeValue();
                                    mFirebaseDatabase.getReference().child("games").child(currentKey).child("player2").setValue(user.getUid());
                                gameExists[0] = true;
                                Log.d("gameExists in for loop ", String.valueOf(gameExists[0]));


                                Intent intent = new Intent(getApplicationContext(), Game.class);
                                    intent.putExtra("gameIdKey", currentKey);
                                    startActivity(intent);
                                }
                            }

                            @Override
                            public void onCancelled(DatabaseError databaseError) {
                            }
                        });
在这里,您正在创建ValueEventListener的新实例,并覆盖其中的方法。在实例化时,您没有在这些方法中执行代码。只要ValueEventListener决定调用onDataChange()方法,就会调用这些代码

我不完全确定这个物体是什么,或者它是如何工作的:

mFirebaseDatabase.getReference().child("games").child(currentKey).child("player1")
但如果我是你,我会先看看是否可以从中获得一个DataSnapshot,然后在你想在监听器之外执行的任何代码上使用该快照

如果非要我猜的话,可能有一种方法如下:

mFirebaseDatabase.getReference().child("games").child(currentKey).child("player1").getDataSnapshot();
然后将所有代码从onDataChange()内部复制到侦听器外部


(我不知道该方法是否存在,但我假设有某种方法可以获取当前的DataSnapshot)

为了简单起见,Firebase数据库请求在代码流之外。请看以下内容:

// here is first point 
allExistingGamesToMatchKeys.addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        // here is second point
    }
    ...
}
// here is third point
上面的示例将这样执行

-->第一点-->第三点

那么第二个点在哪里?Firebase从在线数据库获取数据时,将执行第二个点,因此它在流程之外(但大多数情况下,它将在第三个点之后执行)

总之,如果您需要在Firebase请求完成后执行一些代码,请将其放入
onDataChange()

你可以参考一下


我不确定是否理解:当侦听器附加到我的引用时调用onDataChange(),这是在我的for循环的开始和结束括号之间完成的。那么为什么它不应该是“循环的”?我需要在我的引用上有一个侦听器来获取值,没有“.getDataSnapshot()之类的内容。在这个侦听器中,我需要使用从for循环中获取的变量“currentKey”。没有
getDataSnapshot()
方法,如果要获取值,只能是
addListenerForSingleValueEvent
addValueEventListener()
谢谢,我了解它是如何工作的。在onDataChange中,我想调用我的“if”只有在我的列表被循环之后。所以我想我需要一个条件来说明这一点,比如if(这是DataSnapshot列表中的最后一个元素)或者if(DataSnapshot列表中的下一个元素为null)。我尝试了一些事情,比如if(currentKey==mFirebaseDatabase.getReference().child(“gamesotchkeys”).limitToLast(1.toString())但是我没有得到我想要的。你知道如何创建这样一个条件吗?最简单的方法是创建一个
int
值,该值包含
dataSnapshot
来自
“gamesothitchkeys”
请求的计数,以及计数器的另一个int值。然后在
onDataChange
中创建
“games”
request,将计数器int乘以1。然后在相同的
onDataChange
的最后一部分,比较第一个int值和计数器。如果匹配,则到达末尾