从FirebaseDatabase获取的数据将显示在3个单独的AlertDialog中,而不是一个

时间:2016-12-30 19:49:22

标签: android firebase firebase-realtime-database android-arrayadapter alertdialog

我从FirebaseDatabase获取一些数据,然后将它们放入array,然后尝试在自定义List中的AlertDialog中显示它们}。

以下是代码:

query = mDatabase.child("child").child(anotherChild).child("yetAnotherChild");

uProfile.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        query.orderByChild("someChild").addChildEventListener(new ChildEventListener() {
            @Override
            public void onChildAdded(DataSnapshot dataSnapshot, String s) {
                if (dataSnapshot != null) {

                    Map<String, String> newD = (Map<String, String>) dataSnapshot.getValue();

                    ArrayList<String> l = new ArrayList<String>();
                    l.add(newD.get("lol").substring(30));

                    String names[] = l.toArray(new String[0]);

                    AlertDialog.Builder alertDialog = new AlertDialog.Builder(Activity.this);
                    LayoutInflater inflater = getLayoutInflater();
                    View convertView = inflater.inflate(R.layout.dialog_list, null);
                    alertDialog.setView(convertView);
                    alertDialog.setTitle("title");
                    ListView lv = (ListView) convertView.findViewById(R.id.lv);
                    ArrayAdapter<String> adapter = new ArrayAdapter<String>(getBaseContext(), android.R.layout.simple_list_item_1, names);
                    lv.setAdapter(adapter);

                    alertDialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialogInterface, int i) {

                        }
                    });

                    alertDialog.show();
                } else {
                    Toast.makeText(getBaseContext(), "NULLLLL", Toast.LENGTH_SHORT).show();
                }
            }

            ...
            ...
        });

    }
});

这是数据库结构:

app
 -child
   -anotherChild
     -yetAnotherChild
       -inaccessibleChild
         -someChild: "value"
         -lol: "value"

我无法使用valueEventListener(),因为我无法访问inaccessibleChild。这里的inaccessibleChild是跟随特定用户的其他用户的uid。我如何访问uid

问题是获取数据但是却没有显示在一个AlertDialog的列表中,而是在 3 中逐个显示strong>单独AlertDialog

这里出了什么问题?

请告诉我。

8 个答案:

答案 0 :(得分:3)

Firebase事务是异步的,因此在设置侦听器后会发生添加3个孩子的初始行,因此您的回调会被调用3次。 (制作3个对话框)。

将此行移到点击之外:

 query = mDatabase.child("child").child(anotherChild).child("yetAnotherChild");

然后当你添加下面的监听器时(在点击内部)它应该没问题

query.orderByChild("someChild").addChildEventListener(new ChildEventListener() {
                    @Override
                    public void onChildAdded(DataSnapshot dataSnapshot, String s) {

答案 1 :(得分:3)

使用<div id="app"><!-- vue mounted at this div --> <div v-cloak> <!-- your actual code / content --> </div> </div> [v-cloak] { display: none; } 时设置限制。像这样,

valueEventListener

当你完成与firebase相关的工作后,总是删除监听器。像这样,

addChildEventListener

感谢。

答案 2 :(得分:2)

在调用之前创建并显示AlertDialog .addChildEventListener()

然后在下载相应数据后使用addChildEventListener调用notifyDatasetChanged()。不要在addChildEventListener

中创建AlertDialog

答案 3 :(得分:1)

您可以使用Firebase查询来限制侦听器下载的数据。

query.orderByChild("someChild").limitToLast(1).addChildEventListener(...

答案 4 :(得分:1)

@Blundell有解决问题的洞察力。我只是想建议你使用addValueEventListener的类似方法。

  

值事件侦听器将针对初始状态触发一次   数据,然后每当数据的值发生变化时再次出现。

您需要从onClick函数中移出firebase查询。所以你的查询可能看起来像这样..

// Declare the variable names as public
private String names[];

private void addFirebaseListener() {
    ref = mDatabase.child("child").child(anotherChild).child("yetAnotherChild");
    ref. userRef.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot snapshot) {
          Map<String, String> newD = (Map<String, String>) dataSnapshot.getValue();

          ArrayList<String> l = new ArrayList<String>();
          l.add(newD.get("lol").substring(30));

          names[] = l.toArray(new String[0]);

          // Call notifyDataSetChanged each time your array gets updated
          adapter.notifyDataSetChanged();
        }

        @Override public void onCancelled(FirebaseError error) { }
    });
}

现在编写一个函数来显示ListView

中的AlertDialog
// Declare the adapter as public and initialize it with null
private ArrayAdapter<String> adapter = null;

private void showListInDialog() {
    AlertDialog.Builder alertDialog = new AlertDialog.Builder(Activity.this);
    LayoutInflater inflater = getLayoutInflater();
    View convertView = inflater.inflate(R.layout.dialog_list, null);
    alertDialog.setView(convertView);
    alertDialog.setTitle("title");
    ListView lv = (ListView) convertView.findViewById(R.id.lv);

    if(adapter == null)
        adapter = new ArrayAdapter<String>(getBaseContext(), android.R.layout.simple_list_item_1, names);

    // Now set the adapter
    lv.setAdapter(adapter);

    alertDialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialogInterface, int i) {
            alertDialog.dismiss();
        }
    });

    alertDialog.show();
}

