2

すべてのアクティビティで使用するオブジェクトがあり、その中に多くの複雑なデータが含まれています。オブジェクトの状態を保存してアクティビティからアクティビティに渡す Android フレームワークを使用するのは非常に面倒なので、そうなると思いました。このオブジェクトを管理し、アプリケーションが存続する限り存続させるシングルトンを作成できます。

通常のクラスと通常の静的インスタンスを使用して、通常の Java Singleton スキームを使用しようとしましたが、しばらくするとインスタンスが null になります (これは非常に紛らわしいです。まだ参照されているオブジェクトが null になり、ガベージ コレクションが行われるのはなぜでしょうか?)。だから私はAndroidデザイナーと一緒に流れ、このオブジェクトを管理するサービスを作成することにしました。サービスは次のようになります:

public class DataService extends Service {
    private Data data;
    private static DataService instance;
    @Override
    public void onCreate() {
        instance = this;
        data= new Data(...);
        instance.data.addProgressListener(listener);
        (new Thread() {
            @Override
            public void run() {
                data.doInitProgress();
                listener = null;
            };
        }).start();

    }


    public static void listenToInitDataProcess(final ProgressBar progressBar,final Runnable onDone) {

        listener = new ProgressListener() {
            private int progress;
            private int max;
            @Override
            public void onUpdateProgress(final long i) {
                progressBar.setProgress(progress+=i);
            }

            @Override
            public void onProgressEndComputed(final long n) {
                progressBar.setMax(max=(int) n);
            }

            @Override
            public void onDone() {
                progressBar.setProgress(max);
                onDone.run();
            }
        };
            if (instance!=null) instance.data.addProgressListener(listener);
    }

    public static Data getData() {
        return instance.data;
    }
    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }
}

今の問題は、アプリがオンになってしばらくすると、インスタンスがnullによって引き起こされたNPEを取得することです...データオブジェクトの作成をリッスンしていて、一度開始された後にのみ取得しようとしていたことに注意してください。したがって、そのインスタンスがnullであると想定されることはありません...

これを正しく行う方法は?

4

2 に答える 2

-1

しかし、インスタンスはしばらくすると null になります

まず、Effective Javaのシングルトンの推奨事項と、何かが null にならない方法を理解します。

// Singleton with public final field
public class Elvis {
    public static final Elvis INSTANCE = new Elvis();
    private Elvis() { ... }

    public void leaveTheBuilding() { ... }
}

ただし、パブリック コンストラクターがないため、 Service は異なります。したがって、最初にサービスが実行されているかどうかを確認します (この投稿で参照されているように:サービスがブロードキャスト レシーバーから実行されているかどうかを確認します)。

private boolean isMyServiceRunning(Context context) {
    ActivityManager manager = (ActivityManager)      context.getSystemService(Context.ACTIVITY_SERVICE);
    for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
        if (DataService.class.getName().equals(service.service.getClassName())) {
            return true;
        }
    }

    return false;
}

次に、サービスでいくつかのメソッドを定義して、必要な状態変数を返します。

于 2015-03-03T16:31:45.683 に答える