Android ListView 刷新单行
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2123083/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Android ListView Refresh Single Row
提问by Thizzer
After I have gotten the data for a single row of a ListView
, I want to update that single row.
在获得 a 的单行数据后ListView
,我想更新该单行。
Currently I am using notifyDataSetChanged();
but that makes the View
react very slowly. Are there any other solutions?
目前我正在使用,notifyDataSetChanged();
但这使得View
反应非常缓慢。还有其他解决方案吗?
采纳答案by Daniel Velkov
One option is to manipulate the ListView
directly. First check if the index of the updated row is between getFirstVisiblePosition()
and getLastVisiblePosition()
, these two give you the first and last positions in the adapter that are visible on the screen. Then you can get the row View
with getChildAt(int index)
and change it.
一种选择是ListView
直接操作。首先检查更新行的索引是否在getFirstVisiblePosition()
和之间getLastVisiblePosition()
,这两个为您提供适配器中屏幕上可见的第一个和最后一个位置。然后你就可以得到该行View
与getChildAt(int index)
和改变它。
回答by GriffonRL
As Romain Guy explained a while backduring the Google I/O session, the most efficient way to only update one view in a list view is something like the following (this one update the whole view data):
正如 Romain Guy在Google I/O 会议期间解释的那样,仅更新列表视图中的一个视图的最有效方法如下所示(此方法更新整个视图数据):
ListView list = getListView();
int start = list.getFirstVisiblePosition();
for(int i=start, j=list.getLastVisiblePosition();i<=j;i++)
if(target==list.getItemAtPosition(i)){
View view = list.getChildAt(i-start);
list.getAdapter().getView(i, view, list);
break;
}
Assuming target
is one item of the adapter.
假设target
是适配器的一项。
This code retrieve the ListView
, then browse the currently shown views, compare the target
item you are looking for with each displayed view items, and if your target is among those, get the enclosing view and execute the adapter getView
on that view to refresh the display.
此代码检索ListView
,然后浏览当前显示的视图,将target
您要查找的项目与每个显示的视图项目进行比较,如果您的目标在其中,则获取封闭视图并getView
在该视图上执行适配器以刷新显示。
As a side note invalidate
doesn't work like some people expect and will not refresh the view like getView does, notifyDataSetChanged
will rebuild the whole list and end up calling getview
for every displayed items and invalidateViews
will also affect a bunch.
由于旁注invalidate
不像某些人期望的那样工作,并且不会像 getView 那样刷新视图,notifyDataSetChanged
将重建整个列表并最终调用getview
每个显示的项目,并且invalidateViews
还会影响一堆。
One last thing, one can also get extra performance if he only needs to change a child of a row view and not the whole row like getView
does. In that case, the following code can replace list.getAdapter().getView(i, view, list);
(example to change a TextView
text):
最后一件事,如果他只需要更改行视图的子项而不是整行,也可以获得额外的性能getView
。在这种情况下,以下代码可以替换list.getAdapter().getView(i, view, list);
(更改TextView
文本的示例):
((TextView)view.findViewById(R.id.myid)).setText("some new text");
In code we trust.
在我们信任的代码中。
回答by John Starr Dewar
This simpler method works well for me, and you only need to know the position index to get ahold of the view:
这种更简单的方法对我来说效果很好,您只需要知道位置索引即可获得视图:
// mListView is an instance variable
private void updateItemAtPosition(int position) {
int visiblePosition = mListView.getFirstVisiblePosition();
View view = mListView.getChildAt(position - visiblePosition);
mListView.getAdapter().getView(position, view, mListView);
}
回答by SkolVikingsGuy
The following code worked for me. Note when calling GetChild() you have to offset by the first item in the list since its relative to that.
以下代码对我有用。请注意,在调用 GetChild() 时,您必须偏移列表中的第一个项目,因为它相对于该项目。
int iFirst = getFirstVisiblePosition();
int iLast = getLastVisiblePosition();
if ( indexToChange >= numberOfRowsInSection() ) {
Log.i( "MyApp", "Invalid index. Row Count = " + numberOfRowsInSection() );
}
else {
if ( ( index >= iFirst ) && ( index <= iLast ) ) {
// get the view at the position being updated - need to adjust index based on first in the list
View vw = getChildAt( sysvar_index - iFirst );
if ( null != vw ) {
// get the text view for the view
TextView tv = (TextView) vw.findViewById(com.android.myapp.R.id.scrollingListRowTextView );
if ( tv != null ) {
// update the text, invalidation seems to be automatic
tv.setText( "Item = " + myAppGetItem( index ) + ". Index = " + index + ". First = " + iFirst + ". Last = " + iLast );
}
}
}
}
回答by vedant
There is another much more efficient thing you can do, if it fits your use-case that is.
如果它适合您的用例,您还可以做另一件更有效的事情。
If you are changing the state and can somehow call the proper (by knowing the position) mListView.getAdapter().getView()
it will the most efficient of all.
如果您正在更改状态并且可以以某种方式调用正确的(通过知道位置)mListView.getAdapter().getView()
,它将是最有效的。
I can demonstrate a really easy way to do it, by creating an anonymous inner class in my ListAdapter.getView()
class. In this example I have a TextView
showing a text "new" and that view is set to GONE
when the list item is clicked:
我可以通过在我的ListAdapter.getView()
类中创建一个匿名内部类来演示一种非常简单的方法来做到这一点。在这个例子中,我有一个TextView
显示文本“new”的视图,GONE
当单击列表项时该视图设置为:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// assign the view we are converting to a local variable
View view = convertView;
Object quotation = getItem(position);
// first check to see if the view is null. if so, we have to inflate it.
if (view == null)
view = mInflater.inflate(R.layout.list_item_quotation, parent, false);
final TextView newTextView = (TextView) view.findViewById(R.id.newTextView);
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mCallbacks != null)
mCallbacks.onItemSelected(quotation.id);
if (!quotation.isRead()) {
servicesSingleton.setQuotationStatusReadRequest(quotation.id);
quotation.setStatusRead();
newTextView.setVisibility(View.GONE);
}
}
});
if(quotation.isRead())
newTextView.setVisibility(View.GONE);
else
newTextView.setVisibility(View.VISIBLE);
return view;
}
The framework automatically uses the correct position
and you do have to worry about fetching it again before calling getView
.
框架会自动使用正确的position
,您不必担心在调用getView
.
回答by AnoNym
Just for the record, did anyone consider the 'View view' on the override method ?
只是为了记录,有没有人考虑过覆盖方法上的“查看视图”?
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//Update the selected item
((TextView)view.findViewById(R.id.cardText2)).setText("done!");
}