programing

Android, ListView 불법 상태 예외: "어댑터의 내용이 변경되었지만 ListView에서 알림을 받지 못했습니다."

subpage 2023. 8. 22. 22:09
반응형

Android, ListView 불법 상태 예외: "어댑터의 내용이 변경되었지만 ListView에서 알림을 받지 못했습니다."

제가 하고 싶은 일: 결과가 계산되는 동안 ListView 내용을 계산하는 백그라운드 스레드를 실행하고 ListView를 부분적으로 업데이트합니다.

피해야 할 것은 다음과 같습니다.백그라운드 스레드에서 ListAdapter 콘텐츠를 조작할 수 없으므로 AsyncTask를 상속하고 onProgressUpdate에서 결과(어댑터에 항목 추가)를 게시했습니다.내 어댑터가 결과 개체의 어레이 목록을 사용하면 해당 어레이 목록의 모든 작업이 동기화됩니다.

다른 사람들의 연구: 여기에 매우 가치 있는 데이터가 있습니다.또한 500명의 사용자 그룹에 대해 거의 매일 충돌을 겪었고, 추가했을 때list.setVisibility(GONE)/trackList.setVisibility(VISIBLE)Block in on ProgressUpdate(프로그레스업데이트), 충돌이 10배 감소했지만 사라지지는 않았습니다.(답변에서 제안되었습니다)

가 가끔 받은 것은: 제발, 그것은 정말 드물게 발생합니다(3.5k 사용자 중 한 명에게 일주일에 한 번).하지만 저는 이 버그를 완전히 제거하고 싶습니다.다음은 부분 스택 추적입니다.

