2013-04-09 44 views
9

Tôi đang gặp sự cố không rõ ràng liên quan đến việc tái chế chế độ xem trong phương thức getView của bộ điều hợp mảng tùy chỉnh.Chế độ xem tái chế trong bộ điều hợp mảng tùy chỉnh: chính xác nó được xử lý như thế nào?

Tôi hiểu rằng các phần tử được sử dụng lại, nhưng làm cách nào để biết chính xác những gì cần thực hiện trong phần đầu tiên của câu lệnh if và điều gì trong phần thứ hai?

Hiện tại tôi đang có mã sau. Tôi đã đưa ra câu hỏi này do bỏ mã trong phần thứ hai của câu lệnh dẫn đến danh sách 9 phần tử đầu tiên, được lặp lại nhiều lần thay vì tất cả các phần tử. Tôi thực sự không biết điều gì đang gây ra chính xác điều này ...

@Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     View row = convertView; 

     if (row == null) { 
      LayoutInflater inflater = ((Activity) context).getLayoutInflater(); 
      row = inflater.inflate(layoutResourceId, parent, false); 

      title = getItem(position).getTitle(); 
      size = calculateFileSize(position); 

      txtTitle = (TextView) row.findViewById(R.id.txtTitle); 
      tvFileSize = (TextView) row.findViewById(R.id.tvFileSize); 

      txtTitle.setText(title); 
      tvFileSize.setText(size); 

     } else { 

      title = getItem(position).getTitle(); 
      size = calculateFileSize(position); 

      txtTitle = (TextView) row.findViewById(R.id.txtTitle); 
      tvFileSize = (TextView) row.findViewById(R.id.tvFileSize); 

      txtTitle.setText(title); 
      tvFileSize.setText(size); 
     } 

     return row; 
    } 
+0

Cảm ơn tất cả các bạn cho lời giải thích nhanh chóng và tốt ! Có một số đọc/xem để làm :) Thực sự đánh giá cao nó! –

+0

