我一直在开发一个简单的文件管理器应用程序。我用于测试的设备是 LG Nexus 4 (v4.3) 和 Xperia x10i (v2.3.7)。x10i 的性能虽然有点迟钝,但没有问题。
旋转时:
有几个PopupWindows
我跟踪。我使用标志来确定PopupWindow
当前在屏幕上的是哪个(目前,在任何给定时间最多有一个 PopupWindow 在屏幕上)。在onSaveInstanceState(Bundle),
我使用Bundle
. 在onCreate(Bundle)
中,我检索这些标志并onPostExecute()
在AsyncTask(called in onResume() and used for populating the ListView with data)
.
问题:
如果PopupWindow
在设备旋转时显示 a,则活动将被销毁,重新创建,然后PopupWindow
再次显示。这在两种设备上都运行良好。但是,今天,当搜索弹出窗口显示时,我x10i
从90
度数旋转到度数。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");
}
....
....
}
AnAsyncTask
从 执行onResume()
。在onPostExecute()
这个AsyncTask
:
if (rotated) {
rotated = false;
if (searchPopup) {
showPopupSearch(searchType, searchKeyword); // Line 3453
}
....
....
} else {
searchPopup = false;
....
....
}
在 Nexus 4 上进行测试时不会引发异常。我也尝试过发布Runnable
到mContentView's (the activity's main view)
消息队列。问题仍然存在。
我认为我处理屏幕旋转的方式存在问题。在我使用过的应用程序中,屏幕旋转和布局变化发生得很顺利。在我的应用程序中,您可以从字面上看出PopupWindow
正在被解雇和重新创建。大多数应用程序是否使用 处理屏幕旋转android:configChanges="keyboardHidden|orientation|screenSize"
?我读过这种方法是不正确的。