當我得到一行ListView
的數據後,我想更新該單行。Android ListView刷新單行
目前我正在使用notifyDataSetChanged();
但這使得View
反應非常緩慢。還有其他解決方案嗎?
當我得到一行ListView
的數據後,我想更新該單行。Android ListView刷新單行
目前我正在使用notifyDataSetChanged();
但這使得View
反應非常緩慢。還有其他解決方案嗎?
一個選項是直接操作ListView
。首先檢查更新行的索引是否在getFirstVisiblePosition()
和getLastVisiblePosition()
之間,這兩個參數給出了適配器中屏幕上可見的第一個和最後一個位置。然後你可以通過getChildAt(int index)
得到View
並改變它。
以下代碼適用於我。請注意,調用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);
}
}
}
}
由於羅曼蓋伊的Google I/O session,最有效的辦法只能更新列表視圖一個視圖中explained a while back是類似如下(這個更新整個視圖的數據):
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;
}
假設target
是適配器的一項。
此代碼檢索ListView
,然後瀏覽當前顯示的看法,比較target
項目你正在尋找與每個顯示的視圖中的項目,如果你的目標是那些中,得到封閉看法和對執行適配器getView
查看刷新顯示。
作爲一個側面說明invalidate
不起作用像一些人期望並不會刷新像getView這個視圖,notifyDataSetChanged
將重建整個列表,並最終調用getview
爲每個顯示的項目和invalidateViews
也會影響了一堆。
最後一件事,如果他只需要改變行視圖的子項而不是像getView
那樣的整行,就可以獲得額外的性能。在這種情況下,下面的代碼可以取代list.getAdapter().getView(i, view, list);
(例如更改TextView
文本):
((TextView)view.findViewById(R.id.myid)).setText("some new text");
在代碼中我們信任。
這更簡單的方法很適合我,你只需要知道位置索引得到阿霍德的看法:
// 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);
}
還有另一種更有效的事情可以做,如果它適合你用例就是這樣。
如果你正在改變狀態,並可以以某種方式調用適當的(通過了解位置)mListView.getAdapter().getView()
它將是最有效的。
我可以通過在我的ListAdapter.getView()
類中創建一個匿名內部類來演示一個非常簡單的方法。在這個例子中,我有一個TextView
出「新」一文,並單擊列表項時視圖設置爲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;
}
框架自動使用正確的position
,你也不用擔心取它再次致電getView
。
只是爲了記錄,有沒有人考慮覆蓋方法的'查看視圖'?
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//Update the selected item
((TextView)view.findViewById(R.id.cardText2)).setText("done!");
}
問題是如何在任何給定的ListView中刷新單行時刻。 onItemClick僅在用戶單擊某個項目時纔會調用,因此不夠用 – Thys 2016-09-07 11:24:20
謝謝。如果我正在**編輯孩子的當前佈局,這將起作用。但是,如果我想**改變佈局**(通過膨脹一個不同的XML)?如果我在適配器上調用'newView(...)',它會給我一個不同的視圖,但不會放入'listView'中。 – hadi 2013-08-15 20:30:03
@hadi你應該看看這個答案:http://stackoverflow.com/a/11568271/858626 – 2014-09-24 12:56:02