có thể trùng lặp của [tại sao các ViewHolder pattren làm việc?] (Http://stackoverflow.com/questions/5973917/why-does-the-viewholder-pattren-work) –

Trả lời

13

Tôi hiểu rằng yếu tố này được tái sử dụng, nhưng làm thế nào để tôi biết chính xác những gì để thực hiện trong phần đầu của câu lệnh if, và những gì trong lần thứ hai?

Việc tổ chức khá đơn giản khi bạn nhận được hang của nó:

public View getView(int position, View convertView, ViewGroup parent) { 

    if (convertView == null) { 
     /* This is where you initialize new rows, by: 
     * - Inflating the layout, 
     * - Instantiating the ViewHolder, 
     * - And defining any characteristics that are consistent for every row */ 
    } else { 
     /* Fetch data already in the row layout, 
     * primarily you only use this to get a copy of the ViewHolder */ 
    } 

    /* Set the data that changes in each row, like `title` and `size` 
    * This is where you give rows there unique values. */ 

    return convertView; 
} 

Đối với giải thích chi tiết về cách RecycleBin ListView của hoạt động và lý do tại sao ViewHolders rất quan trọng đồng hồ Turbo Charge your UI, Google I/O trình bày bởi Android dẫn lập trình ListView.

+0

Liên kết tuyệt vời, Sam! Tôi chuẩn bị đăng bài đó cho đến khi tôi thấy bạn đã làm. Lần đầu tiên tôi học về điều này từ bạn ở đây và nó rất hữu ích. Cảm ơn! – codeMagic

+0

Xin cảm ơn, đó là một lựa chọn cho tôi. Bạn có thể đăng nó hay thậm chí là bài thuyết trình tiếp theo "World of ListView". Có quá nhiều thứ để học hỏi từ các bài thuyết trình I/O. – Sam

+0

Tôi thường đăng liên kết đó lên các câu hỏi như vậy nhưng tôi luôn trao tín dụng cho bạn để tôi biết. Tôi muốn thấy những người khác nhưng tôi chưa định vị người khác. Tôi sẽ tìm kiếm cái đó. – codeMagic

15

Thật dễ dàng. Lần đầu tiên không có hàng nào được tạo ra, vì vậy bạn phải thổi phồng chúng. Sau đó, hệ điều hành Android có thể quyết định tái chế các chế độ xem mà bạn đã tăng cao và không hiển thị nữa. Chúng đã được thổi phồng và chuyển vào tham số convertView, vì vậy tất cả những gì bạn phải làm là sắp xếp nó để hiển thị mục hiện tại mới, ví dụ như đặt đúng giá trị vào các trường văn bản khác nhau.

enter image description here

Nói tóm lại, trong phần đầu tiên bạn nên thực hiện lạm phát và điền vào các giá trị, trong lần thứ hai if (if convertView != null), bạn chỉ nên ghi đè lên lĩnh vực này bởi vì, cho quan điểm đã được tái chế, TextView chứa các giá trị của mục cũ.

This postthis là điểm khởi đầu tốt

+0

+1 cho sơ đồ –

4

Tôi khuyên bạn nên sử dụng dạng xem và mẫu chuyển đổi chế độ xem để tạo listView của bạn vì nó sẽ hiệu quả hơn. Here là giải thích tốt về cách hoạt động với chiến lược tái sử dụng. Điều này sẽ trả lời câu hỏi của bạn về cách tái đạp xe hoạt động. Nếu bạn muốn tham khảo một mẫu mã, tôi có nó trên GitHub.

Hy vọng điều này sẽ hữu ích.

1

Phần cuối cùng của câu hỏi tôi thực sự không thể hiểu được mà không có hình ảnh về hiệu ứng nhưng đối với phần đầu tiên "những gì cần thực hiện trong phần đầu tiên của câu lệnh if và nội dung thứ hai" Tôi nghĩ rằng tôi ' đã tìm thấy việc thực hiện này rất phổ biến.

Bạn sẽ tìm thấy tham chiếu lượt xem trước và lưu trữ chúng vào lớp tĩnh ViewHolder mà sau đó bạn đính kèm vào thẻ của chế độ xem được tăng cao mới. Khi listview tái chế các khung nhìn và convertView được chuyển qua getView, bạn sẽ có được ViewHolder từ thẻ của convertView để bạn không phải tìm lại tài liệu tham khảo (cải thiện đáng kể hiệu suất) và cập nhật dữ liệu xem với đối tượng của bạn tại vị trí đã cho.

Về mặt kỹ thuật, bạn không quan tâm vị trí của chế độ xem vì tất cả những gì bạn quan tâm là các tham chiếu đến các chế độ xem bạn cần cập nhật được giữ trong ViewHolder.

@Override 
public View getView(int position, View convertView, ViewGroup container) { 
    ViewHolder holder; 
    Store store = getItem(position); 
    if (convertView == null) { 
     convertView = mLayoutInflater.inflate(R.layout.item_store, null); 

     // create a holder to store references 
     holder = new ViewHolder(); 

     // find references and store in holder 
     ViewGroup logoPhoneLayout = (ViewGroup) convertView 
       .findViewById(R.id.logophonelayout); 
     ViewGroup addressLayout = (ViewGroup) convertView 
       .findViewById(R.id.addresslayout); 

     holder.image = (ImageView) logoPhoneLayout 
       .findViewById(R.id.image1); 
     holder.phone = (TextView) logoPhoneLayout 
       .findViewById(R.id.textview1); 
     holder.address = (TextView) addressLayout 
       .findViewById(R.id.textview1); 

     // store holder in views tag 
     convertView.setTag(holder); 
    } else { 

     // Retrieve holder from view 
     holder = (ViewHolder) convertView.getTag(); 
    } 

    // fill in view with our store (at this position) 
    holder.phone.setText(store.phone); 
    holder.address.setText(store.getFullAddress()); 

    UrlImageViewHelper.setUrlDrawable(holder.image, store.storeLogoURL, 
      R.drawable.no_image); 

    return convertView; 
} 

private static class ViewHolder { 
    ImageView image; 
    TextView phone; 
    TextView address; 
} 
5

Bạn muốn tạo một lớp học ViewHolder trong MainActivity của mình. Một cái gì đó như

static class ViewHolder 
    { 
     TextView tv1; 
     TextView tv2; 
    } 

sau đó trong getView của bạn, lần đầu tiên bạn nhận được từ xml của bạn trong if bạn Views và tái sử dụng chúng sau đó trong else

View rowView = convertView; 
     if (rowView == null) 
     { 
      LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
      rowView = inflater.inflate(R.layout.layout_name_to_inflate, parent, false); 
      holder = new ViewHolder(); 
      holder.tv1= (TextView) rowView.findViewById(R.id.textView1); 
      holder.tv2 = (RadioGroup) rowView.findViewById(R.id.textView2);    
      rowView.setTag(holder); 
     } 
     else 
     { 
      holder = (ViewHolder) rowView.getTag(); 
     }