0

ListView で次のエラーが発生します。

java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread. Make sure your adapter calls notifyDataSetChanged() when its content changes.

私のアプリには、CustomAdapter を持つ ListView があります。

OnCreate メソッドには次のものがあります。

list = new ArrayList<FriendVO>();
mListView = (ListView) this.findViewById(R.id.listView1);
    mFriendAdapter =  new FriendAdapter(null);
    mListView.setAdapter(mFriendAdapter);

また、Web サービスからデータを取得して ListView を埋める AsyncHttpResponseHandler もあります。すべてがうまく機能します。AsyncHttpResponseHandler の onFinish() メソッドで、リスト ビューのデータを更新しています。

メソッド onFinish() にたどり着いたとき、私はすでにデータのリストを持っています。

@Override
        public void onFinish(){

                    mFriendAdapter.setData(list);
                    mListView.setOnItemClickListener(itemClickListener);
        }

これが私のカスタムアダプターです:

private class FriendAdapter extends BaseAdapter {

    private List<FriendVO> mData;
    private LayoutInflater mInflater;

    public FriendAdapter(List<FriendVO> data) {
        mData = data;
        mInflater = FaceVsFaceActivity.this.getLayoutInflater();
    }

    public void setData(List<FriendVO> data) {
        mData = data;
        this.notifyDataSetChanged();
    }

    @Override
    public int getCount() {
        if (mData != null)
            return mData.size();
        else
            return 0;
    }

    @Override
    public Object getItem(int position) {
        return mData.get(position);
    }

    @Override
    public long getItemId(int position) {
        // TODO: If id is needed, change it
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        RowViewsHolder holder;
        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.friend_row, parent, false);
            holder = new RowViewsHolder(convertView);
            convertView.setTag(holder); // Save inside view the holder.
        } else {
            holder = (RowViewsHolder) convertView.getTag();
        }

        FriendVO vo = mData.get(position);
        holder.eventName.setText(vo.getName());

        holder.eventImage.setImageResource(R.drawable.image);

        return convertView; 
    }   
}

private class RowViewsHolder {
    private ImageView eventImage;
    private TextView eventName;

    public RowViewsHolder(View rowView) {
        eventImage = (ImageView) rowView.findViewById(R.id.img_friend);
        eventName = (TextView) rowView.findViewById(R.id.friend_name);

        }
}

これにはどのような解決策がありますか?リストを使用すると(スクロール、クリック)、データが更新されているときにエラーが発生すると思います。少し助けてください。

4

2 に答える 2

0

UI スレッドではないスレッドからアダプターを変更していますが、Android はそれを好みません。Activity.runOnUiThread()メソッドを使用し て mFriendAdapter.setData(list); を呼び出すことができます。この例外を呼び出して回避します。Runnable でラップする必要があります。

于 2014-02-10T20:45:53.543 に答える
0

AsyncHttpResponseHandler のドキュメントから「すべての処理は、これら 4 つのメソッドのいずれかで処理し、UI スレッドで新しい実行可能オブジェクトを呼び出すか、UI スレッドで実行される onFinish で処理する必要があります」

したがって、onFinish でアダプターを設定することは問題ではありません。

私は物事を null に設定し、必要がなければ後で変更するのが好きではないので、onCreate に変更を加えました。また、setData ではなく、notifyDataSetChanged を呼び出すことをお勧めします。これを試してみて、何が起こるか教えてください。

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_contact_picker_main);

        list = new ArrayList<FriendVO>();
        mListView = (ListView) this.findViewById(R.id.listView1);

        mFriendAdapter =  new FriendAdapter(list);
        mListView.setAdapter(mFriendAdapter);

    }

@Override
    public void onFinish(){

        mFriendAdapter.notifyDataSetChanged();
        mListView.setOnItemClickListener(itemClickListener);
    }

また、これを変更します。

@Override
    public int getCount() {
        if (mData != null)
            return mData.size();
        else
            return 0;
    }

これに:

@Override
    public int getCount() {
        return mData.size();
    }

mData が null であってはなりません (最悪の場合、空になるため、サイズはゼロになります)。そうである場合は、修正が必要な問題があります。この null チェックは、望ましくない問題に気付かないだけです。

そして最後に。アダプターは、任意のオブジェクトを mData として渡すことができるように設定されています。getItem を Object から FriendVO に変更して、制御と一貫性を向上させます。

于 2014-02-10T20:49:23.820 に答える