Вызывается BaseAdapter notifyDatasetChanged(), но getView() никогда не вызывается

145
11

У меня есть пользовательский адаптер, который визуализирует каждую строку в списке ордеров.


public class OrderRowAdapter extends BaseAdapter implements OnClickListener {
OrderList items_;
LayoutInflater inflater_;
int list_view_resource_id_;
private final String TAG = "OrderRowAdapter";

public OrderRowAdapter(Context context, int list_view_resource_id,
OrderList items) {
this.list_view_resource_id_ = list_view_resource_id;
this.items_ = items;
this.inflater_ = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

public Object getItem(int position) {
return items_.getOrders(position);
}

public View getView(int position, View convertView, ViewGroup parent) {
Log.d(TAG, "View updated for item in position = " + position);

View v = convertView;
if (v == null) {
v = inflater_.inflate(list_view_resource_id_, parent);
}

Order item = items_.getOrders(position);
if (item != null) {
TextView order_info_tv = (TextView) v.findViewById(R.id.order_info);
TextView order_status_tv = (TextView) v.findViewById(R.id.order_status);

if (order_info_tv != null) {
order_info_tv.setText(
String.format("For customer: %s\nTotal of %d items", item.getCustomerId(), item.getItemsCount()));
}
if (order_status_tv != null) {
order_status_tv.setText("Status: " + getStatusText(item.getStatus()));
}
}
return v;
}

public int getCount() {
if (items_ == null) {
Log.d(TAG, "Null so get count returned 0");
return 0;
} else {
Log.d(TAG, "Get count returned " + items_.getOrdersCount());
return items_.getOrdersCount();
}
};


После запроса нового списка заказов из веб-службы я хочу обновить содержимое ListView, поэтому у меня есть моя активность для обновления перед вызовом notifyDataSetChanged()


@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.orders);

initThreading();
findViews();
setUrls();

// Load the list of order from disk
try {
order_list_ = OrderList.parseFrom(new FileInputStream(
"/sdcard/orderList.bin"));
} catch (FileNotFoundException e) {
Log.e(TAG, "Cannot find the file", e);
} catch (IOException e) {
Log.e(TAG, "Cannot read the file", e);
}

order_row_adapter_ = new OrderRowAdapter(OrderActivity.this,
R.layout.order_row, order_list_);
orders_listview_.setAdapter(order_row_adapter_);

// Request new updates from the server
updateOrderInformation(-1);
}

public void updateOrders(InputStream new_order_stream) {
Log.d(TAG, "Updating order UI");
try {
order_list_.parseFrom(new_order_stream);
} catch (IOException e) {
Log.e(TAG, "IOException" , e);
}

runOnUiThread(new Runnable() {
public void run() {
guiUpdateOrders();
}
});
}

private void guiUpdateOrders() {
order_row_adapter_.notifyDataSetChanged();
Log.d(TAG, "Dataset notified that it has changed. GUI update anytime now.");
}


Но метод getView() метода OrderRowAdapter никогда не вызывается. ListView никогда не обновляется.

спросил(а) 2011-12-06T04:12:00+04:00 8 лет, 10 месяцев назад
1
Решение
145

Оказывается, проблема с тем, что мой getView() не вызывается, потому что он не отображается. Мой макет xml имеет верхний TextView с fill_parent для его высоты. Таким образом, у всего представления есть только один TextView.

Решение: проверьте графическое представление рассматриваемого макета, чтобы убедиться, что отображается ListView.

ответил(а) 2011-12-06T06:06:00+04:00 8 лет, 10 месяцев назад
71

Убедитесь, что методы BaseAdapter


registerDataSetObserver(DataSetObserver observer) 
unregisterDataSetObserver(DataSetObserver observer)

не переопределены.

ответил(а) 2014-10-31T20:01:00+03:00 5 лет, 11 месяцев назад
57

Чтобы изменить содержимое вашего ListView, вы должны продолжать использовать ту же ссылку на список. Здесь вы создаете другой список и назначаете его переменной items_ (которая не содержит самого списка, это просто место для хранения ссылки на список), но в вашем представлении все еще есть ссылка на старый список.


Вместо items_ = new_order_list это должно работать:


items_.clear();
items_.addAll(new_order_list);

ИЗМЕНИТЬ:


Чтобы объяснить это лучше, попробуйте создать новую переменную с именем old_items:


public void setNewOrderList(List<Order> new_order_list)
{
Log.d(TAG, "New Order List available. Num items = " + new_order_list.size());

List<Order> old_items = items_; // store the reference to the old list
items_ = new_order_list;

Log.d(TAG, "items_.size() = " + items_.size());
Log.d(TAG, "old_items.size() = " + old_items.size()); // The old list still exists, and it the one used by your ListView

notifyDataSetChanged();
}

ответил(а) 2011-12-06T04:20:00+04:00 8 лет, 10 месяцев назад
41

Если все вышеперечисленные ответы не работают, попробуйте с invalidateViews()


ListView.invalidateViews() используется, чтобы сообщить ListView о недействительности всех его дочерних элементов (перерисовать их).


Обратите внимание, что не должно быть равного количества просмотров, чем элементов. Это потому, что ListView перерабатывает свои представления элементов и перемещает их по экрану разумным способом во время прокрутки.


 listView.invalidateViews()

Моя примерная реализация,


                    lvitems.post(new Runnable() {
@Override
public void run() {
lvitems.invalidateViews(); //invalidate old
CustomAdapter customAdapter=new CustomAdapter(context, names, images); // load new data
customAdapter.notifyDataSetChanged();// call notifydatasetChanged
}
});

Если какая-либо ошибка в этом ответе, пожалуйста, исправьте мои ошибки.

ответил(а) 2016-06-03T10:33:00+03:00 4 года, 4 месяца назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема