4

アプリケーションの状態/シングルトンを保存するのに問題があります。

アプリケーションがロード画面(アクティビティ)を開始すると、シングルトンがWebサービス呼び出しからの値で初期化されます(ネットワークアクセスはメインスレッドで実行できないことに注意してください)。

シングルトンが作成されたら、メインアクティビティを開きます。レイアウトを作成するには、シングルトンの値が必要であることに注意してください。

ここで、アプリがバックグラウンドで実行され、そこで強制終了されたと仮定します(たとえば、メモリが不足しているため)。アプリが強制終了されると、シングルトンインスタンスが削除されます。アプリに戻ると、メインのアクティビティを再現しようとします。前述したように、レイアウトを構築するにはシングルトンの値が必要であるため、NullPointerExceptionが発生します(シングルトンのメンバーにアクセスしようとすると、もう存在しないため)。

アプリが強制終了された後、最初の読み込みアクティビティを開始するようにAndroidに指示することはできますか?レイアウトを再作成する前にシングルトンを更新できれば素晴らしいのですが、ネットワーク呼び出しをメインスレッドで実行できないため、更新が完了するまでブロックされないため、これは問題のようです。すべてのアクティビティonStopでシングルトンを保存し、onCreateメソッドで再作成できると思いますが、これは少し予測が難しいようで、一貫性のない状態になる可能性があります...

別の方法は、常にonStopでアクティビティを終了することですが、これにより、アプリが強制終了されていなくても、ユーザーが最後に使用したタブなどが失われるため、これは適切なオプションではありません。

これを解決する方法について何かアイデアはありますか?

4

3 に答える 3

4

シングルトンの代わりにSharedPreferencesを使用しないのはなぜですか?

グローバルな状態を保存したいときはいつでも、それを設定にコミットします。グローバル状態を読みたいときはいつでも、設定から読み戻してください。

そうすれば、電話の動作に関係なくデータが常に保持されるため、アプリケーションのライフサイクルについてまったく気にする必要はありません。

于 2012-10-26T21:39:09.570 に答える
0

そのようなもののために、私はApplicationクラスとして疑似singeltonオブジェクトを使用しました。このオブジェクトは最初に作成され、メモリ内にあります。ただし、他のアプリケーションでメモリが必要な場合、システムはアプリケーションを終了することに注意してください。ただし、このオブジェクトは、すべてのアクティビティが一時的に終了した場合でも永続的です。

これを使用するには、Androidマニフェストで次のように宣言する必要があります。

<application android:label="@string/app_name"
             android:icon="@drawable/icon"
             android:description="@string/desc"
             android:name=".MySingeltonClass"
             ...

コード例は次のとおりです。

public abstract class MySingeltonClass extends Application {
    // ...

    public void informClientOnline() {
        clientOnline=true;
        Log.v(LOG_TAG, "Client is online!");
    }

    public void informClientShutdown() {
        clientOnline=false;
        Log.v(LOG_TAG, "Client is going offline. Waiting for restart...");
        Timer t=new Timer("shutdowntimer", false);
        t.schedule(new TimerTask() {
            @Override
            public void run() {
                if(!clientOnline) {
                    Log.v(LOG_TAG, "Client has not restartet! Shutting down framework.");
                    shutdown();
                    System.exit(0);
                }
            }
        }, 5000);
    }
}

この2つの関数は次のように呼び出されます。

((MySingeltonClass)getApplicationContext()).informClientOnline();
于 2012-10-26T21:06:16.853 に答える
0

onSaveInstanceState()アクティビティで呼び出されたときにシングルトンを保存できます。あなたがする必要があるのはそれを実装させることですParcelable(それはAndroid独自のシリアル化の形式です)、そしてあなたはそれをあなたが好きな方でそれを海苔でまたはアクティビティで取得することを可能にするoutState Bundleに置くことができます。onSaveInstanceState()onCreate()onRestoreInstanceState()

私はあなたのために例を含めました:

public class TestActivity extends Activity {

    private MySingleton singleton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if(savedInstanceState.containsKey("singleton")) {
            singleton = savedInstanceState.getParcelable("singleton");
        } else {
            singleton = MySingleton.getInstance(5);
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putParcelable("singleton", singleton);
    }

    public static class MySingleton implements Parcelable {

        private static MySingleton instance;
        private int myData;

        private MySingleton(int data) {
            myData = data;
        }

        public static MySingleton getInstance(int initdata) {
            if(instance == null) {
                instance = new MySingleton(initdata);
            }

            return instance;
        }

        public static final Parcelable.Creator<MySingleton> CREATOR = new Creator<TestActivity.MySingleton>() {

            @Override
            public MySingleton[] newArray(int size) {
                return new MySingleton[size];
            }

            @Override
            public MySingleton createFromParcel(Parcel source) {
                return new MySingleton(source.readInt());
            }
        };

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(Parcel parcel, int flags) {
            parcel.writeInt(myData);
        }

    }

}
于 2012-10-26T21:14:23.713 に答える