现在,在onCreate功能中,您需要先设置Firebase侦听器,然后像这样设置onClick功能。

uProfile.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        showListInDialog();
    }
});

答案 5 :(得分:1)

@Hammad根据您的要求尝试此修改后的代码。

    query = mDatabase.child("child").child(anotherChild).child("yetAnotherChild");

    AlertDialog alertDialog;
    ArrayList<String> l;

    uProfile.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            query.orderByChild("someChild").addChildEventListener(new ChildEventListener() {
                @Override
                public void onChildAdded(DataSnapshot dataSnapshot, String s) {
                    if (dataSnapshot != null) {

                        Map<String, String> newD = (Map<String, String>) dataSnapshot.getValue();

    if(l == null) {
                        l = new ArrayList<String>();
    }
                        l.add(newD.get("lol").substring(30));

    String names[] = new String[l.size()];
    for(int length=0; length < l.size(); l++) {
        names[length] = l.get(length);
    }

    if(alertDialog == null) {
                        alertDialog = new AlertDialog.Builder(Activity.this).create();
                        LayoutInflater inflater = getLayoutInflater();
                        View convertView = inflater.inflate(R.layout.dialog_list, null);
                        alertDialog.setView(convertView);
                        alertDialog.setTitle("title");
                        ListView lv = (ListView) convertView.findViewById(R.id.lv);

    } ArrayAdapter<String> adapter = new ArrayAdapter<String>(getBaseContext(), android.R.layout.simple_list_item_1, names);
                        lv.setAdapter(adapter);

                        alertDialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialogInterface, int i) {

                            }
                        });

if(!alertDialog.isShowing()) {
                        alertDialog.show();
}
                    } else {
                        Toast.makeText(getBaseContext(), "NULLLLL", Toast.LENGTH_SHORT).show();
                    }
                }

                ...
                ...
            });

        }
    });

答案 6 :(得分:1)

ChildEventListener childEventListener = new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) {
    Log.d(TAG, "onChildAdded:" + dataSnapshot.getKey());

/ **

检索项目列表或侦听项目列表的添加项。对于每个现有子项,将触发此回调一次,然后每次将新子项添加到指定路径时再次触发此回调。传递给侦听器的DataSnapshot包含新子项的数据。

** /

}

@Override
public void onChildChanged(DataSnapshot dataSnapshot, String previousChildName) {
    Log.d(TAG, "onChildChanged:" + dataSnapshot.getKey());
}

@Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
    Log.d(TAG, "onChildRemoved:" + dataSnapshot.getKey());
}

@Override
public void onChildMoved(DataSnapshot dataSnapshot, String previousChildName) {
    Log.d(TAG, "onChildMoved:" + dataSnapshot.getKey());
}

@Override
public void onCancelled(DatabaseError databaseError) {
}

}; ref.addChildEventListener(childEventListener); 使用ChildEventListener onChildAdded是在该节点中为每个孩子调用的。表示您的代码运行3次,因此对话框会出现3次。

这是问题 所以解决方案是:

  

虽然建议使用ChildEventListener来读取数据列表,但有时会将ValueEventListener附加到列表引用中。

     

将ValueEventListener附加到数据列表会将整个数据列表作为单个DataSnapshot返回,然后您可以循环访问以访问各个子项。

     

即使查询只有一个匹配项,快照仍然是一个列表;它只包含一个项目。要访问该项目,您需要循环结果:

inaccessibleChild.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
    for (DataSnapshot postSnapshot: dataSnapshot.getChildren()) {
       //here you can access the each child of that node.
    }
}

@Override
public void onCancelled(DatabaseError databaseError) {
    // Getting Post failed, log a message
    Log.w(TAG, "loadPost:onCancelled", databaseError.toException());
    // ...
}

});

答案 7 :(得分:1)

嗯,上述答案都没有真正帮助,虽然Linxy的回答是正确的,我在解决了问题之后看到了它。

将所有代码移出并写下这一行:alertDialog.show();setOnClickListener()内改进我的代码:

    query = mDatabase.child("child").child(anotherChild).child("yetAnotherChild");

    query.orderByChild("someChild").addChildEventListener(new ChildEventListener() {
                @Override
                public void onChildAdded(DataSnapshot dataSnapshot, String s) {
                    if (dataSnapshot != null) {

                        Map<String, String> newD = (Map<String, String>) dataSnapshot.getValue();

                        ArrayList<String> l = new ArrayList<String>();
                        l.add(newD.get("lol").substring(30));

                        String names[] = l.toArray(new String[0]);

                        AlertDialog.Builder alertDialog = new AlertDialog.Builder(Activity.this);
                        LayoutInflater inflater = getLayoutInflater();
                        View convertView = inflater.inflate(R.layout.dialog_list, null);
                        alertDialog.setView(convertView);
                        alertDialog.setTitle("title");
                        ListView lv = (ListView) convertView.findViewById(R.id.lv);
                        ArrayAdapter<String> adapter = new ArrayAdapter<String>(getBaseContext(), android.R.layout.simple_list_item_1, names);
                        lv.setAdapter(adapter);

                        alertDialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialogInterface, int i) {

                            }
                        });
                    } else {
                        Toast.makeText(getBaseContext(), "NULLLLL", Toast.LENGTH_SHORT).show();
                    }
                }

                ...
                ...
            });

uProfile.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        alert11.show();
    }
});

无论如何,我要感谢所有回答这个问题的人。

和平。