2011-08-05 5 views
4

イメージとテキストがグリッド表示で表示されるアンドロイドアプリケーションを開発しました。ユーザーが次にスクロールすると10個のアイテム(イメージとテキスト)が表示されます。アダプターのgetViewメソッドがadapter.notifyDataSetChanged()呼び出しの後に呼び出されるとき、問題が発生します。アダプターはデータをリサイクルしますが、位置は再配置され、グリッド表示で繰り返されます。 convertViewがnullであるかどうかをチェックする条件を追加するまで、私はこの問題に直面していませんでした。ビューが存在する場合でもconvertViewがnullとして渡されます

Activityクラス:

public class DynamicListViewActivity extends Activity implements 
    OnScrollListener { 

int visibleElements; 
int scrollState; 
int count; 
TextAdapter adapter = new TextAdapter(); 
int total=200;// total items limit in grid view 


@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    setContentView(R.layout.grid); 
    count=10; 
    GridView grid = (GridView) findViewById(R.id.gridview); 
    grid.setAdapter(adapter); 
    grid.setOnScrollListener(this); 

} 

public void onScroll(AbsListView view, int firstVisible, int visibleCount, 
     int totalCount) { 
    visibleElements= visibleCount; 
} 

public void onScrollStateChanged(AbsListView v, int s) { 
    Log.d("ScrollState", s+""); 
    scrollState=s; 
    isScrollStateComplete(); 
} 

public void isScrollStateComplete(){ 
if(visibleElements>0 && scrollState==SCROLL_STATE_IDLE && total>count){ 
     int diff=total-count; 
     count+=(diff>=10)?10:diff;//update count to next ten items 
     adapter.notifyDataSetChanged(); 
    } 
} 


class TextAdapter extends BaseAdapter { 
    public int getCount() { 
     return count; 
    } 

    public Object getItem(int pos) { 
     return pos; 
    } 

    public long getItemId(int pos) { 
     return pos; 
    } 

    public View getView(int pos, View convertView, ViewGroup p) { 

     View v = convertView; 
     System.out.println("pos : "+pos+" boolean "+(v==null));// log to check position and convertView 
        if(v==null){ 
      v =((LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.textlayout,null); 

      ImageView iv = (ImageView) v.findViewById(R.id.album_thumbnail); 
      iv.setImageDrawable(getResources().getDrawable(R.drawable.icon)); 

      TextView tvAlbumName = (TextView)v.findViewById(R.id.album_name); 
      tvAlbumName.setText("postion "+pos); 

      TextView tvAlbumDesc = (TextView)v.findViewById(R.id.album_description); 
      tvAlbumDesc.setText(""); 

      } 

      return v; 
    } 
} 
} 

正しくグリッドビューディスプレイをスクロールする前に。ログ:

08-05 14:24:34.440: INFO/ActivityManager(58): Starting activity: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.mis.list.demo/.DynamicListViewActivity } 
08-05 14:24:34.642: INFO/System.out(685): pos : 0 boolean true 
08-05 14:24:34.710: INFO/System.out(685): pos : 0 boolean false 
08-05 14:24:34.710: INFO/System.out(685): pos : 1 boolean true 
08-05 14:24:34.730: INFO/System.out(685): pos : 2 boolean true 
08-05 14:24:34.800: INFO/System.out(685): pos : 3 boolean true 
08-05 14:24:34.860: INFO/System.out(685): pos : 4 boolean true 
08-05 14:24:34.880: INFO/System.out(685): pos : 5 boolean true 
08-05 14:24:34.910: INFO/System.out(685): pos : 6 boolean true 
08-05 14:24:34.920: INFO/System.out(685): pos : 7 boolean true 
08-05 14:24:34.960: INFO/System.out(685): pos : 0 boolean true 
08-05 14:24:35.030: INFO/ActivityManager(58): Displayed activity com.mis.list.demo/.DynamicListViewActivity: 520 ms (total 520 ms) 

を第1スクロール