`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. [in ListView(2131296334, class android.widget.ListView) with Adapter(class com.transportoid.Tracks.TrackListAdapter)]
at android.widget.ListView.layoutChildren(ListView.java:1432)
at android.widget.AbsListView.onTouchEvent(AbsListView.java:2062)
at android.widget.ListView.onTouchEvent(ListView.java:3234)
at android.view.View.dispatchTouchEvent(View.java:3709)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:852)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:884)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:884)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:884)
[...]

도움말? 더 이상 필요하지 않습니다. 아래를 참조하십시오.

최종 답변: 알고 보니, 저는 전화를 하고 있었습니다.notifyDataSetChanged5번 삽입할 때마다 깜박임 및 갑작스러운 목록 변경을 방지합니다.이러한 방식으로는 수행할 수 없습니다. 기본 목록이 변경되면 어댑터에 항상 알립니다.이 벌레는 이제 오래 전에 사라졌습니다.

저도 같은 문제가 있었습니다.

항목을 추가하는 중이었습니다.ArrayListUI 스레드 외부에 있습니다.

솔루션:난 둘 다 했어요adding the items라고 불렸습니다.notifyDataSetChanged()사용자 인터페이스 스레드에서.

저도 같은 문제가 있었지만 방법을 사용하여 수정했습니다.

requestLayout();

에서.ListView

이것은 다중 스레드 문제이며 올바르게 동기화된 블록을 사용하면 방지할 수 있습니다.UI 스레드에 추가 사항을 추가하거나 앱의 응답성을 저하시키지 않습니다.

저도 마찬가지였습니다.그리고 가장 일반적인 답변에서 알 수 있듯이 UI 스레드에서 어댑터 데이터를 변경하면 문제를 해결할 수 있습니다.그것은 효과적이지만 빠르고 쉬운 해결책이지만 최선의 해결책은 아닙니다.

일반적인 경우를 보면 알 수 있습니다.백그라운드 스레드에서 데이터 어댑터를 업데이트하고 UI 스레드에서 notifyDataSetChanged를 호출하면 작동합니다.

이 잘못된 상태 예외는 UI 스레드가 보기를 업데이트하고 다른 백그라운드 스레드가 데이터를 다시 변경할 때 발생합니다.그 순간이 이 문제를 야기합니다.

따라서 어댑터 데이터를 변경하고 알림 데이터 집합 변경 호출을 하는 모든 코드를 동기화할 수 있습니다.이 문제는 사라져야 합니다.저는 사라졌고 저는 여전히 백그라운드 스레드의 데이터를 업데이트하고 있습니다.

여기 다른 사람들이 참조할 수 있는 제 사례별 코드가 있습니다.

메인 화면의 로더는 전화번호부 연락처를 백그라운드에 있는 내 데이터 소스로 로드합니다.

    @Override
    public Void loadInBackground() {
        Log.v(TAG, "Init loadings contacts");
        synchronized (SingleTonProvider.getInstance()) {
            PhoneBookManager.preparePhoneBookContacts(getContext());
        }
    }

이 PhoneBookManager.getPhoneBookContacts는 전화번호부에서 연락처를 읽고 해시 맵에 입력합니다.목록 어댑터가 목록을 그릴 때 직접 사용할 수 있습니다.

내 화면에 버튼이 있습니다.그러면 해당 전화 번호가 나열된 활동이 열립니다.이전 스레드가 작업을 완료하기 전에 Adapter를 목록 위에 직접 설정하면 빠른 탐색 사례가 덜 발생합니다.예외가 표시됩니다.이 SO 질문의 제목입니다.그래서 저는 두 번째 활동에서 이런 것을 해야 합니다.

두 번째 활동의 로더는 첫 번째 스레드가 완료될 때까지 기다립니다.진행 표시줄이 표시될 때까지.두 로더의 loadInBackground를 확인합니다.

그런 다음 어댑터를 생성하여 UI 스레드에서 setAdapter를 호출하는 활동으로 전달합니다.

그것으로 제 문제가 해결되었습니다.

이 코드는 스니펫일 뿐입니다.당신이 잘 컴파일하기 위해서는 그것을 변경해야 합니다.

@Override
public Loader<PhoneBookContactAdapter> onCreateLoader(int arg0, Bundle arg1) {
    return new PhoneBookContactLoader(this);
}

@Override
public void onLoadFinished(Loader<PhoneBookContactAdapter> arg0, PhoneBookContactAdapter arg1) {
    contactList.setAdapter(adapter = arg1);
}

/*
 * AsyncLoader to load phonebook and notify the list once done.
 */
private static class PhoneBookContactLoader extends AsyncTaskLoader<PhoneBookContactAdapter> {

    private PhoneBookContactAdapter adapter;

    public PhoneBookContactLoader(Context context) {
        super(context);
    }

    @Override
    public PhoneBookContactAdapter loadInBackground() {
        synchronized (SingleTonProvider.getInstance()) {
            return adapter = new PhoneBookContactAdapter(getContext());    
        }
    }

}

이것이 도움이 되길 바랍니다.

2개의 Lists를 가지고 이것을 해결했습니다.어댑터에 대해서만 사용하는 하나의 목록에서 다른 목록의 모든 데이터 변경/업데이트를 수행합니다.이렇게 하면 백그라운드 스레드의 한 목록에서 업데이트를 수행한 다음 메인/오프라인의 "어댑터" 목록을 업데이트할 수 있습니다.UI 스레드:

List<> data = new ArrayList<>();
List<> adapterData = new ArrayList();

...
adapter = new Adapter(adapterData);
listView.setAdapter(adapter);

// Whenever data needs to be updated, it can be done in a separate thread
void updateDataAsync()
{
    new Thread(new Runnable()
    {
        @Override
        public void run()
        {
            // Make updates the "data" list.
            ...

            // Update your adapter.
            refreshList();
        }
    }).start();
}

void refreshList()
{
    runOnUiThread(new Runnable()
    {
        @Override
        public void run()
        {
            adapterData.clear();
            adapterData.addAll(data);
            adapter.notifyDataSetChanged();
            listView.invalidateViews();
        }
    });
}

저는 이 코드를 작성하고 2.1 에뮬레이터 이미지에서 12시간 동안 실행했지만 불법 상태 예외를 얻지 못했습니다.저는 안드로이드 프레임워크에 대해 의심의 여지가 있는 이점을 제공하고 당신의 코드에 오류가 있을 가능성이 높다고 말할 것입니다.이것이 도움이 되길 바랍니다.아마도 당신은 당신의 목록과 데이터에 그것을 적용할 수 있을 것입니다.

public class ListViewStressTest extends ListActivity {
    ArrayAdapter<String> adapter;
    ListView list;
    AsyncTask<Void, String, Void> task;

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

        this.adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);
        this.list = this.getListView();

        this.list.setAdapter(this.adapter);

        this.task = new AsyncTask<Void, String, Void>() {
            Random r = new Random();
            int[] delete;
            volatile boolean scroll = false;

            @Override
            protected void onProgressUpdate(String... values) {
                if(scroll) {
                    scroll = false;
                    doScroll();
                    return;
                }

                if(values == null) {
                    doDelete();
                    return;
                }

                doUpdate(values);

                if(ListViewStressTest.this.adapter.getCount() > 5000) {
                    ListViewStressTest.this.adapter.clear();
                }
            }

            private void doScroll() {
                if(ListViewStressTest.this.adapter.getCount() == 0) {
                    return;
                }

                int n = r.nextInt(ListViewStressTest.this.adapter.getCount());
                ListViewStressTest.this.list.setSelection(n);
            }

            private void doDelete() {
                int[] d;
                synchronized(this) {
                    d = this.delete;
                }
                if(d == null) {
                    return;
                }
                for(int i = 0 ; i < d.length ; i++) {
                    int index = d[i];
                    if(index >= 0 && index < ListViewStressTest.this.adapter.getCount()) {
                        ListViewStressTest.this.adapter.remove(ListViewStressTest.this.adapter.getItem(index));
                    }
                }
            }

            private void doUpdate(String... values) {
                for(int i = 0 ; i < values.length ; i++) {
                    ListViewStressTest.this.adapter.add(values[i]);
                }
            }

            private void updateList() {
                int number = r.nextInt(30) + 1;
                String[] strings = new String[number];

                for(int i = 0 ; i < number ; i++) {
                    strings[i] = Long.toString(r.nextLong());
                }

                this.publishProgress(strings);
            }

            private void deleteFromList() {
                int number = r.nextInt(20) + 1;
                int[] toDelete = new int[number];

                for(int i = 0 ; i < number ; i++) {
                    int num = ListViewStressTest.this.adapter.getCount();
                    if(num < 2) {
                        break;
                    }
                    toDelete[i] = r.nextInt(num);
                }

                synchronized(this) {
                    this.delete = toDelete;
                }

                this.publishProgress(null);
            }

            private void scrollSomewhere() {
                this.scroll = true;
                this.publishProgress(null);
            }

            @Override
            protected Void doInBackground(Void... params) {
                while(true) {
                    int what = r.nextInt(3);

                    switch(what) {
                        case 0:
                            updateList();
                            break;
                        case 1:
                            deleteFromList();
                            break;
                        case 2:
                            scrollSomewhere();
                            break;
                    }

                    try {
                        Thread.sleep(0);
                    } catch(InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }

        };

        this.task.execute(null);
    }
}

며칠 전에 저는 동일한 문제를 만났고 하루에 수천 건의 충돌을 일으켰으며, 약 0.1%의 사용자가 이 상황에 직면했습니다.나는 노력했다.setVisibility(GONE/VISIBLE)그리고.requestLayout()하지만 충돌 횟수는 약간 감소할 뿐입니다.

그리고 마침내 해결했습니다.에는 도 없습니다.setVisibility(GONE/VISIBLE)에는 도 없습니다.requestLayout().

마침내 나는 그 이유를 찾았습니다. 왜냐하면 나는 a를 사용했기 때문입니다.Handler을 부르다notifyDataSetChanged()데이터를 업데이트한 후 다음과 같은 결과가 발생할 수 있습니다.

  1. 모델 개체에 데이터를 업데이트합니다(데이터 소스라고 함).
  2. 사용자가 목록 보기를 누릅니다(이를 호출할 수 있음).checkForTap()/onTouchEvent()그리고 마침내 전화를 합니다.layoutChildren())
  3. 객체에서 어터가모개및체호서데이가를다져니옵터에댑출을 호출합니다.notifyDataSetChanged() views(및 업데이트 보기)

그리고 나는 또 다른 실수를 했습니다.getCount(),getItem()그리고.getView()저는 어댑터에 필드를 복사하는 대신 데이터 소스의 필드를 직접 사용합니다.마지막으로 다음과 같은 경우에 충돌합니다.

  1. 마지막 응답이 제공하는 어댑터 업데이트 데이터
  2. 다음 응답 시 데이터 소스가 데이터를 업데이트하므로 항목 수가 변경됩니다.
  3. 사용자가 목록 보기를 터치합니다. 목록 보기는 탭, 이동 또는 플립일 수 있습니다.
  4. getCount()그리고.getView()호출되고 하지 않는 하고 " 호되고는출 listview"와 같은 예외를 던집니다."와 같은 를 던집니다.java.lang.IllegalStateException: The content of the adapter has changed but...는 또다일반예다같습다니음과외는인적른▁an▁is다입니다.IndexOutOfBoundException머키글/에서 헤더ListView.

때 . 처리기가 어댑터를 트리거하여 데이터와 호출을 가져올 때 데이터 소스에서 어댑터로 데이터를 복사하기만 하면 됩니다.notifyDataSetChanged()이제 다시는 충돌이 발생하지 않습니다.

이 문제가 간헐적으로 발생한 경우, 마지막으로 '추가 로드' 항목을 클릭한 후 목록을 스크롤했을 때만 이 문제가 발생한 것으로 드러났습니다.목록을 스크롤하지 않았다면 모든 것이 정상적으로 작동했습니다.

MUCH 디버깅 후, 그것은 제 쪽의 버그였지만 안드로이드 코드의 불일치이기도 했습니다.

유효성 검사가 발생하면 이 코드가 ListView에서 실행됩니다.

        } else if (mItemCount != mAdapter.getCount()) {
            throw new IllegalStateException("The content of the adapter has changed but "
                    + "ListView did not receive a notification. Make sure the content of "

그러나 변경 시 AdapterView(ListView의 상위)에서 이 코드가 실행됩니다.

    @Override
    public void onChanged() {
        mDataChanged = true;
        mOldItemCount = mItemCount;
        mItemCount = getAdapter().getCount();

어댑터가 동일한 것으로 보장되지 않는 방식에 주의하십시오.

저의 경우, 'LoadMoreAdapter'였기 때문에 getAdapter 호출(기본 개체에 액세스하기 위해)에서 RapedAdapter를 반환했습니다.이로 인해 추가 '추가 로드' 항목과 예외가 발생하여 카운트가 서로 다릅니다.

저는 단지 의사들이 그것을 하는 것이 괜찮은 것처럼 보이게 하기 때문에 이것을 한 것입니다.

ListView.getAdapter javadoc

이 목록 보기에서 현재 사용 중인 어댑터를 반환합니다.반환된 어댑터가 setAdapter(ListAdapter)에 전달된 어댑터와 다를 수 있지만 WrapperListAdapter일 수 있습니다.

내 문제는 필터와 ListView를 함께 사용하는 것과 관련이 있습니다.

ListView의 기본 데이터 모델을 설정하거나 업데이트할 때 다음과 같은 작업을 수행했습니다.

public void updateUnderlyingContacts(List<Contact> newContacts, String filter)
{
    this.allContacts = newContacts;
    this.filteredContacts = newContacts;
    getFilter().filter(filter);
}

하기 르기filter()마막줄에그될것고이원 (그리고 반드시)가 합니다.notifyDataSetChanged()에서 publishResults()ㅠㅠ. 요. 이것은 때때로 잘 작동할지도 모릅니다, 특히 제 빠른 Nexus 5에서 말입니다.그러나 실제로는 장치 속도가 느리거나 리소스를 많이 사용하는 환경에서 발견할 수 있는 버그를 숨기고 있습니다.

문제는 필터링이 비동기적으로 수행되어, 따라서 종료 사이에 수행된다는 것입니다.filter()와 성서와호전로의 .publishResults()UI 스레드 모두에서 일부 다른 UI 스레드 코드가 실행되고 어댑터의 내용이 변경될 수 있습니다.

실제 수리는 간단합니다. 전화만 하면 됩니다.notifyDataSetChanged()또한 필터링을 수행하도록 요청하기 전에:

public void updateUnderlyingContacts(List<Contact> newContacts, String filter)
{
    this.allContacts = newContacts;
    this.filteredContacts = newContacts;
    notifyDataSetChanged(); // Fix
    getFilter().filter(filter);
}

피드 개체의 경우 목록이 있습니다.UI가 없는 스레드에서 추가되고 잘립니다.아래의 어댑터에서 작동이 잘 됩니다.부를게요FeedAdapter.notifyDataSetChangedUI 스레드에서 사용할 수 있습니다.UI가 비활성화된 경우에도 내 피드 개체가 로컬 서비스의 메모리에 남아 있기 때문에 나는 이것을 좋아합니다.

public class FeedAdapter extends BaseAdapter {
    private int size = 0;
    private final List<Feed> objects;

    public FeedAdapter(Activity context, List<Feed> objects) {
        this.context = context;
        this.objects = objects;
        size = objects.size();
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        ...
    }

    @Override
    public void notifyDataSetChanged() {
        size = objects.size();

        super.notifyDataSetChanged();
    }

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

    @Override
    public Object getItem(int position) {
        try {
            return objects.get(position);
        } catch (Error e) {
            return Feed.emptyFeed;
        }
    }

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

저는 정확히 같은 오류 로그와 같은 문제에 직면하고 있었습니다. 경우에는 경에는우내는▁in.onProgress()는 "AsyncTask"를 사용하여 합니다.mAdapter.add(newEntry) 것을 UI를 합니다.mAdapter.setNotifyOnChange(false) 와를 요.mAdapter.notifyDataSetChanged()2초에 4번.초당 한 번씩 배열이 정렬됩니다.

이것은 잘 작동하고 중독성이 있어 보이지만 불행히도 표시된 목록 항목을 충분히 자주 터치하면 충돌할 수 있습니다.

하지만 괜찮은 해결책을 찾은 것 같습니다.내 생각에 당신이 UI 스레드에서 작업하더라도 어댑터는 호출하지 않고 데이터에 대한 많은 변경 사항을 수락하지 않습니다.notifyDataSetChanged()이것 때문에 저는 언급된 300ms가 끝날 때까지 모든 새로운 항목을 저장하는 큐를 만들었습니다.이 순간에 도달하면 저장된 모든 항목을 한 번에 추가하고 호출합니다.notifyDataSetChanged()지금까지 저는 더 이상 목록을 삭제할 수 없었습니다.

이는 Android 4-4.4(KitKat)에서 알려진 버그이며 ">4.4"에서 해결되었습니다.

다음을 참조하십시오. https://code.google.com/p/android/issues/detail?id=71936

에도 수신자 해야 합니다(XMPP와 함께 됨).ArrayList을 통해 때, 를 통 수 해 추 려 하 고 가 했MessageListener(스레드 삭제), 위의 오류로 인해 응용 프로그램이 종료됩니다.는 제 저는이문해위결컨추다니해습가에 해서 했습니다.arraylist&setListviewadapater를 통하여runOnUiThread활동 클래스의 일부인 메서드입니다.이것으로 저의 문제가 해결되었습니다.

저도 비슷한 문제에 직면했습니다. 저의 경우 이렇게 해결했습니다.나는 그것이 가능합니다.task 미이입니다.RUNNING또는FINISHED태스크를 한 번만 실행할 수 있기 때문입니다.아래에는 제 솔루션의 일부 코드와 수정된 코드가 표시됩니다.

public class MyActivity... {
    private MyTask task;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
       // your code
       task = new MyTask();
       setList();
    }

    private void setList() {
    if (task != null)
        if (task.getStatus().equals(AsyncTask.Status.RUNNING)){
            task.cancel(true);
            task = new MyTask();
            task.execute();         
        } else if (task.getStatus().equals(AsyncTask.Status.FINISHED)) {
            task = new MyTask();
            task.execute();
        } else 
            task.execute();
    }

    class MyTask extends AsyncTask<Void, Item, Void>{
       List<Item> Itens;

       @Override
       protected void onPreExecute() {

        //your code

        list.setVisibility(View.GONE);
        adapterItem= new MyListAdapter(MyActivity.this, R.layout.item, new ArrayList<Item>());
        list.setAdapter(adapterItem);

        adapterItem.notifyDataSetChanged();
    }

    @Override
    protected Void doInBackground(Void... params) {

        Itens = getItens();
        for (Item item : Itens) {
            publishProgress(item );
        }

        return null;
    }

    @Override
    protected void onProgressUpdate(Item ... item ) {           
        adapterItem.add(item[0]);
    }

    @Override
    protected void onPostExecute(Void result) {
        //your code
        adapterItem.notifyDataSetChanged();     
        list.setVisibility(View.VISIBLE);
    }

}

}

저도 같은 문제가 있었고 해결했습니다.내 문제는 내가 사용하고 있었다는 것입니다.listview어레이 어댑터 및 필터를 사용합니다.performFiltering데이터가 있는 어레이를 조작하다가 UI 스레드에서 이 메서드가 실행되지 않아 문제가 발생했습니다.

의 한 은 이충한가원인은지의입니다.ArrayList개체를 완전히 변경할 수 없습니다.따라서 항목을 제거할 때 다음 작업을 수행해야 합니다.

mList.clear();
mList.addAll(newDataList);

이것으로 사고를 해결했습니다.

제 경우에는 제가 그 방법을 불렀습니다.GetFilter()에의 에서.TextWatcher() Activity, For에 했습니다.GetFilter() 책은다변로음경것하이는다니습었으프결해루를▁to▁the로 변경하는 것이었습니다.AfterTextChanged()하고 통화 합니다.GetFilter()

adapter.notifyDataSetChanged()

또한 정확히 같은 오류가 발생하여 비동기 작업을 사용하고 있었습니다.

`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. [in ListView(2131296334, class android.widget.ListView) with Adapter... etc

저는 그것을 퍼팅으로 해결했습니다.adapter.notifyDataSetChanged();UI 스레드의 맨 아래에 있는 것이 게시 시 비동기 작업입니다.메서드를 실행합니다. 다과같이음:

 protected void onPostExecute(Void aVoid) {

 all my other stuff etc...
    all my other stuff etc...

           adapter.notifyDataSetChanged();

                }

            });
        }

