2011-12-06 38 views
12

Tôi có một bộ điều hợp tùy chỉnh hình dung từng hàng trong danh sách Đơn đặt hàng.BaseAdapter thông báoDatasetChanged() được gọi nhưng getView() không bao giờ được gọi là

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(); 
     } 
    }; 

Sau khi truy vấn danh sách mới của đơn đặt hàng từ một dịch vụ web, tôi muốn cập nhật nội dung của ListView, vì vậy tôi có Hoạt động của tôi hiện cập nhật trước khi gọi 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."); 
} 

Nhưng, phương thức getView() của OrderRowAdapter không bao giờ được gọi. ListView không bao giờ được cập nhật.

Trả lời

12

Nó chỉ ra các vấn đề với số getView() không được gọi là vì nó không hiển thị. Bố cục xml của tôi có trên TextView với chiều cao fill_parent. Do đó, toàn bộ khung nhìn chỉ có duy nhất TextView hiển thị.

Giải pháp: kiểm tra chế độ xem đồ họa của bố cục được đề cập để đảm bảo rằng ListView hiển thị.

+0

IMO đây là một vấn đề rất không rõ ràng. Đặc biệt là kể từ khi ẩn một 'AdapterView' để hiển thị một' Spinner' vẫn là một mô hình phổ biến, tôi có thể thấy đây là con ngỗng hoang dã pesky cho rất nhiều người ... – alexgophermix

1

Để thay đổi nội dung của ListView, bạn phải tiếp tục sử dụng cùng một tham chiếu đến Danh sách. Ở đây bạn đang tạo một danh sách khác và gán nó cho biến số items_ (không chứa danh sách, nó chỉ là nơi để lưu trữ một tham chiếu đến một Danh sách), nhưng Chế độ xem của bạn vẫn có tham chiếu đến danh sách cũ.

Thay vì items_ = new_order_list này nên làm việc:

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

EDIT:

Để giải thích nó tốt hơn, cố gắng tạo ra một biến mới có tên 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's the one used by your ListView 

    notifyDataSetChanged(); 
} 
+0

Mặc dù vậy, phương pháp getView của tôi không được gọi nếu getCount tiếp tục trả lại 5? Tôi đã thử đề xuất của bạn và tôi nhận được java.lang.UnsupportedOperationException tại java.util.Collections $ UnmodifiableCollection.clear –

+0

Phương thức 'getCount()' đếm các mục chứa trong danh sách mới của bạn kể từ khi bạn thay thế tham chiếu, chứ không phải cái cũ bị lạc đâu đó trong ký ức. Tôi đã chỉnh sửa câu trả lời của mình. – Dalmas

+0

Ngoại lệ của bạn có nghĩa là danh sách của bạn là chỉ đọc. Làm thế nào để bạn tạo ra nó? – Dalmas

2

Hãy chắc chắn rằng BaseAdapter phương pháp

registerDataSetObserver(DataSetObserver observer) 
unregisterDataSetObserver(DataSetObserver observer) 

không ghi đè.

0

Nếu tất cả các câu trả lời ở trên không thử với invalidateViews làm việc()

ListView.invalidateViews() được sử dụng để báo cho ListView để vô hiệu hóa tất cả các quan điểm mục con của nó (vẽ lại chúng).

Lưu ý rằng không cần phải có số lượt xem bằng nhau so với mục. Đó là bởi vì một ListView tái chế các khung nhìn mục của nó và di chuyển chúng xung quanh màn hình một cách thông minh trong khi bạn di chuyển.

listView.invalidateViews() 

thi mẫu của tôi,

    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 
         } 
        }); 

Nếu bất kỳ sai lầm trong câu trả lời này hãy sửa lại sai lầm của tôi.

Các vấn đề liên quan