2013-04-29 36 views
5

tôi đang sử dụng bộ điều hợp tùy chỉnh chế độ xem danh sách để hiển thị hình ảnh và tiêu đề. Trong ứng dụng của tôi, tôi thêm và xóa các mục trong danh sách và tôi phải hiển thị các thay đổi đó trên giao diện. về bất kỳ thay đổi nào trong dữ liệu tôi nhận được tất cả danh sách từ cơ sở dữ liệu và lưu trữ nó trong danh sách bộ điều hợp và sau đó gọi adapter.notifyDataSetChanged(); nhưng giao diện không hiển thị bất kỳ thay đổi nào. mặt khác khi tôi trực tiếp thêm hoặc xóa mục khỏi bộ điều hợp, nó phản hồi chính xác. tôi đã sử dụng bộ điều hợp đơn giản và cho adapter.notifyDataSetChanged(); đang hoạt động tốt nhưng tùy chỉnh nó không phản hồi. tôi cũng đã thử nhiều giải pháp trên stackoverflow nhưng không phải của họ làm việc. như Updating the list view when the adapter data changestùy chỉnh adapter.notifyDataSetChanged() không hoạt động

Android List view refresh

Adapter.notifyDataSetChanged() is not working

notifyDataSetChange not working from custom adapter

tôi làm điều này như folows tại onCreate

enter code here 

      product_data = new ArrayList<Product>(); 
    Bundle extras = getIntent().getExtras(); 
    if (extras != null) { 
     value = extras.getInt("list_id"); 
    } 
    product_data = db.getAllProductsstatus(value, 1); 
    Collections.reverse(product_data); 

    adapter = new ProductAdopter(this, 
      R.layout.listview_item_row, product_data, 2); 
    ListView listView1 = (ListView)findViewById(R.id.listView1); 
    listView1.setAdapter(adapter); 
    registerForContextMenu(listView1); 

và trong onMenuItemSelected

enter code here 
@Override 
public boolean onMenuItemSelected(int featureId, MenuItem item) { 
    AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)item.getMenuInfo(); 

     int menuItemIndex = item.getItemId(); 
     String listItemName = adapter.getItem(info.position)._name; 
     int id = adapter.getItem(info.position)._id; 

     if(menuItemIndex == 0) 
     { 

      db.deleteProduct(adapter.getItem(info.position)); 

      product_data = db.getAllProducts(value); 
      Collections.reverse(product_data); 
      //adapter.remove(adapter.getItem(info.position)); 
      adapter.notifyDataSetChanged(); 
     } 
     else if(menuItemIndex == 1){ 
      String name ; 
      if (adapter.getItem(info.position)._status == 0){ 
       popall("bar code", "no bar code entered");     
      } 
      else { 
      popall("bar code", adapter.getItem(info.position)._bar_code); 
      } 
     } 
     else if (menuItemIndex == 2){ 
      adapter.getItem(info.position)._status = 0; 
      adapter.getItem(info.position)._bar_code = "0"; 
      db.updateProduct(adapter.getItem(info.position)); 
       product_data = db.getAllProductsstatus(value, 1); 
      adapter.notifyDataSetChanged(); 

      popall("alert", "successfully done"); 
     } 
     return true; 
} 

tùy chỉnh lớp adapter của tôi được đưa ra dưới đây

public class ProductAdopter extends ArrayAdapter<Product> { 
    Context context; 
    int layoutResourceId;  
    List<Product> data = null; 
    int source; 
    public ProductAdopter(Context context, int layoutResourceId, List<Product> product_data, int source) { 
     // TODO Auto-generated constructor stub 
     super(context, layoutResourceId, product_data); 
     this.layoutResourceId = layoutResourceId; 
     this.context = context; 
     this.data = product_data; 
     this.source = source; 
    } 
    // public ProductAdopter(MainActivity context2, int listviewItemRow, List<Product> product_data) { 
     // TODO Auto-generated constructor stub 
    //} 
    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     View row = convertView; 
     ProductHolder holder = null; 

     if(row == null && source == 1) 
     { 
      LayoutInflater inflater = ((MainActivity)context).getLayoutInflater(); 
      row = inflater.inflate(layoutResourceId, parent, false); 

      holder = new ProductHolder(); 
      holder.imgIcon = (ImageView)row.findViewById(R.id.imgIcon); 
      holder.txtTitle = (TextView)row.findViewById(R.id.txtTitle); 

      row.setTag(holder); 
     } 
     if(row == null && source == 2) 
     { 
      LayoutInflater inflater = ((purchased)context).getLayoutInflater(); 
      row = inflater.inflate(layoutResourceId, parent, false); 

      holder = new ProductHolder(); 
      holder.imgIcon = (ImageView)row.findViewById(R.id.imgIcon); 
      holder.txtTitle = (TextView)row.findViewById(R.id.txtTitle); 

      row.setTag(holder); 
     } 
     if(row == null && source == 3) 
     { 
      LayoutInflater inflater = ((Skiped)context).getLayoutInflater(); 
      row = inflater.inflate(layoutResourceId, parent, false); 

      holder = new ProductHolder(); 
      holder.imgIcon = (ImageView)row.findViewById(R.id.imgIcon); 
      holder.txtTitle = (TextView)row.findViewById(R.id.txtTitle); 

      row.setTag(holder); 
     } 


