崩溃:android.widget.ListView.layoutChildren中的java.lang.IllegalStateException

时间:2017-10-08 08:18:54

标签: android listview crash

我在prod中崩溃,我无法重现。跟踪没有说明它崩溃的地方。进行一些搜索后,它看起来可能与notifyDataSetChanged()有关。 它发生在Android 6和7上。

我有两个包使用listview:

用于检查wifi AP列表的BroadcastReceiver:在这种情况下,代码收集所有AP,将它们添加到List中并调用notifyDataSetChanged:

 @Override
    public void onReceive(Context context, Intent intent) {
        if (wifiManager != null) {
            if (wifiManager.isWifiEnabled()) {
                List<ScanResult> listeScan = wifiManager.getScanResults();
                listeWifiItem.clear();
                for (ScanResult scanResult : listeScan) {
                    WifiItem item = new WifiItem();

                    item.setAdresseMac(scanResult.BSSID);
                    item.setAPName(scanResult.SSID);
                    item.setForceSignal(scanResult.level);

                    listeWifiItem.add(item);
                }

                wifiAdapter.notifyDataSetChanged();
            } else {
                Toast.makeText(context, "You must activate the WiFi", Toast.LENGTH_SHORT);
            }
        }
    }

我在onPostExecute方法中调用notifyDataSetChanged的异步任务:

@Override
protected void onPostExecute(Void result) {
    iPadaptater.notifyDataSetChanged();
    super.onPostExecute(result);
}

我使用notifyDataSetChanged的方式有问题吗?在异步任务中,如果用户移动到另一个功能,我认为这样做更安全

你认为崩溃与notifyDataSetChanged有关吗?

您是否从痕迹中看到了另一个重要信息?

以下是两种类型的跟踪:

-type 1:

  java.lang.IllegalStateException: 
      at android.widget.ListView.layoutChildren (ListView.java:1747)
      at android.widget.AbsListView$CheckForTap.run (AbsListView.java:4728)
      at android.os.Handler.handleCallback (Handler.java:751)
      at android.os.Handler.dispatchMessage (Handler.java:95)
      at android.os.Looper.loop (Looper.java:154)
      at android.app.ActivityThread.main (ActivityThread.java:6776)
      at java.lang.reflect.Method.invoke (Native Method)
      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:1520)
      at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1410)

-type 2:

