2011-12-06 2 views
12

Orders 목록의 각 행을 시각화하는 사용자 지정 어댑터가 있습니다.BaseAdapter notifyDatasetChanged()가 호출되었지만 getView()가 호출되지 않습니다.

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

웹 서비스에서 주문의 새 목록을 조회 후,리스트 뷰의 내용을 업데이트 할, 그래서) (내 활동 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."); 
} 

하지만, OrderRowAdapter의 getView() 메소드는 호출되지 않습니다. ListView는 업데이트되지 않습니다.

답변

12

을 내 getView()이 호출되지 않는 것은 보이지 않기 때문입니다. 내 레이아웃 xml의 높이는 TextView이고 fill_parent입니다. 따라서 전체보기에는 단일 TextView 만 표시됩니다.

해결책 : 해당 레이아웃의 그래픽보기를 확인하여 ListView이 표시되는지 확인하십시오.

+0

IMO 이것은 매우 명백하지 않은 문제입니다. 특히 'Spinner'를 표시하는 'AdapterView'를 숨기는 것이 여전히 일반적인 패러다임이기 때문에 나는 이것이 많은 사람들에게 성가신 야생 거위라는 것을 알 수 있습니다 ... – alexgophermix

1

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's the one used by your ListView 

    notifyDataSetChanged(); 
} 
+0

getCount가 5를 계속 반환하면 내 getView 메소드를 호출하면 안됩니까? 나는 당신의 제안을 시도하고 java.util.Collections $ UnmodifiableCollection.clear에서 java.lang.UnsupportedOperationException을 얻었습니다. –

+0

'getCount()'메소드는 이전의 참조가 아닌 참조를 대체 한 이후 새 목록에 포함 된 항목을 계산합니다. 기억의 어딘가에서 잃어 버렸습니다. 나는 내 대답을 편집했다. – Dalmas

+0

귀하의 예외는 귀하의 목록이 읽기 전용임을 의미합니다. 어떻게 그것을 만드나요? – Dalmas

2

확인 BaseAdapter 방법

registerDataSetObserver(DataSetObserver observer) 
unregisterDataSetObserver(DataSetObserver observer) 

은 무시되지 않습니다.

0

모든 위의 대답은() 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 
         } 
        }); 

합니다.

관련 문제