08-05 14:26:15.740: DEBUG/ScrollState(685): 1 
08-05 14:26:15.830: DEBUG/dalvikvm(685): GC_EXTERNAL_ALLOC freed 3624 objects/257464 bytes in 71ms 
08-05 14:26:16.210: INFO/System.out(685): pos : 8 boolean false 
08-05 14:26:16.210: INFO/System.out(685): pos : 9 boolean true 
08-05 14:26:16.250: DEBUG/ScrollState(685): 0 
08-05 14:26:16.260: INFO/System.out(685): pos : 0 boolean true 
08-05 14:26:16.271: INFO/System.out(685): pos : 0 boolean false 
08-05 14:26:16.271: INFO/System.out(685): pos : 1 boolean false 
08-05 14:26:16.271: INFO/System.out(685): pos : 2 boolean false 
08-05 14:26:16.271: INFO/System.out(685): pos : 3 boolean false 
08-05 14:26:16.271: INFO/System.out(685): pos : 4 boolean false 
08-05 14:26:16.271: INFO/System.out(685): pos : 5 boolean false 
08-05 14:26:16.280: INFO/System.out(685): pos : 6 boolean false 
08-05 14:26:16.280: INFO/System.out(685): pos : 7 boolean false 
08-05 14:26:16.280: INFO/System.out(685): pos : 8 boolean false 
08-05 14:26:16.280: INFO/System.out(685): pos : 9 boolean false 
08-05 14:26:16.280: INFO/System.out(685): pos : 10 boolean false 
08-05 14:26:16.280: INFO/System.out(685): pos : 11 boolean true 
08-05 14:26:16.371: DEBUG/dalvikvm(685): GC_EXTERNAL_ALLOC freed 644 objects/33224 bytes in 41ms 
08-05 14:26:45.270: WARN/KeyCharacterMap(685): No keyboard for id 0 
08-05 14:26:45.270: WARN/KeyCharacterMap(685): Using default keymap: /system/usr/keychars/qwerty.kcm.bin 
08-05 14:26:45.341: INFO/System.out(685): pos : 12 boolean true 
08-05 14:26:45.351: INFO/System.out(685): pos : 13 boolean true 
08-05 14:26:45.371: INFO/System.out(685): pos : 14 boolean true 
08-05 14:26:45.380: INFO/System.out(685): pos : 15 boolean true 
08-05 14:26:45.450: INFO/System.out(685): pos : 16 boolean false 
08-05 14:26:45.450: INFO/System.out(685): pos : 17 boolean false 
08-05 14:26:45.460: INFO/System.out(685): pos : 18 boolean false 
08-05 14:26:45.460: INFO/System.out(685): pos : 19 boolean false 

の終わりしかし、繰り返される値ではなく、それはすべき順にグリッドが表示されたら。 申し訳ありません私は新しいユーザーであるため、画像を投稿することはできません。

ログでは、位置0ではconvertView == nullがtrueです。

現在使用されている画像ビューのアンドロイドアイコンの代わりに画像をダウンロードする予定ですので、この権利を設定する方法。

助けてください。

+0

ビューを再利用することができない場合、AndroidはconvertViewパラメータにnullを渡します – Nepster

答えて

13

あなたのconvertViewの解釈が正しくありません。

public View getView(int pos, View convertView, ViewGroup p) { 

    View v = convertView; 

    //If convertView is null create a new view, else use convert view 
    if(v==null) 
     v =((LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.textlayout,null); 

    ImageView iv = (ImageView) v.findViewById(R.id.album_thumbnail); 
    iv.setImageDrawable(getResources().getDrawable(R.drawable.icon)); 

    TextView tvAlbumName = (TextView)v.findViewById(R.id.album_name); 
    tvAlbumName.setText("postion "+pos); 

    TextView tvAlbumDesc = (TextView)v.findViewById(R.id.album_description); 
    tvAlbumDesc.setText(""); 


    return v; 
} 

です。

convertViewがnullでない場合、データを更新せずにconvertViewを返すだけだったため、イメージが繰り返し表示されていました。 convertViewがnullの場合のみ、データを設定していました。

アダプタとリストビューシステム間の契約:convertViewがnullの場合は新しいものを作成し、それ以外の場合は再利用してください。

+0

返信いただきありがとうございます。しかし、私は既存のビューを再現したくないのと同じことをやっています。あなたはコードを見ることができます。convertViewがnullの場合、ビューを作成して最後にビューを返します。私はそれが動作するかどうかを確認するためにelse文を追加しましたが、結果は同じです。 – Megna

+0

これをシステムに残す必要があります。システムはこれを最適化します。また、getView(View、Position)が呼び出されたときに、実行していないPositionでデータをViewに更新する必要があります。 [こちらをご覧ください](www.youtube.com/watch?v=wDBM6wVEO70) –

+0

おかげでビクラム。私はそれを確認し、是正するでしょう。ありがとう、トン。今私はそれを得る。 :) – Megna

3

Vikram Bodicherlaは正しいです(+1)。実装が間違っていて、彼のコードサンプルが問題を適切に修正しています。しかし、私は次のGoogle I/O 2010の話:The world of ListViewをお勧めしたいと思います。 1時間ですが、ListViewがどのように機能し、どのようにアダプタを正しく作成する必要があるかをより深く理解することができます。

0

Androidが、行を表すViewが表示されなくなったと判断した場合、getView()メソッドはconvertViewパラメータで再利用することができます。

パフォーマンス最適化アダプターは、新しいデータをconvertViewに割り当てます。これにより、XMLファイルを膨らませたり、新しいJavaオブジェクトを作成したりすることがなくなります。

ビューを再利用することができない場合、AndroidはconvertViewパラメータにnullを渡します。したがって、アダプタの実装ではこれをチェックする必要があります。

関連する問題