2013-03-07 10 views
7

Ich habe auslagerbare ListView und seine Zeilen werden asynchron während des Scrollens geladen und manchmal stürzt die App einfach ab. Es ist nicht auf Android 2.3.3 passiert, aber passiert auf Android 4.0 und höher.Android ListView mit Paging stürzt ab

Hier ist mein Stack-Trace:

03-07 15:23:02.450: D/AndroidRuntime(1545): Shutting down VM 
03-07 15:23:02.450: W/dalvikvm(1545): threadid=1: thread exiting with uncaught exception (group=0x40ccb930) 
03-07 15:23:02.455: E/AndroidRuntime(1545): FATAL EXCEPTION: main 
03-07 15:23:02.455: E/AndroidRuntime(1545): 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(2131099953, class com.ui.PaginableListView) with Adapter(class android.widget.HeaderViewListAdapter)] 
03-07 15:23:02.455: E/AndroidRuntime(1545):   at android.widget.ListView.layoutChildren(ListView.java:1544) 
03-07 15:23:02.455: E/AndroidRuntime(1545):   at android.widget.AbsListView$FlingRunnable.run(AbsListView.java:4042) 
03-07 15:23:02.455: E/AndroidRuntime(1545):   at android.view.Choreographer$CallbackRecord.run(Choreographer.java:749) 
03-07 15:23:02.455: E/AndroidRuntime(1545):   at android.view.Choreographer.doCallbacks(Choreographer.java:562) 
03-07 15:23:02.455: E/AndroidRuntime(1545):   at android.view.Choreographer.doFrame(Choreographer.java:531) 
03-07 15:23:02.455: E/AndroidRuntime(1545):   at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:735) 
03-07 15:23:02.455: E/AndroidRuntime(1545):   at android.os.Handler.handleCallback(Handler.java:725) 
03-07 15:23:02.455: E/AndroidRuntime(1545):   at android.os.Handler.dispatchMessage(Handler.java:92) 
03-07 15:23:02.455: E/AndroidRuntime(1545):   at android.os.Looper.loop(Looper.java:137) 
03-07 15:23:02.455: E/AndroidRuntime(1545):   at android.app.ActivityThread.main(ActivityThread.java:5191) 
03-07 15:23:02.455: E/AndroidRuntime(1545):   at java.lang.reflect.Method.invokeNative(Native Method) 
03-07 15:23:02.455: E/AndroidRuntime(1545):   at java.lang.reflect.Method.invoke(Method.java:511) 
03-07 15:23:02.455: E/AndroidRuntime(1545):   at com.android.internal.os.ZygoteInit$MethodAnd 

Es ist Teil des Codes ist, wahrscheinlich nicht sehr hilfreich;/

protected DataResponse doInBackground(IRequest... reqs) { 
    IRequest req = reqs[0]; 
    CancelStateHolder cancelStateHolder = new CancelStateHolder() { 
     @Override 
     public boolean isCancelled() { 
      return DataRequestTask.this.isCancelled(); 
     } 
    }; 

    if (cacheKey != null) { 
     try { 
      CacheDogpileProtector.getInstance().acquire(cacheKey); 
     } catch (InterruptedException e) { 
      cancel(true); 
      ZLog.printStackTrace(e); 
     } 
    } 

    reqExec.setParentTask(this); 
    DataResponse resp = reqExec.execute(req, cancelStateHolder, 
    cacheContext, cacheKey); 
    if (resp == null) { 
     Log.d(LOG, "resp == null"); 
    } 
    return resp; 
} 

@Override 
protected void onPostExecute(DataResponse result) { 
    super.onPostExecute(result); 
    ZLog.d(LOG, "override onPostExecute"); 
    try { 
     if (result.getJsonResponse() == null) { 
      ZLog.i(LOG, "json is NULL (probably connection problem) response text: " + result.getResponseText()); 
      throw new NASAException(R.string.exception_io); 
     } 
     ConsumptionStatus consumption = ConsumptionStatus.REQUEST_NOT_CONSUMED; 
     if (onZadaneRequestCompletedListener != null) { 
      consumption = onZadaneRequestCompletedListener.onZadaneRequestCompleted(PaginableListView.this, request, result); 
     } 

     switch (consumption) { 
      case REQUEST_CONSUMED: 
       break; 
      case REQUEST_UPDATE_METADATA: 
       wrapAndUpdate(result.getJsonResponse(), true); 
       break; 
      case REQUEST_NOT_CONSUMED: 
       wrapAndUpdate(result.getJsonResponse(), false); 
       break; 
     } 
     if (onZadaneRequestCompletedListener != null) { 
      onZadaneRequestCompletedListener.onZadaneRequestCompletedAfterWrap(PaginableListView.this, request, result, lastFetchedPage); 
     } 
     setOnRefreshListener(properOnRefreshListener); 
    } catch (NASAException e) { 
     DialogHandler.handleError(mContext, e.getMessage(mContext)); 
    } finally { 
     removeFooterView(footerView); 
     actualTask = null; 
    } 
} 

}; 
actualTask.executeCached(activity, cacheContext, request); 
+0

laden Verwenden Sie eine 'AsyncTask' oder einen' Thread'? – MCeley

+0

Welcher Teil von * "Stellen Sie sicher, dass der Inhalt Ihres Adapters nicht von einem Hintergrundthread geändert wird, sondern nur vom UInthread." * Haben Sie nicht verstanden? Ich will nicht unhöflich sein, es ist eine echte Frage :) – m0skit0

+0

Ich benutze eine AsyncTask. –

Antwort

4

Sie können versuchen, etwas zu Ihrem Listview hinzufügen:

@Override 
protected void layoutChildren() { 
    try { 
     super.layoutChildren(); 
    } catch (IllegalStateException e) { 
     ZLog.e(LOG, "This is not realy dangerous problem"); 
    } 
} 

Wenn Sie eine headerview oder eine footerview Listview hinzufügen und wenn Sie notifyDataSetChanged(), wird es die mItemCount auf das Element ändern zählen realer Adapter, aber die rechte Seite wird die gefälschte itemcount zurück, die die headercount und footercount hinzugefügt:

Ihre resu Sie

http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.1.1_r1/android/widget/ListView.java?av=f#1538

+3

wow, das hat mein Problem gelöst, vielen Dank –

0

Als Ihr Stack-Trace sagt, Sie nicht den Inhalt eines Adapters aktualisieren einen Hintergrund-Thread verwenden. Da Sie eine AsyncTask verwenden, ist die Reparatur ziemlich einfach. Aktualisieren Sie den Adapter nicht in doInBackground, sondern in onPostExecute.

Hier ist ein Beispiel dafür, wie das aussehen könnte.

@Override 
protected Object doInBackground(Object... params) { 
    Object results = getResults(); /* Replace with your own result fetching code */ 
    return results; 
} 

@Override 
protected void onPostExecute(Object result) { 
    super.onPostExecute(result); 
    /* Update your adapter here using the returned results. */ 
    myAdapter.addNewData(result); 
    myAdapter.notifyDataSetChanged(); 
} 
+0

Ich mache das schon :(Das behebt das Problem nicht –