3

私は単純なファイル マネージャー アプリケーションに取り組んできました。テストに使用したデバイスは、LG Nexus 4 (v4.3) と Xperia x10i (v2.3.7) です。x10i でのパフォーマンスは、少し遅いものの、問題はありませんでした。

回転時:

PopupWindows私が追跡しているいくつかがあります。フラグを使用して、現在画面に表示されているものを判断PopupWindowします (現在、画面に表示される PopupWindow は常に 1 つだけです)。では、.onSaveInstanceState(Bundle),を使用してこれらのフラグを保存しBundleます。ではonCreate(Bundle)、これらのフラグを取得して、 で使用しonPostExecute()ますAsyncTask(called in onResume() and used for populating the ListView with data)

問題:

PopupWindowデバイスを回転させたときに が表示されている場合、アクティビティは破棄されて再作成され、が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 でのテスト中に例外はスローされません。また、メッセージ キューに投稿しようとしましたRunnablemContentView's (the activity's main view)問題は解決しません。

画面回転の扱い方に問題があると思います。私が使用したアプリでは、画面の回転とレイアウトの変更がスムーズに行われます。私のアプリの場合、文字通り、PopupWindowが破棄されて再作成されていることがわかります。ほとんどのアプリは を使用して画面の回転を処理しますandroid:configChanges="keyboardHidden|orientation|screenSize"か? このアプローチは正しくないことを読みました。

4

2 に答える 2

2

最も可能性が高いのは、x10i が 2 つのActivityインスタンス化を行っていることです。これにより、2 つAsyncTasksが実行されます。Activity最初のものは、フレームワークとウィンドウ マネージャーから見てもはや存在しない (または存在するはずの)のインスタンスへの参照を持つことになり、null トークンとその結果の例外が発生します。

Activity#onStopおそらく、キャンセルされたかどうかを設定しAsyncTask#cancelAsyncTask#onPostExecute確認する必要があります。キャンセルされた場合は、ポップアップウィンドウを作成しないでください。


実際の解決策:

Activityで false に設定されている でフラグを作成しますonCreate()onStop()true に設定してから、設定されているかどうかを確認onPostExecuteし、設定されている場合はポップアップ ウィンドウを表示しません。

于 2013-08-08T06:42:45.497 に答える
0

PopupWindow を次のように表示

final View parent = findViewById(R.id.{parentId});
parent.post(new Runnable() {
    @Override
    public void run() {
        mPopup.showAtLocation(parent, ...);
    }
});

問題を解決しました。

于 2014-08-23T17:02:33.207 に答える