gpt4 book ai didi

android - PopupWindow.showAtLocation() 在使用 onSaveInstanceState() 处理设备旋转时导致 WindowManager$BadTokenException

转载 作者:太空狗 更新时间:2023-10-29 13:29:02 25 4
gpt4 key购买 nike

我一直在开发一个简单明了的文件管理器应用程序。我用于测试的设备是 LG Nexus 4 (v4.3) 和 Xperia x10i (v2.3.7)。 x10i 的性能虽然有点低迷,但没有问题。

轮换:

我跟踪了几个 PopupWindows。我使用标志来确定哪个 PopupWindow 当前在屏幕上(目前,在任何给定时间屏幕上最多有一个 PopupWindow)。在 onSaveInstanceState(Bundle), 中,我使用 Bundle 保存这些标志。在 onCreate(Bundle) 中,我检索这些标志并在 AsyncTask 的 onPostExecute() 中使用它们(在 onResume() 中调用并用于填充 ListView数据)

问题:

如果旋转设备时显示 PopupWindow,则销毁、重新创建 Activity,然后再次显示 PopupWindow。这在两种设备上都适用。但是,今天,当搜索弹出窗口显示时,我将 x10i90 度旋转到 270 度。应用程序因以下异常而崩溃:

08-08 01:55:51.961: E/AndroidRuntime(32373): FATAL EXCEPTION: main
08-08 01:55:51.961: E/AndroidRuntime(32373): android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?
08-08 01:55:51.961: E/AndroidRuntime(32373): at android.view.ViewRoot.setView(ViewRoot.java:544)
08-08 01:55:51.961: E/AndroidRuntime(32373): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:177)
08-08 01:55:51.961: E/AndroidRuntime(32373): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
08-08 01:55:51.961: E/AndroidRuntime(32373): at android.view.Window$LocalWindowManager.addView(Window.java:424)
08-08 01:55:51.961: E/AndroidRuntime(32373): at android.widget.PopupWindow.invokePopup(PopupWindow.java:907)
08-08 01:55:51.961: E/AndroidRuntime(32373): at android.widget.PopupWindow.showAtLocation(PopupWindow.java:767)
08-08 01:55:51.961: E/AndroidRuntime(32373): at com.apprehension.phylerfilemanager.Phyler.showPopupSearch(Phyler.java:2852)
08-08 01:55:51.961: E/AndroidRuntime(32373): at com.apprehension.phylerfilemanager.Phyler$DisplayFilesTask.onPostExecute(Phyler.java:3453)
08-08 01:55:51.961: E/AndroidRuntime(32373): at com.apprehension.phylerfilemanager.Phyler$DisplayFilesTask.onPostExecute(Phyler.java:1)
08-08 01:55:51.961: E/AndroidRuntime(32373): at android.os.AsyncTask.finish(AsyncTask.java:417)
08-08 01:55:51.961: E/AndroidRuntime(32373): at android.os.AsyncTask.access$300(AsyncTask.java:127)
08-08 01:55:51.961: E/AndroidRuntime(32373): at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:429)
08-08 01:55:51.961: E/AndroidRuntime(32373): at android.os.Handler.dispatchMessage(Handler.java:99)
08-08 01:55:51.961: E/AndroidRuntime(32373): at android.os.Looper.loop(Looper.java:123)
08-08 01:55:51.961: E/AndroidRuntime(32373): at android.app.ActivityThread.main(ActivityThread.java:3701)
08-08 01:55:51.961: E/AndroidRuntime(32373): at java.lang.reflect.Method.invokeNative(Native Method)
08-08 01:55:51.961: E/AndroidRuntime(32373): at java.lang.reflect.Method.invoke(Method.java:507)
08-08 01:55:51.961: E/AndroidRuntime(32373): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:862)
08-08 01:55:51.961: E/AndroidRuntime(32373): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620)
08-08 01:55:51.961: E/AndroidRuntime(32373): at dalvik.system.NativeStart.main(Native Method)

第 2852 行:

popupWindowSearch.showAtLocation(popupViewSearch, Gravity.CENTER, 0, 0);    

如果我每旋转 90 度并暂停一次,问题就不存在了。当设备不停地旋转 180 度时发生崩溃。

保存标志:

@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);

if (searchPopup) {
outState.putBoolean("searchPopup", searchPopup);
outState.putString("searchKeyword", searchKeyword);
outState.putInt("searchType", searchType);
}

if (....) {
........
........
}
}

onCreate(Bundle) 中检索标志:

if (savedInstanceState != null) {

rotated = true;

if (savedInstanceState.containsKey("searchPopup")) {
searchPopup = true;
searchKeyword = savedInstanceState.getString("searchKeyword");
searchType = savedInstanceState.getInt("searchType");
}

....
....
}

AsyncTaskonResume() 开始执行。在此 AsyncTaskonPostExecute() 中:

if (rotated) {
rotated = false;
if (searchPopup) {
showPopupSearch(searchType, searchKeyword); // Line 3453
}
....
....
} else {
searchPopup = false;
....
....
}

在 Nexus 4 上测试时未抛出异常。我还尝试将 Runnable 发布到 mContentView( Activity 的主视图) 消息队列。问题仍然存在。

我认为我处理屏幕旋转的方式存在问题。在我使用过的应用程序中,屏幕旋转和布局变化很顺利。在我的应用程序中,您可以从字面上看出 PopupWindow 正在被关闭并重新创建。大多数应用程序是否使用 android:configChanges="keyboardHidden|orientation|screenSize" 处理屏幕旋转?我了解到这种方法不正确。

最佳答案

最有可能发生的情况是 x10i 正在执行两个 Activity 实例化。这导致两个 AsyncTasks 运行。第一个最终将引用 Activity 的实例,在框架和窗口管理器看来,该实例不再存在(或应该存在),导致空标记和结果异常。

在您的 Activity#onStop 中,您可能应该设置 AsyncTask#cancel 并在 AsyncTask#onPostExecute 中检查它是否已取消,如果已取消,则不要t 创建弹出窗口。


实际解决方案:

Activity 中创建一个标志,该标志在 onCreate() 中设置为 false。在 onStop() 中将其设置为 true,然后在 onPostExecute 中检查它是否已设置,如果已设置则不显示弹出窗口。

关于android - PopupWindow.showAtLocation() 在使用 onSaveInstanceState() 处理设备旋转时导致 WindowManager$BadTokenException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18119256/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com