web-dev-qa-db-ja.com

notifyDataSetChanged()はリストを更新し、スクロールして先頭に戻ります

無限スクロールリストビューを実装しようとしていますが、notifyDataSetChanged()を呼び出すと、リスト全体が更新され、スクロール位置が先頭に戻ります。

これは通常の動作ですか?更新せずに追加されたアイテムを単純に追加し、スクロール位置を維持するにはどうすればよいですか?

29

このような動作は正常ではありません。あなたのコードを見ることなく、私は以下を提案することができます:

1)UIスレッドからnotifyDataSetChanged()を呼び出していません。正しい方法:

_runOnUiThread(new Runnable() {
    public void run() {
        adapter.notifyDataSetChanged();
    }
});
_

2)誤ってadapter.notifyDataSetInvalidated();を呼び出しているかどうか

3)アダプタでadapter.notifyDataSetChanged();メソッドをオーバーライドし、トップに移動するための命令を追加しました

4)リストを使用してアダプターにデータを入力している場合-毎回新しいリストを提供するため、アダプターの設定が更新されます。常に同じリストを提供する必要があります。ただし、必要なだけ変更できます。リストをリセットする場合は、list = new ArrayList();の代わりに_list.clear_を使用します

これが私のアダプターの例です:

_public class Adapter extends BaseAdapter {

    private Activity activity;
    private ArrayList<HashMap<String, String>> data;
    private static LayoutInflater inflater = null;
    public ImageLoader imageLoader;

    public MediaItemAdapter(Activity a, ArrayList<HashMap<String, String>> d) {
        activity = a;
        data = d;
        inflater = (LayoutInflater) activity
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        imageLoader = new ImageLoader(activity.getApplicationContext());
    }

    public int getCount() {
        return data.size();
    }

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

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

    public View getView(int position, View convertView, ViewGroup parent) {
        View vi = convertView;
        if (convertView == null) {
            vi = inflater.inflate(R.layout.item_composer, null);
        }
        TextView title = (TextView) vi.findViewById(R.id.item_title); // title
        TextView price = (TextView) vi.findViewById(R.id.price);


        return vi;
    }


}
_

アダプターの呼び出し:

_List myList = new ArrayList<HashMap<String, String>>();
Adapter ma = new Adapter(this, myList);
_

アダプタの初期化の前にmyListを空にすることができます。

次に、リストを使用して操作を行います。

_myList.add(someElement);
ma.notifyDataSetChanged();
_

すべてのアイテムを削除する必要がある場合:

_myList.clear();
ma.notifyDataSetChanged();
_

そのような実装は非常に無限であり、問​​題なく15000以上の要素を見ました。

63
Yarh

私の場合、問題は、新しいデータが設定されるたびにListView.setAdapter(adapter)を呼び出していたため、位置もリセットされ、ビューが先頭にジャンプすることでした。

冗長なsetAdapter(...)呼び出しを削除すると修正されました。

9
vir us

このように別の方法でそれを行うことができます

int position = scrollView.getSelectedItemPosition();
notifyDataSetChanged();
scrollView.setSelection(position);
6
Abhishek Shukla

アダプタがArrayListをサブクラス化している場合、adapter.clear()を呼び出すとnotifyDataSetChanged()が呼び出され、スクロール位置が失われます。これを防ぐには、最初にsetNotifyOnChange(false)を呼び出すことを検討してください。

詳細はこちら: https://stackoverflow.com/a/14719538/383761

2
Hugh Jeffner

@Yarthの答えは、あなたが電話した場合、これを引き起こしたことがわかった1つの小さな問題を追加するのに役立ちました

listview.setVisibility(View.VISIBLE);

また、リスト全体が上部にスクロールされます。

0
Lee Boon Kong