1

エミュレーター (ADT v17.0.0) またはデバイス (元の Droid) で方向の変更を行うと、アクティビティが複数の作成と破棄のサイクルを経ることがあることに気付きました。問題について言及しているこのブログ投稿を見つけましたが、解決策はありません。

私のアプリ (API 8) は現在、onPause でユーザー データの「ラストチャンス」保存を行い、そのデータを onCreate/onStart で取得します。これは、1 回の再起動では正常に機能しますが、サイクルが戻ってくると同時実行の問題が発生します。 -戻る。具体的には、保存が完了する前にロードが開始された場合、「ラストチャンス」データが失われます。

onRetainNonConfigurationInstance/getLastNonConfigurationInstance を介してオブジェクトを転送することについて言及している Faster Screen Orientation Change Android 開発者の記事を読みました。アクティビティが「再起動中」かどうかを示すフラグのように onRetain/getLast... を使用してみましたが、これは機能しますが、既存の保存/読み込み操作がいつ完了したかがわからないという主な問題がまだあります。

同時実行とスレッド管理は私の最強のスーツではないので、メモリリークなしで、連続した再起動の回数にかかわらず、少なくとも 1 回の保存と読み込みを行うソリューションを探しています。高速な作成と破棄のサイクルは向き以外の理由で発生する可能性があるため、向きの変更だけを壊したり処理したりするだけのアイデアは、私が求めているものではありません。

これは、いくつかのサイクルを含むログ ファイルの抜粋です。横向きから縦向きに移動するときに、アクティビティが 2 回作成および破棄される場所を確認できます。これが私が今持っているものの抜粋です:

onPause() {
    file_manager.saveTemporaryPattern(); // writes to OutputStream on UI thread
}

onStart() {
    findViewById (R.id.main_screen).post (new Runnable() {
        file_manager.loadTemporaryPattern(); // reads from InputStream on UI thread
    });

    if (getLastNonConfigurationInstance() != null) {
        // DO SOMETHING HERE?
    }
}

onRetainNonConfigurationInstance() {
    return dummy_object;
}
4

1 に答える 1

1

アクティビティ コンテキストではなく、アプリケーション コンテキストにリンクされたハンドラ スレッドに Load/Save 呼び出しを送信することで、同時実行の問題を解決することができました。呼び出しで Load vs Save トークンをセットアップして、Save->Load->Save パターンをチェックし、横向きから縦向きへの変更で不完全なアクティビティ ライフサイクルが発生するという奇妙な動作を回避する必要がありました。

これは開発中およびテスト デバイスで動作し、アクティビティ コンテキストを漏らさないため、実際にどのように動作するかを見ていきます。

YourApp では、アプリケーションを拡張します。

private Handler fileAccessThread = null;

public void onCreate() {
    super.onCreate();

    if (fileAccessThread == null) {
        fileAccessThread = new Handler();
        token = 0;
    }
}

public void postCallbackFileAccess (int _token, Runnable _callback) {
    switch (_token) {
    case TOKEN_SAVE:
        // Save must follow load, not another save
        if (token == TOKEN_SAVE) { return; }
        token = _token;
        break;

    case TOKEN_LOAD:
//      Have to allow load->load, otherwise data gets lost/deleted
//      if (token == TOKEN_LOAD) { return; }
        token = _token;
        break;
    }

    fileAccessThread.post (_callback);
}

YourActivity で:

protected void onStart() {
    super.onStart();

    ((YourApp) getApplication()).postCallbackFileAccess (
        YourApp.TOKEN_LOAD, new Runnable() {
            @Override
            public void run() {
                file_manager.load();
            }
    });
}

protected void onPause() {
    super.onPause();

    ((YourApp) getApplication()).postCallbackFileAccess (
        YourApp.TOKEN_SAVE, new Runnable() {
            @Override
            public void run() {
                file_manager.save();
            }
    });
}
于 2012-05-31T13:12:52.233 に答える