2009-08-24 40 views
11

Tôi tải dữ liệu từ Cursor đến listview, nhưng Listview của tôi không thực sự hiển thị "trơn tru". Sự thay đổi dữ liệu khi tôi kéo lên và xuống trên scollbar trong ListView của tôi. Và một số mục trông giống như hiển thị trùng lặp trong danh sách của tôi. Tôi hava một "ListView phức tạp" (hai textview, một imageview) Vì vậy, tôi đã sử dụng newView(), bindView() để hiển thị dữ liệu. Ai đó có thể giúp tôi?Làm thế nào để tải Listview "trơn tru" trong android

Trả lời

11

Tôi sẽ mô tả cho bạn cách nhận được sự cố như vậy mà bạn gặp phải. Có thể điều này sẽ giúp bạn.

Vì vậy, trong danh sách bộ chuyển đổi bạn có mã ví dụ:

public View getView(int position, View contentView, ViewGroup arg2) 
    { 
     ViewHolder holder; 

     if (contentView == null) { 
      holder = new ViewHolder(); 
      contentView = inflater.inflate(R.layout.my_magic_list,null); 
      holder.label = (TextView) contentView.findViewById(R.id.label); 
      contentView.setTag(holder); 
     } else { 
      holder = (ViewHolder) contentView.getTag(); 
     } 

     holder.label.setText(getLabel()); 

     return contentView; 
    } 

Như bạn có thể thấy, chúng ta thiết lập giá trị danh mục chỉ sau khi chúng tôi đã lấy ra giữ.

Nhưng nếu bạn di chuyển mã vào trên câu lệnh if:

holder.label.setText(getLabel()); 

vì vậy nó sẽ chăm sóc như dưới đây:

if (contentView == null) { 
    holder = new ViewHolder(); 
    contentView = inflater.inflate(R.layout.my_magic_list,null); 
    holder.label = (TextView) contentView.findViewById(R.id.label); 
    holder.label.setText(getLabel()); 
    contentView.setTag(holder); 
} 

bạn sẽ có hành vi ứng dụng hiện tại của bạn với sự trùng lặp mục danh sách.

Có thể nó sẽ hữu ích.

+0

này cũng giúp quá. Cảm ơn – Dennie

7

ListView là một con thú khôn lanh.

Câu hỏi thứ hai của bạn trước tiên: bạn đang thấy các bản sao vì ListView sử dụng lại Chế độ xem thông qua convertView, nhưng bạn không đảm bảo đặt lại tất cả các khía cạnh của chế độ xem được chuyển đổi. Đảm bảo rằng đường dẫn mã cho convertView!=null đặt đúng tất cả dữ liệu cho chế độ xem và mọi thứ sẽ hoạt động bình thường.

Bạn sẽ muốn phương pháp getView() của bạn để tìm xấp xỉ như sau nếu bạn đang sử dụng xem tùy chỉnh:

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    final MyCustomView v = convertView!=null ? (MyCustomView)convertView : new MyCustomView(); 
    v.setMyData(listAdapter.get(position)); 
    return v; 
} 

Nếu bạn không sử dụng giao diện tùy chỉnh của riêng bạn, chỉ cần thay thế các cuộc gọi đến new MyCustomView() với một cuộc gọi đến inflater.inflate(R.layout.my_layout,null)

Đối với câu hỏi đầu tiên của bạn, bạn sẽ muốn xem techtalk Romain về hiệu suất ListView ở đây: http://code.google.com/events/io/sessions/TurboChargeUiAndroidFast.html

Từ nói chuyện của mình và theo thứ tự im tầm quan từ kinh nghiệm của riêng tôi,

  • Sử dụng convertView
  • Nếu bạn có hình ảnh, không mở rộng hình ảnh của bạn một cách nhanh chóng. Sử dụng Bitmap.createScaledBitmap để tạo bitmap có tỷ lệ và đặt bitmap đó vào chế độ xem của bạn
  • Sử dụng ViewHolder để bạn không phải gọi một nhóm findViewByIds() mỗi lần
  • Giảm độ phức tạp của chế độ xem trong chế độ xem danh sách của bạn. Ít hơn các bản xem phụ, càng tốt. RelativeLayout tốt hơn nhiều so với LinearLayout. Và đảm bảo sử dụng nếu bạn đang triển khai chế độ xem tùy chỉnh.
+0

Xin lỗi, nhưng tôi sử dụng newView(), bindView() để hiển thị dữ liệu. nó có phải là vấn đề tương tự không? – Dennie

+0

Tôi nghĩ rằng tôi thấy điều gì đó hữu ích với video, cảm ơn bạn đã chia sẻ! – Dennie

1

Tôi cũng đang gặp sự cố này, nhưng trong trường hợp của tôi, tôi đã sử dụng các chuỗi để tìm nạp hình ảnh bên ngoài. Điều quan trọng là luồng thực hiện hiện tại không thay đổi imageView nếu nó được sử dụng lại!

public View getView(int position, View vi, ViewGroup parent) { 
ViewHolder holder; 
String imageUrl = ...; 

if (vi == null) { 
    vi = inflater.inflate(R.layout.tweet, null); 
    holder = new ViewHolder(); 
    holder.image = (ImageView) vi.findViewById(R.id.row_img); 
    ... 
    vi.setTag(holder); 
} else { 
    holder = (ViewHolder) vi.getTag();  
} 
holder.image.setTag(imageUrl); 
... 
DRAW_MANAGER.fetchDrawableOnThread(imageUrl, holder.image); 
} 

Và sau đó trên thread quyến rũ tôi đang làm kiểm tra quan trọng:

final Handler handler = new Handler() { 
@Override 
public void handleMessage(Message message) { 
    // VERY IMPORTANT CHECK 
    if (urlString.equals(url)) 
     imageView.setImageDrawable((Drawable) message.obj); 
}; 

Thread thread = new Thread() { 

@Override 
public void run() { 
    Drawable drawable = fetchDrawable(urlString); 
    if (drawable != null) { 
     Message message = handler.obtainMessage(1, drawable); 
     handler.sendMessage(message); 
    } 
}}; 
thread.start(); 

Một cũng có thể hủy bỏ các thread hiện hành nếu quan điểm của họ được tái sử dụng (như nó được mô tả here), nhưng tôi quyết định chống lại điều này vì tôi muốn lấp đầy bộ nhớ cache để sử dụng lại sau này.

0

Bạn có thể xem văn bản định kỳ trong nhiều hàng nếu bạn xử lý văn bản theo cách sai. Gần đây tôi đã viết blog một chút về nó - xem here. Ngoài ra, bạn có thể muốn xem ListView performance optimization. Nói chung nó là do xem lại sử dụng và tôi đã nhìn thấy nó vài lần rồi.

1

Chỉ cần một tip: KHÔNG BAO GIỜ sử dụng nền trong suốt của bố cục mục - nó làm chậm hiệu suất đáng kể

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