13

リスト全体をリロードせずに ListView に項目を追加する方法があるかどうか疑問に思っています。

BaseAdapter から派生した ListView アダプターがあり、基になるモデルに新しい要素が追加されると、notifyDataSetChanged() が呼び出され、ListView のリロードがトリガーされます。

リスト内の要素には画像があり、要素のコンテンツに従って動的に読み込まれます。問題は、リロード中に getView() が呼び出されると、再利用のために渡された convertView パラメータが以前の別の位置からのものであるため、画像もリロードする必要があり、かなり醜い点滅が発生することです。

最後にアイテムを追加するだけでリスト全体をリロードしない方法はありますか (それが新しいアイテムを追加する唯一の方法になります)。または、可能であれば、コストのかかる画像のリロードを回避するために、少なくとも何らかの方法で同じ位置のセルを再利用しますか?

4

4 に答える 4

5

Android では、アイテムを追加するとリスト ビューの高さが変わるため、リストを更新せずにアイテムを追加することはできません。以下のリンクを参照してください。Romain Guy は同じことを言っています。

http://groups.google.com/group/android-developers/browse_thread/thread/7e54522c37772d04/05abfd17b59b07f7?lnk=gst&q=how+to+add+list+item+in+listview+without+reload+the+listview+# 05abfd17b59b07f7

于 2011-11-23T05:08:18.150 に答える
1

まあ、それは可能です。

ArrayAdapter のメソッド getView および add をオーバーライドします。

たとえば、テストケースとして何をしたか:

public class custom_row extends ArrayAdapter<String> {

String newItem = "";
Boolean doRefresh = true;

public custom_row(Context context, int resource, ArrayList<String> objects) {
    super(context, resource, objects);
}

public custom_row(Context context, int resource, String[] objects) {
    super(context, resource, objects);
}

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

    if (doRefresh == false && itemValue != newItem) {
        return convertView;
    }

    LayoutInflater inflater = LayoutInflater.from(getContext());

    View customView = inflater.inflate(R.layout.customr_row, parent, false);
    ImageView myImageView = (ImageView) customView.findViewById(R.id.imageView);

    String url = "https://urltoimage/image.jpg";

    (new DownloadImageTask(myImageView)).execute(url);

    TextView myTextView = (TextView) customView.findViewById(R.id.myCustomText);
    myTextView.setText(itemValue);

    return customView;
}

public void addNewItemToList(String item) {
    this.newItem = item;
    this.doRefresh = false;
    add(item);
}

private class DownloadImageTask extends AsyncTask<String, Integer, Bitmap>{
    private ImageView mImageView;

    public DownloadImageTask(ImageView imageView) {
        this.mImageView = imageView;
    }

    @Override
    protected Bitmap doInBackground(String... params) {
        URL url = null;
        Bitmap bmp = null;

        try {
            url = new URL(params[0]);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }

        try {
            InputStream stream = url.openStream();
            bmp = BitmapFactory.decodeStream(stream);

        } catch (IOException e) {
            e.printStackTrace();
        }

        return bmp;
    }

    @Override
    protected void onPostExecute(Bitmap bmp) {
        this.mImageView.setImageBitmap(bmp);
    }
}

}

初めてすべてのアイテムをロードすると、非同期スレッドによって画像が動的にロードされます。メソッド getView のコードの次の部分は、リストが完全に更新されないようにするため、画像の点滅を防ぎます。

    String itemValue = getItem(position);

    if (doRefresh == false && itemValue != newItem) {
        return convertView;
    }

新しい項目がリストに追加されると、ArrayAdapter はリストを再度調べます。現在の位置にあるアイテムが新しく追加されたアイテムかどうかを確認するだけです。そうでない場合は、古いビューである convertView を返すか、アイテムをロードしてカスタム ビューを返します。

于 2016-03-03T11:45:59.803 に答える
1

notifyDataSetChanged() を呼び出す代わりにこれを行います。

int firstVisiblePosition = getFirstVisiblePosition();
View view = getChildAt(0);
int distFromTop = (view == null) ? 0 : view.getTop();
setSelectionFromTop(firstVisiblePosition, distFromTop);
于 2012-05-25T11:43:15.653 に答える