6

シングルトンとして動作するServiceを作成することは悪い習慣ですか?Androidでシングルトンとしてサービスを使用する

public class CustomService extends Service { 
    private List<Profile> mProfiles; 
    private static CustomService instance; 

    public static CustomService getInstance() { 
     if(instance == null) { 
      instance = new CustomService(); 
     } 
     return instance; 
    } 

    public List<Profile> getProfiles() { 
      return mProfiles; 
    } 

    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) { 
     ... 
    } 
    ... 
} 

Serviceを行うだけではなくシングルトンの理由がある:私はServiceのようなものを持っていることができるように、停止しないと、それはいくつかの他のエンジンとActivitiesが使用することを、いくつかのプライベートなデータが含まれているんServiceを意味しますアプリケーションとは独立して動作しなければならないということです。開始時には決して閉じてはならず、アプリケーションに依存しないwebsocketを接続します。あなたは私に何を勧めていますか? Serviceを再利用して、他のエンジンから利用可能なデータ(mProfilesアレイなど)とActivitiesを入手する方が良いでしょうか?

私はServiceがシングルトンとして動作するところを読んだことがありますが、アプリケーションの他のポイントからプライベート変数にアクセスする方法はわかりません。

ありがとうございます。

+0

あなたが知っている限り、あなたはサービスインスタンスを自分で作成すべきではありませんが、コンテキストを使って 'startService()'を使うべきです。私は結果が 'new CustomService();を使用しているかどうか分かりません。 –

+0

こんにちは、あなたの答えに感謝します。しかし、startServiceはサービスを開始してonStartCommandを呼び出しますが、これは私が望むものではありません。アプリケーションのonCreateメソッドで一度サービスを開始し、アプリケーションの他のポイントからサービスのプライベート変数を取得したい – FVod

答えて

7

シングルトンとして機能するサービスを作成することは悪い習慣ですか?

それはあなたが示唆するように、冗長であり、

は、

  • Applicationライフサイクルに関連して、その機能を実行することで、アプリケーションコンポーネントとしてAndroidServiceの観点から仕事に行くのではないこと、順番に、
  • システムイベントの影響を受けます。

アプリケーションコンポーネントの意図は、それをトリガー(開始/結合/登録)

  • AndroidManifest.xmlで宣言、
  • が到達すると
  • は(システムによって)作成そのようなコンポーネントのインスタンスがApplicationにあり、それをApplicationThread/ActivityThreadに「添付」します。言っ

、アプリケーションコンポーネントは、独立して実行することはできませんOSのプロセスとが主催Applicationインスタンスに結びついているという事実にもたらします。


あなたのアプローチについては、2つのシナリオがあります

1.CustomServiceのデフォルトコンストラクタは、パターンごととしてプライベートです。

getInstance()を呼び出すと、CustomServiceという1つのインスタンスが作成されます。インスタンスは、AndroidServiceアプリケーションコンポーネントとは何も共通していないJavaオブジェクト(シングルトン)です。 onStart(),onStartCommand()などのメソッドは、システムから決して呼び出されません。

startService(Intent)で "サービス"(マニフェストで宣言されている)を開始しようとすると、IllegalAccessException: access to constructor not allowedで失敗します。

2.CustomServiceのデフォルトコンストラクタは、(掲示コードごとに)公開されています。

サービスがAndroidManifestで宣言され、デフォルトコンストラクタが空の場合、startService()しかしgetInstance()AndroidServiceアプリケーションコンポーネントとして扱われることはありませんCustomServiceの別のインスタンスを作成しますが、失敗することはありません。

これはシングルトンではありません。


あなたは私が何をすることをお勧め?他のエンジンやアクティビティからいくつかのデータ(たとえばmProfiles配列)を利用できるようにするために、サービスを再利用する方が良いでしょうか?

the documentationあたりとして

使用Serviceと通信の種類を選ぶ次のものが必要です。

  • 一方向通信(Activity-->Service) - started Serviceを使用し、取り扱う各Intent(あなたのデータは、それに接続して例えばProfileクラスがParcelableを実装する場合はmProfilesのようにonStartCommand()にあります。
  • 双方向通信(Activity<->Service) - bound Serviceを使用し、IBinderで通信します。

最後に、ServiceAndroidはシングルトンです。システムには各サービスのインスタンスが1つしかありません。オンデマンドで開始し、保留中のすべてのクライアント(Intent)を処理します。それが完了するか、明示的に停止すると、破壊されます。

+0

ありがとうございます。しかし、その後、エンジンのサービスのプライベート変数を取得する方法はありますか?私はアクティビティやサービスだけがサービスにバインドできることを読んだので、ブロードキャストレシーバや別のシングルトンやエンジンからどのようにmProfiles配列を取得できますか?どうもありがとうございます。 – FVod

+0

「エンジン」の意味はわかりませんが、[Context](http://developer.android.com/reference/android/content/Context.html)を自由に使い分けることができますサービスへの開始/バインド。バインドされると、IPCを含む[IBinder](http://developer.android.com/reference/android/os/IBinder.html)を介してParcelableを実装するすべてのデータを送信できます。あなたがコンテクストを持っていないなら、できることはあまりありません(私はあなたのユースケースを知らない)...私の最善のアドバイスは、公式のドキュメント(それはAndroid用に書かれている)特に、Activity-Service通信の例を見つけることができます。 – Onik

0

サービスをシングルトンとして作成するのは悪い習慣です。サービスをスティッキーにすることができます。名前でサービスを取得して、アクティビティ内から次のコードでサービスが動作しているかどうかを確認できます。

private boolean isMyServiceRunning(Class<?> serviceClass) { 
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); 
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) { 
    if (serviceClass.getName().equals(service.service.getClassName())) { 
     return true; 
    } 
} 
return false; 

}

0

サービスは、Androidのフレームワークで一度だけインスタンス化された(と私はこれをサポートしていますが、それはケースだと仮定する文書を発見していない)場合は、Service.onCreateinstanceを初期化することができます。唯一の欠点は、これが呼び出されるときに保証がないことです。つまり、Application.onCreateの中でstartServiceを呼び出すと、サービスが実際にインスタンス化されるまで少し待たなければならない可能性が非常に高いでしょう。

関連する問題