2

私は、(クライアント側から)同期方法でいくつかのインテントの送受信を行うライブラリを作りたいと思います。そのため、私の図書館のクライアントは、受信者の実装に気を配る必要はありません。Android - sendBroadcast()とonReceive() - プロセス間通信のための同期ソリューション

ライブラリはインテントをどこかに送り、応答を受け取ります。次に、結果をクライアントに同期して返します。

ユースケースは、インテントを使用して自分のアプリケーション間でデータを転送する場合です。通常はインテントとレシーバを非同期で使用しますが、これはルールの例外です。

提案されている解決策(簡略化!)図書館:

public class Helper { 
private Context context; 
private BroadcastReceiver tempReceiver; 
private int result = 0; 

int getResult() { 

    tempReceiver = new BroadcastReceiver() { 
     @Override 
     public void onReceive(Context context, Intent intent) { 
      Helper.this.result = 1; 
     } 
    }; 
    context.registerReceiver(tempReceiver); 
    context.sendBroadcast(/* ask for smth */); 

    Thread.sleep(5000); 

    context.unregisterReceiver(tempReceiver); 
    return result; 
} 
} 

クライアントがそのように、ライブラリからいくつかのデータを取得したいアプリケーションです:あなたはそれについて

int timeout = 5000; 
Helper lib = new Helper(timeout); 
lib.getData(); 

どう思いますか?脅威とは何ですか? getReturn()を呼び出すとブロックされ、GUIスレッドで呼び出すことができないことを理解しています。睡眠解答が受け入れられるかどうかという疑問。

+0

私は本当に 'Thread.sleep'の使用をお勧めしません。 5秒後には、[Handler.postDelayed'](http://goo.gl/rYpyp)を使用してください。 – Jakar

+0

しかし私が知る限り、postDelayedは非同期なので、この例では動作しません。このメソッドは、応答が準備できるまで(ストリームからの読み込みなど)クライアントをフリーズする必要があることに注意してください。 – Kacper86

答えて

2

私はあなたが既に標準的な同期と非同期のトレードオフ、それが有利ではない状況を認識していると思います。

IMOでは、自分のアプリケーションからブロードキャストも送信された場合に限り、あなたのアプローチは問題ありません。システムブロードキャストに興味がある場合は、5秒の遅延が許容範囲と致命的な間で変化する可能性があります。 「写真を撮った」ブロードキャストに登録した後、5秒後に別の写真を撮っていると、同期コールが戻ってきて何かを表示してユーザーに迷惑をかけます。

ブロードキャストが1回限りではなくむしろ連続的な場合にどのように対処することを提案しますか?

私は、カバーの下にAsyncTaskを使用してAPIを設計しようとしました。それを同期的な方法で公開する必要があります。しかし、このAPIの使用法はクライアントコードにとってははるかに混乱していることが判明しました。私は、特定のことは同期的に行われることを意味するものではないと結論づけました。コールバックベースの非同期アプローチを進めました。私が作ろうとしている点は、放送は単に同期することではないということです。

ちょうど私の2セントです。

+0

私はそれを使いたい特定のユースケースを1つ持っています。 私はApplication1にApplication2に小さなデータを尋ねて欲しいです。そしてそれは連続的ではないと考えられています。ただ1回のリクエストです。 はい、私のアプリケーションはインテントをブロードキャストし、他のアプリケーションはそれを受信して​​それに応答します。 – Kacper86

+0

私は参照してください。その場合、あなたはこの設計で逃げることができます。タイムアウトが経過した後にデータが利用できないケースを処理するために、クライアントコードにonusが追加されていることに注意してください。これを非同期設計と比較すると、クライアントコードが通知されるだけである - データがすぐに利用可能かどうか。または10秒後。また、データがすぐに利用できる場合でも、アプリケーション1はまだ5秒遅れています。 – curioustechizen

+1

あなたの洞察をいただきありがとうございます。私はループを作ることができると思う: 'for(int i = 0; i <10; i ++){ Thread.sleep(100); if(result!= 0){ break; } } ' これはもっと反応的なものになるでしょう。 Btw。私はいくつかの問題がある低レベルプログラミングのようなものだと理解していますが、この場合はクライアント側にとって簡単です。 – Kacper86

1

私はあなたが正確に達成しようとしていることを理解していません。
ブロードキャスタは誰ですか?受信者は誰ですか?ライブラリとクライアントコードの間のコミュニケーションのより良い記述が役に立つでしょう。

ブロードキャストはとにかく非同期です(sendBroadcast)。受信者はUIスレッドで呼び出されます。それはと同時に動作します。しかし、いつ呼び出されるかは保証されません。アンドロイドシステムはできるだけ早くそれを行います。

本当に間違ったデザイン決定のような睡眠の縫い目で同期すると、どのような放送を使用するべきではありません。

同期コールバックが必要な場合は、アンドロイドのようにリスナーパターンをおすすめします。 onClickインターフェイス。

+0

コメントありがとうございました!私はtechie.curiousのコメントでこのデザインを少し説明しようとしました。 ストリームからブロックを読み取るように使用される1つのブロッキングメソッドに「送信インテント」と「レスポンスを受信」することを想像してみましょう。 – Kacper86

+0

私は参照してください。これはアプリケーション間の通信です。それは重要な事実です。あなたはあなたの質問に言及すべきです。それは疑問を「プロセス間のコミュニケーション」に押し上げるでしょう。私は前にそれを試したことがないので、私はそこにお手伝いできません、申し訳ありません。 – Knickedi

+0

あなたが正しいです、私は詳細を追加します。ありがとう! – Kacper86

0

- 同期

public abstract class WorkerThread { 

    @Override 
    public void run() { 
     // loop 
     while(!isCanceled()) { 
      try { 
       // wait() 
       waitUntilResumed(): 
       // when notified do work 
       doWork(): 
      } catch (InterruptedException e) { 
       // restore interrupted state 
      } 
     } 
    } 

    /** 
    * main thread loop 
    */ 
    protected abstract void doWork() throws InterruptedException; 

    /** 
    * blocks current thread until it is resumed 
    */ 
    private synchronized void waitUntilResumed() throws InterruptedException { 
     while (isPaused()) { 
      wait(); 
     } 
    } 

    /** 
    * resume thread 
    */ 
    public synchronized void resumeAction() { 
     notifyAll(); 
    } 

} 
関連する問題