2016-08-12 13 views
3

MainActivityというActivityがあり、これはMainServiceというサービスを開始します。また、MainActivityはMainService内のメソッドとパブリック変数にアクセスできるため、サービスをバインドします。それは他の方法で行うことができますか?つまり、サービスはアクティビティのメソッドにアクセスできますか?サービスはアクティビティ内の変数にアクセスできますか?

私はMainActivityの変数がonResume()に設定されているため、最初の起動時にonResume()が実行されるまでにまだサービスが開始されていないため、その時点でサービスはまだnullです。

+0

インテントサービスでアプリケーションクラスから変数にアクセスしました。活動については不明。 –

+0

代わりに共有プロパティを使用してみませんか? –

+1

私はそれができるとは思わない。私はこの悪いデザインとも呼ぶだろう。サービスはUIのものとは独立している必要があります。サービスがUIの値を必要とする場合は、代わりにサービスの値を設定するUIを設計します。 –

答えて

1

この回答は、問題のサービスは、異なるプロセスで実行されることを前提としています

はい、それは可能です。一般的な考え方は、あなたのActivityがAIDLで定義されたインタフェースを介してリモートServiceをバインドするだけでなく、Serviceが認識している追加のAIDLインタフェースも実装し、リモートServiceのコールバックターゲットとして設定するということです。

2つのAIDLファイルが必要です.1つはServiceのインターフェイスを表し、2つ目はActivityのインターフェイスを示します。

方法はもはやvoidなりませんが、あなたが興味を持っている値を返します「コールバック」かかわらず、このようなスキームの実装は、this answerに記載の「リモートサービスコールバック」に非常によく似ている。

デザイン考慮事項:

上記のスキームでは、Activityから値を取得できますが、このパスをとる必要はありません。ユースケースの説明から、Activityが再開されたときに、Serviceに値を渡したいと考えています。とにかくServiceがバインドされているので、メソッドsetSomeValue(int value)をAIDL定義に追加し、このメソッドをonServiceConnected()コールバックから呼び出すことができます。

+1

AIDLファイルは、異なるアプリケーション間でサービスを共有する場合にのみ必要です。 – piotrpo

+0

@piotrpo、良い点!私はIPCの関与を前提としていましたが、今はサービスがどのプロセスに存在するのかという問題には言及されていません。 – Vasiliy

0

はい、可能です。 あなたはサービスがバインドされた直後に、あなたの活動をバック返すために、あなたのサービスでメソッドを用意する必要があります。

public void bindActivity(MyActivity activity){...} 

サービスがアクティビティにバインドされた後だけパラメータとしてMyActivity.thisでこのメソッドを呼び出します。

しかし...

あなたはおそらくそれを行うべきではありません。 LocalBroadcastManagerを使ってイベントやデータを渡すか、Ottoのようなより効率的なソリューションを使用して、同じことをやっていますが、別のコンポーネントのフィールドやメソッドに直接アクセスする必要はありません。

+0

'Service'が' Activity'に依存するのは良い考えではありません。このメソッドのパラメータが何らかのインタフェースであれば、より洗練されたものになり、 'MainActivity'は単にそれを実装するだけです。 – Vasiliy

+0

唯一の私の意見では、本当に "クリーン"な解決策は、メッセージベースのものです。もちろん、いくつかのインターフェイスを導入することはOODのルールに従って良いアイデアですが、それでも問題は設計についてではなく、むしろ実装です。 – piotrpo

+0

メッセージングは​​必要ありません。「サービス」はバインドされているため、単純な関数呼び出しで十分です。インタフェースは実装の一部です。そうでなければ実装はクリーンではありません;) – Vasiliy

関連する問題