     else 
     { 
      holder = (ProductHolder)row.getTag(); 
     } 

     Product product = data.get(position); 
     holder.txtTitle.setText(product.getName()); 
     if(product.icon.equals("no")){ 
      holder.imgIcon.setImageResource(R.drawable.blank); 
     } 
     else{ 
      File imgFile = new File(product.icon); 
      if(imgFile.exists()){ 

       Bitmap myBitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath()); 
       Bitmap resized = Bitmap.createScaledBitmap(myBitmap, 70, 70, true); 

       holder.imgIcon.setImageBitmap(resized); 
       myBitmap.recycle(); 
      }   
     } 

     return row; 
    } 
    static class ProductHolder 
    { 
     ImageView imgIcon; 
     TextView txtTitle; 
    } 

} 
+0

Vâng. Đó là hành vi của ArrayAdapter <>: nó không theo dõi mảng ban đầu mà bạn cung cấp. Bạn sẽ phải thêm và xóa các đối tượng trong cả mảng và bộ điều hợp. – etienne

+0

tôi biết và đó là vấn đề mà tôi không nên thêm mục trong cả hai – user2274314

Trả lời

10

Vấn đề là ở bạn onMenuItemSelected() bạn có dòng này:

product_data = db.getAllProducts(value); 

Khi bạn đã tạo adapter trong onCreate(), bạn đã cho nó tham chiếu đến product_data. Tại thời điểm đó, các thay đổi của bạn là product_data sẽ truyền vào bộ điều hợp, vì nó có tham chiếu đến danh sách của bạn.

Nhưng ngay sau khi bạn gán danh sách mới cho biến số product_data (như bạn làm trong onMenuItemSelected()) bộ điều hợp hiện có tham chiếu đến danh sách cũ, trong khi product_data của bạn bây giờ trỏ đến danh sách mới. Vì vậy, bộ điều hợp của bạn không biết về những thay đổi của bạn trong danh sách mới.

Thay vì giao lại các thay đổi, hãy thử xoá nó và sao chép các mục của bạn như thế này:

product_data.clear(); 
product_data.addAll(db.getAllProducts(value)); 

Ngày lưu ý khác, nếu bạn đọc dữ liệu từ cơ sở dữ liệu, bạn nên xem xét sử dụng một CursorAdapter để thay thế.

Đây là một hướng dẫn đơn giản: http://blog.cluepusher.dk/2009/11/16/creating-a-custom-cursoradapter-for-android/

+0

Tôi đã xem xét điều này trong vài giờ qua và không thể tìm ra. Câu trả lời thực sự tuyệt vời, giải thích thực sự tuyệt vời. – TrueCoke

+0

Câu trả lời hoàn hảo cảm ơn –

0

Các vấn đề trong mã của bạn là, bạn đang thông báo cho bộ chuyển đổi của bạn Để làm mới danh sách, nhưng bạn không cung cấp dữ liệu tươi (I.e after add/remove items.) Để nó.

Hãy làm như sau:

if(menuItemIndex == 0) { db.deleteProduct(adapter . Get item(info.position)); product_data = db.getAllProducts(value); 
    Collections.reverse(product_data); 


    adapter = new ProductAdopter(this, R.layout.listview_item_row, product_data, 2); ListView listView1 = (ListView)findViewById(R.id.listView1); 
    listView1.setAdapter(adapter); 

//adapter.remove(adapter.getItem(info.position)); 
//adapter.notifyDataSetChanged(); 

} 

Việc làm này bạn đang cung cấp dữ liệu mới vào thiết bị tiếp hợp Vì vậy, nó sẽ làm mới xem danh sách để hiển thị thay đổi tươi dữ liệu ngay cả khi không gọi adapter.notifyDataSetChanged();

Ngoài ra bạn cần phải làm cho đối tượng xem danh sách là toàn cầu để sử dụng nó trong khi Giải quyết bộ điều hợp mới trong onMenuItemSelected()

Tôi hy vọng điều này sẽ giải quyết được vấn đề của bạn.

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