이제 제 앱이 작동합니다.

편집: 사실, 제 앱은 여전히 10번 중 1번꼴로 충돌했고, 같은 오류를 일으켰습니다.

결국 나는 우연히 발견했습니다.runOnUiThread도움이 될 거라 생각했던 이전 게시물에서.방식으로 넣었습니다 :DoInBackground 방식으로.

@Override
protected Void doInBackground(Void... voids) {

    runOnUiThread(new Runnable() {
                      public void run() { etc... etc...

그리고 나는 그것을 제거했습니다.adapter.notifyDataSetChanged();. 이제 제 은 절대됩니다.이제, 제 앱은 절대 충돌하지 않습니다.

다음 솔루션 중 하나를 사용해 보십시오.

  1. 스레드의 데이터 목록에 새 개체를 추가하는 경우가 있습니다.doInBackgroundmethod), 이 오류가 발생합니다.은 : 에서 이 doInBackground )의 합니다.onPostExcute)

  2. 모든 UI 업데이트가 UI 스레드에서 호출되는지 확인합니다.

방금 넣은 게으른 이미지 로더에 새 데이터를 추가할 때도 같은 문제가 발생했습니다.

         adapter.notifyDataSetChanged();

       protected void onPostExecute(Void args) {
        adapter.notifyDataSetChanged();
        // Close the progressdialog
        mProgressDialog.dismiss();
         }

도움이 되길 바랍니다.

@가 말한Mullins 말것처럼한"
나는 둘 다 항목을 추가하고 전화했습니다.notifyDataSetChanged()UI 스레드에서 이 문제를 해결했습니다.멀린스".

저 같은 경우에는.asynctask그리고 전화했습니다.notifyDataSetChanged()에 시대에doInBackground()방법과 문제는 내가 전화했을 때 해결되었습니다.onPostExecute()저는 예외를 받았습니다.

나는 관습이 있었습니다.ListAdapter그리고 전화하고 있었습니다.super.notifyDataSetChanged()

@Override
public void notifyDataSetChanged() {
    recalculate();
    super.notifyDataSetChanged();
}

저도 같은 상황이었고, 목록 보기에 있는 제 항목 안에 많은 버튼 그룹이 있었고 holder.rbVar.setOnclick과 같은 항목 안의 부울 값을 변경하고 있었습니다.

getView() 내부에서 메서드를 호출하고 공유 기본 설정 내부에서 개체를 저장하는 중에 문제가 발생했습니다. 그래서 위에서 동일한 오류가 발생했습니다.

해결 방법: DataSetInvalid()를 알리기 위해 getView() 내부의 메서드를 제거하고 문제가 사라졌습니다.

   @Override
    public void notifyDataSetChanged() {
        saveCurrentTalebeOnShare(currentTalebe);
        super.notifyDataSetChanged();
    }

저도 같은 문제가 있었습니다.마침내 나는 해결책을 얻었습니다.

목록 보기를 업데이트하기 전에 소프트 키패드가 있으면 먼저 닫으십시오. 그런 다음 데이터 소스를 설정하고 변경된 데이터 집합을 호출합니다.

키패드를 내부적으로 닫는 동안 listview는 UI를 업데이트합니다.키패드를 닫을 때까지 계속 호출됩니다.데이터 소스가 변경되면 이 예외가 발생합니다. 데이터가 ActivityResult에서 업데이트되는 경우 동일한 오류가 발생할 가능성이 있습니다.

 InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
            imm.hideSoftInputFromWindow(v.getWindowToken(), 0);

        view.postDelayed(new Runnable() {
            @Override
            public void run() {
                refreshList();
            }
        },100L);

내 솔루션:

을 생성합니다.temp ArrayList.

당신의 무거운 일을 합니다.doInBackground방법을 지정하고 임시 배열 목록에 항목을 추가합니다.

을 목록 의 배열합니다.onPostExecute방법.

note:된 일부 에서 항목과 관련된 일부 한 후 을 제거하고 sqlite의 임시 할 수 . 단지 데이터베이스에서 항목을 제거하고 관련된 파일을 제거한 후 임시 배열 목록에 추가하기를 원할 수 있습니다.background thread 다음에 그에때로UI thread목록 보기의 배열 목록에서 임시 배열 목록에 있는 항목을 삭제합니다.

이게 도움이 되길 바랍니다.

언급URL : https://stackoverflow.com/questions/3132021/android-listview-illegalstateexception-the-content-of-the-adapter-has-changed

반응형