java.lang.IllegalStateException: 
  at android.widget.ListView.layoutChildren (ListView.java:1623)
  at android.widget.AbsListView.onTouchUp (AbsListView.java:4210)
  at android.widget.AbsListView.onTouchEvent (AbsListView.java:3969)
  at android.view.View.dispatchTouchEvent (View.java:9957)
  at android.view.ViewGroup.dispatchTransformedTouchEvent (ViewGroup.java:2705)
  at android.view.ViewGroup.dispatchTouchEvent (ViewGroup.java:2386)
  at android.view.ViewGroup.dispatchTransformedTouchEvent (ViewGroup.java:2711)
  at android.view.ViewGroup.dispatchTouchEvent (ViewGroup.java:2400)
  at android.view.ViewGroup.dispatchTransformedTouchEvent (ViewGroup.java:2711)
  at android.view.ViewGroup.dispatchTouchEvent (ViewGroup.java:2400)
  at android.view.ViewGroup.dispatchTransformedTouchEvent (ViewGroup.java:2711)
  at android.view.ViewGroup.dispatchTouchEvent (ViewGroup.java:2400)
  at android.view.ViewGroup.dispatchTransformedTouchEvent (ViewGroup.java:2711)
  at android.view.ViewGroup.dispatchTouchEvent (ViewGroup.java:2400)
  at android.view.ViewGroup.dispatchTransformedTouchEvent (ViewGroup.java:2711)
  at android.view.ViewGroup.dispatchTouchEvent (ViewGroup.java:2400)
  at android.view.ViewGroup.dispatchTransformedTouchEvent (ViewGroup.java:2711)
  at android.view.ViewGroup.dispatchTouchEvent (ViewGroup.java:2400)
  at android.view.ViewGroup.dispatchTransformedTouchEvent (ViewGroup.java:2711)
  at android.view.ViewGroup.dispatchTouchEvent (ViewGroup.java:2400)
  at android.view.ViewGroup.dispatchTransformedTouchEvent (ViewGroup.java:2711)
  at android.view.ViewGroup.dispatchTouchEvent (ViewGroup.java:2400)
  at android.view.ViewGroup.dispatchTransformedTouchEvent (ViewGroup.java:2711)
  at android.view.ViewGroup.dispatchTouchEvent (ViewGroup.java:2400)
  at com.android.internal.policy.DecorView.superDispatchTouchEvent (DecorView.java:416)
  at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent (PhoneWindow.java:1837)
  at android.app.Activity.dispatchTouchEvent (Activity.java:3154)
  at android.support.v7.view.WindowCallbackWrapper.dispatchTouchEvent (WindowCallbackWrapper.java:63)
  at com.android.internal.policy.DecorView.dispatchTouchEvent (DecorView.java:378)
  at android.view.View.dispatchPointerEvent (View.java:10177)
  at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent (ViewRootImpl.java:4634)
  at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess (ViewRootImpl.java:4502)
  at android.view.ViewRootImpl$InputStage.deliver (ViewRootImpl.java:3953)
  at android.view.ViewRootImpl$InputStage.onDeliverToNext (ViewRootImpl.java:4006)
  at android.view.ViewRootImpl$InputStage.forward (ViewRootImpl.java:3972)
  at android.view.ViewRootImpl$InputStage.apply (ViewRootImpl.java:3980)
  at android.view.ViewRootImpl$InputStage.deliver (ViewRootImpl.java:3953)
  at android.view.ViewRootImpl$InputStage.onDeliverToNext (ViewRootImpl.java:4006)
  at android.view.ViewRootImpl$InputStage.forward (ViewRootImpl.java:3972)
  at android.view.ViewRootImpl$AsyncInputStage.forward (ViewRootImpl.java:4101)
  at android.view.ViewRootImpl$InputStage.apply (ViewRootImpl.java:3980)
  at android.view.ViewRootImpl$AsyncInputStage.apply (ViewRootImpl.java:4158)
  at android.view.ViewRootImpl$InputStage.deliver (ViewRootImpl.java:3953)
  at android.view.ViewRootImpl$InputStage.onDeliverToNext (ViewRootImpl.java:4006)
  at android.view.ViewRootImpl$InputStage.forward (ViewRootImpl.java:3972)
  at android.view.ViewRootImpl$InputStage.apply (ViewRootImpl.java:3980)
  at android.view.ViewRootImpl$InputStage.deliver (ViewRootImpl.java:3953)
  at android.view.ViewRootImpl.deliverInputEvent (ViewRootImpl.java:6443)
  at android.view.ViewRootImpl.doProcessInputEvents (ViewRootImpl.java:6417)
  at android.view.ViewRootImpl.enqueueInputEvent (ViewRootImpl.java:6378)
  at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent (ViewRootImpl.java:6577)
  at android.view.InputEventReceiver.dispatchInputEvent (InputEventReceiver.java:185)
  at android.os.MessageQueue.nativePollOnce (Native Method)
  at android.os.MessageQueue.next (MessageQueue.java:323)
  at android.os.Looper.loop (Looper.java:136)
  at android.app.ActivityThread.main (ActivityThread.java:6311)
  at java.lang.reflect.Method.invoke (Native Method)
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:872)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:762)

2 个答案:

答案 0 :(得分:3)

查看API 25的源代码,抛出非法状态异常的唯一地方是LayoutChildren() ListView。代码中的异常状态:

摘自ListView$LayoutChildren

// Handle the empty set by removing all views that are visible
// and calling it a day
if (mItemCount == 0) {
    resetList();
    invokeOnItemScrollListener();
    return;
} 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 "
            + "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(" + getId() + ", " + getClass()
            + ") with Adapter(" + mAdapter.getClass() + ")]");
}

这表示由ListView维护的内部项目计数与适配器维护的项目计数之间不匹配。看起来LayoutChildren可能是从CheckforTap的{​​{1}}内部类调用的:

摘自AbsListView

AbsListView$CheckforTap

这可能是其他人在询问您是否正在从非UI线程更改数据集的原因。它似乎也指出了如何调用if (!mDataChanged) { final float[] point = mTmpPoint; point[0] = x; point[1] = y; transformPointToViewLocal(point, child); child.drawableHotspotChanged(point[0], point[1]); child.setPressed(true); setPressed(true); layoutChildren(); // ... and it continues... 的潜在问题。

假设您正在使用UI线程进行更改,并且不了解有关应用内部工作的更多信息,我建议您不要将对notifyDataSetChanged()的调用与您所做的更改分开。您似乎是从回复中这样做的。

答案 1 :(得分:0)

您需要在UI线程中向listeWifiItem添加项目并调用notifyDataSetChanged()

@Override 
protected void onPostExecute (Void result){
            super.onPostExecute(result);

            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    listeWifiItem.clear();
                    for (ScanResult scanResult : listeScan) {
                        WifiItem item = new WifiItem();

                        item.setAdresseMac(scanResult.BSSID);
                        item.setAPName(scanResult.SSID);
                        item.setForceSignal(scanResult.level);

                        listeWifiItem.add(item);
                    }
                    wifiAdapter.notifyDataSetChanged();
                }
            });
        }