如何在运行时更改动态添加的 Android 视图中的数据
Posted
技术标签:
【中文标题】如何在运行时更改动态添加的 Android 视图中的数据【英文标题】:How to change data in dynamically added Android Views at runtime 【发布时间】:2013-08-01 12:26:56 【问题描述】:我有 android
应用程序,它根据在 Firebase
存储库中找到的数据在运行时动态添加 TableViews,
TableRows
和 TextViews
。更具体地说,为在 repo 中找到的每个“投票”添加一个 TableView
到静态 LinearLayout
,对于在投票中找到的每个“选举”,将一个 TableRow
添加到该 Tablelayout
,并且对于每个“ Nominee”在选举中包含两个 TextViews
用于数据的 TableRow
也被添加到 TableLayout
中。因此,我可能会在运行时添加多个表,每个表都包含用于多次选举的行,并且每次选举都有多个用于被提名人的数据行。这是我的静态布局,可以很好地衡量......
<?xml version="1.0"?>
<ScrollView android:layout_@+id/scrollView1" xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout android:layout_ android:layout_ android:id="@+id/linearLayout" android:orientation="vertical">
</LinearLayout>
</ScrollView>
..这是我的Firebase
repo 的表示...
-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的...
-
当repo中的数据发生变化时,动态添加的
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) ...
我认为这种布局方式,我可以直接参考的唯一布局是基础LinearLayout
。我可以用setId()
给所有TableRows
唯一ID,但据我所知,我不能将任何数据传递给ValueEventListener
,也不能引用封闭范围内的任何变量(我希望我是错了,这会让事情变得更容易)。我知道我可以在ValueEventListener
中引用静态最终变量,但我不知道这对我有什么帮助,因为我不知道在运行时我将处理多少表或行。
那么,简而言之,我如何才能将特定调用链接到 ValueEventListener
与它的数据关联的 TableRow
?
现在是问题 2,它更具体一点 Firebase
....
-
似乎
ValueEventListener
在加载活动时调用一次,然后再次调用基础数据的任何更改。但我只希望它要求对基础数据进行更改,而不是在加载时。我使用了错误的 EventListener 吗?或者有什么方法可以避免这种行为?
【问题讨论】:
“那么,简而言之,我如何将对 ValueEventListener 的特定调用与它的数据关联的 TableRow 链接起来?”也许尝试继承 ValueEventListener 并添加一个字段来存储您需要的数据。另外,不确定 Firebase 到底是什么,但您认为 CursorAdapters 是否适用于这种情况? 嗯,也许吧,我现在正在看教程。 Firebase 只是一种存储服务,可让您存储数据并在 ValueEvent 等事件中检索数据 【参考方案1】:对于 Firebase 特定问题 - 这是设计使然。 Firebase 不鼓励区分初始数据和数据更新,因为在实时场景中,您永远无法真正“赶上”最新数据。
如果您不想在启动时检索所有数据,那么我会使用查询和限制来限制您可以接收的数据。例如,如果您只想接收最新的 100 次投票,您可以执行以下操作:
Firebase ref = new Firebase(url);
Query q = ref.limit(100);
q.addChildEventListener(...);
每次轮询都会调用一次子事件侦听器。添加新民意调查时,它将再次被调用(对于 100 个列表中最旧的民意调查,将会有一个子删除事件)。
希望这会有所帮助!
【讨论】:
酷,是的。谢谢阿南特!以上是关于如何在运行时更改动态添加的 Android 视图中的数据的主要内容,如果未能解决你的问题,请参考以下文章
如何使用javascript动态更改html中svg的文本内容