4

画像とテキストがグリッド ビューに表示され、ユーザーが下にスクロールすると次の 10 項目 (画像とテキスト) が表示される Android アプリケーションを開発しました。この問題は、adapter.notifyDataSetChanged() 呼び出しの後にアダプターの getView メソッドが呼び出されると発生します。アダプターはデータをリサイクルしますが、位置は再配置され、グリッド ビューで繰り返されます。convertView が null かどうかを確認する条件を追加するまで、この問題に直面していませんでした。

活動クラス :

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)

最初のスクロール終了後

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 であることがわかります。

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

助けてください。

4

3 に答える 3

13

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

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

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

あなたがすべきことです。

実行した結果、convertViewnullでない場合は、データを更新せずにconvertViewを返すだけであったため、画像が繰り返されていました。convertViewnullの場合にのみ、データを設定しました。

アダプタとリストビューシステム間のコントラクト:渡されたconvertViewものがnullの場合は、新しいものを作成し、そうでない場合は再利用します。

于 2011-08-05T09:21:19.457 に答える
4

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

于 2011-08-05T09:28:17.447 に答える
0

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

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

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

于 2014-06-11T07:10:43.337 に答える