1

リポジトリで見つかったデータに従って、実行時に動的に追加Androidするアプリがあります。より具体的には、レポで見つかった「Poll」ごとに staticに aが追加され、Poll で見つかった「選挙」ごとに aが追加され、選挙の「候補者」ごとに2 つのデータを含むa が追加されます。にも。そのため、実行時に複数のテーブルを追加して、それぞれに複数の選挙の行が含まれ、各選挙に候補者の複数のデータ行が含まれる可能性があります。これが私の静的レイアウトです....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) - ...

したがって、私の質問には実際には 2 つのスレッドがあります。1つ目はAndroid向けです...

  1. レポ内のデータが変更されたときにデータAndroidを変更するために動的に追加されたビューを反復処理する最良の方法は何ですか?TextViewTableViewTableRows

今、私はこのようなことをしていますが、非常に遅いです。もっと良い方法が必要だと感じています...

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も、囲んでいるスコープ内の変数を参照することもできません (これについて間違っていることを願っています。より簡単に)。内で static final 変数を参照できることはわかってValueEventListenerいますが、実行時に処理するテーブルまたは行の数がわからないため、これがどのように役立つかわかりません。

要するに、特定の呼び出しをそのデータが関連付けられているものValueEventListenerにリンクするにはどうすればよいでしょうか?TableRow

では、もう少しFirebase具体的な質問 2 について説明します....

  1. ValueEventListenerアクティビティが読み込まれたときに一度呼び出され、基になるデータが変更されたときに再度呼び出されるようです。しかし、ロード時ではなく、基になるデータの変更に対してのみ呼び出されるようにしたいのです。間違った EventListener を使用していますか? または、この動作を回避する方法はありますか?
4

1 に答える 1

1

Firebase 固有の質問については、これは仕様によるものです。Firebase では、初期データとデータ更新を区別することは推奨されていません。リアルタイムのシナリオでは、最新のデータに実際に「追いつく」ことができないためです。

起動時にすべてのデータを取得したくない場合は、クエリと制限を使用して、受信できるデータを制限します。たとえば、最新の 100 件の投票のみを受け取りたい場合は、次のようにします。

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

子イベント リスナーは、ポーリングごとに 1 回呼び出されます。新しい投票が追加されると、それが再度呼び出されます (100 のリストの中で最も古い投票の子削除イベントが発生します)。

お役に立てれば!

于 2013-07-31T22:29:18.150 に答える