1

我有一个应用程序,它根据在存储库中找到的数据在运行时动态Android添加。更具体地说,为在 repo 中找到的每个“民意调查”添加 a 到 static中,对于在民意调查中找到的每个“选举” a添加到 that 中,并且对于包含两个for data的选举中的每个“提名人”添加到也。因此,我可能会在运行时添加多个表,每个表都包含用于多次选举的行,并且每次选举都有多个用于被提名人的数据行。这是我的静态布局,可以很好地衡量......TableViews, TableRowsTextViewsFirebaseTableViewLinearLayoutTableRowTablelayoutTableRowTextViewsTableLayout

     <?xml version="1.0"?>
    <ScrollView android:layout_height="android:layout_width="match_parent" android:id="@+id/scrollView1" xmlns:android="http://schemas.android.com/apk/res/android">

<LinearLayout android:layout_height="match_parent" android:layout_width="match_parent" android:id="@+id/linearLayout" android:orientation="vertical"> 
</LinearLayout>

    </ScrollView>

..这是我的Firebase回购的代表......

-POLLS
    NUMPOLLS - 5
    (pollskey) - NAME - Poll1
            NUMELECTIONS - 2
            ELECTIONS 
                (electionskey) - NAME - Election1
                        NUMNOMINATIONS - 2
                        NUMVOTERS - 2
                        NUMBERTOELECT - 1
                        VOTERS - (votesrkey) - NAME - Charles
                                         NUMBER - (678) 333-4444
                                 .
                                 .
                                 .
                                 (voterskey) - ...
                        NOMINATIONS - (nominationskey) - NAME - Richard Nixon
                                              NUMBEROFVOTES - 2
                                       .
                                       .
                                       .
                                      (nominationskey) - ...
            .
            .
            .
            (electionskey) - ...
     .
     .
     .
     (pollskey) - ...

所以我的问题真的有两个线程。首先是面向Android的...

  1. 当存储库中的数据发生变化时,迭代Android动态添加的视图以更改TextView数据的最佳方法是什么,我不知道有多少这样TableView的,或者TableRows在编译时会有多少?

现在我正在做这样的事情,但是进展很慢我觉得必须有更好的方法......

private void appendCandidatesAndVotes(DataSnapshot election, TableLayout tbl) {
        Random randGen = new Random();
        DataSnapshot nominees = election.child("Nominations");
        for (DataSnapshot nominee : nominees.getChildren()) {

            // Create row for candidate name and number of votes
            TableRow rowNameAndVotes = new TableRow(this);
            // Generating a random row ID here allows us to pass this to 
            // the valueEventListener and quickly locate this row in 
            // the case of a data change (someone has cast a vote) so we 
            // can update
            int uniqueRowId = randGen.nextInt(1000);
            rowNameAndVotes.setId(uniqueRowId);
            rowNameAndVotes.setBackgroundColor(Color.WHITE);
            rowNameAndVotes.setLayoutParams(new TableRow.LayoutParams (
                    LayoutParams.MATCH_PARENT,
                    LayoutParams.WRAP_CONTENT));

            // Create candidate name view
            TextView viewCandidateName = new TextView(this);
            viewCandidateName.setId(2);
            viewCandidateName.setText(nominee.child("Name").getValue(String.class));
            viewCandidateName.setTextColor(Color.BLACK);
            viewCandidateName.setPadding(5,  5,  5, 5);
            rowNameAndVotes.addView(viewCandidateName);

            // Create number of votes view
            TextView viewNumVotes = new TextView(this);
            viewNumVotes.setId(3);
            viewNumVotes.setText(nominee.child("NumberOfVotes").getValue(String.class));
            viewNumVotes.setTextColor(Color.BLACK);
            viewNumVotes.setPadding(3,  5,  5,  5);
            rowNameAndVotes.addView(viewNumVotes);

            // Add row to table
            tbl.addView(rowNameAndVotes);

            // Lets get a Firebase reference for this nominee and
            // attach a listener to alert us to all future changes of
            // the values therein, so we can update vote counts dynamically
            Firebase nomineeRef = nominee.getRef();
            nomineeRef.addValueEventListener(new ValueEventListener() {

                @Override
                public void onDataChange(DataSnapshot nomineeSnapshot) {

                    String nomineeName = nomineeSnapshot.child("Name").getValue(String.class);
                    LinearLayout layout = (LinearLayout) findViewById(R.id.linearLayout);
                    int layoutChildCount = layout.getChildCount();
                    for (int i = 0; i < layoutChildCount; i++) {
                        View layoutChildView = layout.getChildAt(i);
                        // If its a Table, loop through all row
                        if (layoutChildView instanceof TableLayout) {
                            TableLayout tbl = (TableLayout)layoutChildView;
                            int tableChildCount = tbl.getChildCount();
                            for (int j = 0; j < tableChildCount; j++) {
                                View tblChildView = tbl.getChildAt(i);
                                if (tblChildView instanceof TableRow) {
                                    TableRow row = (TableRow)tblChildView;
                                    int rowChildren = row.getChildCount();
                                    for (int k = 0; k < rowChildren; k++) {
                                        TextView tv = (TextView)(row.getChildAt(k));
                                        String rowCandidateName = tv.getText().toString();
                                        if (rowCandidateName) ...
                                    }
                                }
                            }
                        }
                    }
                }

认为这是布局的方式,我可以直接参考的唯一布局是 base LinearLayout。我可以用 给出所有TableRows唯一的 ID setId(),但据我所知,我不能将任何数据传递给ValueEventListener,也不能引用封闭范围内的任何变量(我希望我错了,它会让事情变得更轻松)。我知道我可以引用内部的静态最终变量ValueEventListener,但我不知道这对我有什么帮助,因为我不知道在运行时我将处理多少表或行。

所以,简而言之,我如何将特定调用ValueEventListenerTableRow它的数据相关联?

现在对于问题 2,它更Firebase具体一点......

  1. 似乎ValueEventListener在加载活动时调用一次,然后再次调用基础数据的任何更改。但我只希望它要求对基础数据进行更改,而不是在加载时。我使用了错误的 EventListener 吗?或者有什么方法可以避免这种行为?
4

1 回答 1

1

对于 Firebase 特定问题 - 这是设计使然。Firebase 不鼓励区分初始数据和数据更新,因为在实时场景中,您永远无法真正“赶上”最新数据。

如果您不想在启动时检索所有数据,那么我会使用查询和限制来限制您可以接收哪些数据。例如,如果您只想接收最新的 100 个民意调查,您可以执行以下操作:

Firebase ref = new Firebase(url);
Query q = ref.limit(100);
q.addChildEventListener(...);

每次轮询都会调用一次子事件侦听器。添加新的民意调查时,它将再次被调用(对于 100 个列表中最旧的民意调查,将会有一个子删除事件)。

希望这可以帮助!

于 2013-07-31T22:29:18.150 回答