我已多次修改我的代码以避免此错误,每次我触摸我的listview适配器时都是来自UI线程。我做的是我做了一个异步任务来获取listview所需的数据。 On" PostExecute"我调用静态方法来处理之后需要处理的操作。我不时地得到报告,应用程序使用ListView在片段上崩溃。它不一致所以很难再现,但我想知道如何修复?也许我可以抓住错误并要求用户再次刷新,但我认为不可能。这是我的代码触及我的适配器。
public static void refresh() {
Log.i("Handling Refresh", "Handling");
HandleRefresh handleRefresh = new HandleRefresh(Util.tabbedActivity);
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.HONEYCOMB)
handleRefresh.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
else
handleRefresh.execute();
}
处理刷新
public class HandleRefresh extends AsyncTask<String, String, String> {
Context context;
String response;
public HandleRefresh(Context context)
{
this.context = context;
}
@Override
protected String doInBackground(String... params) {
final LoadEvents loadEvents = new LoadEvents(Util.tabbedActivity.getApplicationContext(), 1);
try{
response = loadEvents.execute().get();
Log.i("Response ", response);
if(response.equals("A"))
{
Log.d("Loading Events: ", "1 Events Loaded" + " " + AdapterUtilities.posts.size());
AdapterUtilities.sortPosts();
Log.i("Loading Events:", " " + AdapterUtilities.posts.size());
AdapterUtilities.ORIGINALPOSTSLISTS.addAll(AdapterUtilities.POSTSLISTS);
AdapterUtilities.Originalposts.addAll(AdapterUtilities.posts);
AdapterUtilities.OriginalTIMELIST.addAll(AdapterUtilities.TIMELIST);
Calendar cal = Calendar.getInstance();
Long realTime = cal.getTimeInMillis();
AdapterUtilities.REALTIME = realTime;
for (int i = 0; i < AdapterUtilities.POSTSLISTS.size(); i++) {
Log.d("Loading Events: ", "PRE LOAD : " + AdapterUtilities.POSTSLISTS.get(i).get(AdapterUtilities.EVENTID));
}
Log.d("Loading Events: ", "2 Events Loaded" + " " + AdapterUtilities.posts.size());
Util.saveToSharedPrefsInteger(Util.tabbedActivity.getApplicationContext(), "LN", 1);
try {
} catch (IllegalStateException ise) {
ise.printStackTrace();
}
}
else if (response.equals("D"))
{
return "D";
}
else
{
return "C";
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
return "C";
}
@Override
protected void onPostExecute(String o)
{
MainFeed.setMainFeed(response);
}
}
这是setMainFeed,触及listview和适配器的方法。我等待后台线程的回复然后我做我的行动。
public static void setMainFeed(String response)
{
Log.i("Handle refresh response", response);
if(response.equals("A"))
{
lv.setAdapter(adapter);
new Thread(new Runnable() {
@Override
public void run() {
try {
final EventUtils EventUtils = new EventUtils(Util.tabbedActivity);
EventUtils.runRefresh(EventUtils.REDO_LISTS);
Util.tabbedActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
Log.i("EVENTS TO RATE ", "EVENTS TO RATE = " + RateEventNode.EVENTS_TO_RATE);
if (RateEventNode.EVENTS_TO_RATE != 0) {
MainFeed.showRateDialog(EventUtils.EVENTSTORATELIST.get(RateEventNode.EVENTS_TO_RATE - 1));
}
}
});
} catch (ExecutionException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
if(mainFeedLayoutsVF.getDisplayedChild() == 1) {
mainFeedLayoutsVF.setDisplayedChild(0);
}
final ImageView failedRefreshButton = (ImageView) view.findViewById(R.id.failedRefreshButtonWhite);
failedRefreshButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
actionRefresh.setActionView(abprogress);
failedRefreshButton.setVisibility(View.INVISIBLE);
refresh();
}
});
swipeLayout.setRefreshing(false);
EventUtils.enableServicesAndReceivers(Util.tabbedActivity);
Log.i("LV ", "LV " + lv.getAdapter().toString());
if(actionRefresh != null) {
actionRefresh.setActionView(null);
}
}
else if(response.equals("D"))
{
if(mainFeedLayoutsVF.getDisplayedChild() == 0) {
mainFeedLayoutsVF.setDisplayedChild(1);
}
if(actionRefresh != null) {
actionRefresh.setActionView(null);
}
final ImageView failedRefreshButton = (ImageView) view.findViewById(R.id.failedRefreshButtonWhite);
failedRefreshButton.setVisibility(View.INVISIBLE);
failedRefreshTV.setText("Whoops! Looks like you aren't following anyone. Go to the DISCOVER tab to get connected.");
failedRefreshButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
actionRefresh.setActionView(abprogress);
failedRefreshButton.setVisibility(View.INVISIBLE);
refresh();
}
});
}
else
{
if(mainFeedLayoutsVF.getDisplayedChild() == 0) {
mainFeedLayoutsVF.setDisplayedChild(1);
}
if(actionRefresh != null) {
actionRefresh.setActionView(null);
}
final ImageView failedRefreshButton = (ImageView) view.findViewById(R.id.failedRefreshButtonWhite);
failedRefreshButton.setVisibility(View.VISIBLE);
failedRefreshTV.setText(Util.tabbedActivity.getString(R.string.couldNotConnect));
failedRefreshButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
actionRefresh.setActionView(abprogress);
failedRefreshButton.setVisibility(View.INVISIBLE);
refresh();
}
});
}
}
这是LogCat
01-23 09:47:56.283 18567-18567/com.android.wallfly E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.android.wallfly, PID: 18567
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. [in ListView(2131362088, class android.widget.ListView) with Adapter(class android.widget.HeaderViewListAdapter)]
at android.widget.ListView.layoutChildren(ListView.java:1566)
at android.widget.AbsListView.onLayout(AbsListView.java:2528)
at android.view.View.layout(View.java:15655)
at android.view.ViewGroup.layout(ViewGroup.java:4856)
at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1055)
at android.view.View.layout(View.java:15655)
at android.view.ViewGroup.layout(ViewGroup.java:4856)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
at android.view.View.layout(View.java:15655)
at android.view.ViewGroup.layout(ViewGroup.java:4856)
at android.support.v4.widget.SwipeRefreshLayout.onLayout(SwipeRefreshLayout.java:543)
at android.view.View.layout(View.java:15655)
at android.view.ViewGroup.layout(ViewGroup.java:4856)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
at android.view.View.layout(View.java:15655)
at android.view.ViewGroup.layout(ViewGroup.java:4856)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
at android.view.View.layout(View.java:15655)
at android.view.ViewGroup.layout(ViewGroup.java:4856)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1677)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1531)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1440)
at android.view.View.layout(View.java:15655)
at android.view.ViewGroup.layout(ViewGroup.java:4856)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
at android.view.View.layout(View.java:15655)
at android.view.ViewGroup.layout(ViewGroup.java:4856)
at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1055)
at android.view.View.layout(View.java:15655)
at android.view.ViewGroup.layout(ViewGroup.java:4856)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
at android.view.View.layout(View.java:15655)
at android.view.ViewGroup.layout(ViewGroup.java:4856)
at com.android.internal.widget.ActionBarOverlayLayout.onLayout(ActionBarOverlayLayout.java:438)
at android.view.View.layout(View.java:15655)
at android.view.ViewGroup.layout(ViewGroup.java:4856)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
at android.view.View.layout(View.java:15655)
at android.view.ViewGroup.layout(ViewGroup.java:4856)
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2282)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2002)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1234)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6465)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:803)
at android.view.Choreographer.doCallbacks(Choreographer.java:603)
at android.view.Choreographer.doFrame(Choreographer.java:573)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:789)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:157)
at android.app.ActivityThread.main(ActivityThread.java:5356)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.Zygot
我做错了什么?
答案 0 :(得分:1)
如果您碰巧更改了输入适配器的基础数据,我怀疑您可能正在使用
AdapterUtilities.ORIGINALPOSTSLISTS.addAll(AdapterUtilities.POSTSLISTS);
AdapterUtilities.Originalposts.addAll(AdapterUtilities.posts);
AdapterUtilities.OriginalTIMELIST.addAll(AdapterUtilities.TIMELIST);
每当您更改适配器中显示的数据时,您都必须致电notifyDatasetChanged()
,请参阅base adapter docs