2009-08-24 7 views
11

私はCursorからリストビューにデータをロードしますが、リストビューは実際には「滑らか」ではありません。私のListViewのScollbarを上下にドラッグすると、データが変わります。そして、私のリストには重複した表示のようなものがあります。 私は "複雑なListView"(2つのtextview、1つのimageview)を持っていたので、newView()、bindView()を使ってデータを表示しました。誰か助けてくれますか?アンドロイドでリストビューをスムーズに読み込む方法

答えて

11

このような問題を解決する方法について説明します。これはおそらくあなたを助けるでしょう。

ので、リストアダプタであなたは、このようなコードを持っている:あなたが見ることができるように

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

を、我々はホルダーを取得した後にのみ、リスト項目の値を設定します。

しかし、あなたは上記のif文の中にコードを移動した場合:

holder.label.setText(getLabel()); 

ので、それは後に以下のようになります。

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

リスト項目の重複を使用して、現在のアプリケーションの動作を持っています。

おそらくそれが役に立ちます。

+0

大幅にパフォーマンスが低下します。これは、あまりにも役立ちます。ありがとう – Dennie

7

ListViewはトリッキーな獣です。

2番目の質問:リストビューはconvertView経由でビューを再利用するため、重複が表示されていますが、変換されたビューのすべての面をリセットする必要はありません。 convertView!=nullのコードパスでは、ビューのすべてのデータが正しく設定されていることを確認してください。すべてが正しく動作するはずです。

カスタムビュー使用している場合は、あなたのgetView()方法は、大きく次のようになりたいでしょう:あなただけでnew MyCustomView()への呼び出しを置き換える、独自のカスタムビューを使用していない場合

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

を彼の話からhttp://code.google.com/events/io/sessions/TurboChargeUiAndroidFast.html

とイムのために:あなたはここにリストビューのパフォーマンスにロマンのtechtalkを見たいと思うでしょう、あなたの最初の質問にとしてinflater.inflate(R.layout.my_layout,null)

への呼び出しあなたがイメージを持っている場合は、私自身の経験、

  • 使用convertView
  • からportanceは、その場であなたのイメージをスケーリングしません。あなたはリストビューでのビューの複雑さを減らしfindViewByIdsの束()するたびに
  • を呼び出す必要はありませんので、スケールビットマップを作成するためにBitmap.createScaledBitmapを使用して、あなたの意見
  • 使用ViewHolderにそれを置きます。サブビューが少ないほど良いでしょう。 RelativeLayoutは、LinearLayoutよりもはるかに優れています。また、カスタムビューを実装する場合は必ず使用してください。
+0

申し訳ありませんが、newView()、bindView()を使用してデータを表示します。それは同じ問題ですか? – Dennie

+0

私はビデオで役に立つものを見つけたと思う、共有のおかげで! – Dennie

1

私はこの問題に直面していますが、私の場合はスレッドを使用して外部画像を取得しました。再利用されている場合、現在実行中のスレッドはimageViewを変更しないことが重要です!

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

そして、フェッチスレッド上で、私は重要なチェックをやってる:

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

一つの彼らの見解が再利用されている場合(それはhereに記載されているような)も、現在のスレッドをキャンセルすることができ、私は後で再利用できるようにキャッシュを埋めるためにこれに反対して決めました。

0

間違った方法で再処理テキストを処理すると、再読み込みテキストが複数の行に表示されます。私は最近それについて少しブログしました - hereを参照してください。それ以外の場合は、ListView performance optimizationをご覧ください。一般的にビューの再利用のためです。私はそれを数回見ました。

1

ただ、1チップ:アイテムのレイアウトの透明な背景を使用しないでください - それは

関連する問題