2017-05-23 18 views
2

私は現在、Objective-Cで書かれたネットワーキングライブラリをJavaに移植しています。サードパーティのライブラリに依存することなく非同期HTTPリクエストをサーバに送信する機能が必要です、Apacheの依存関係はありません)。これを行うにはHTTPUrlConnectionを使用しています。しかし、あなたが知っているように、それは同期プロセスです。メインスレッドをブロックせずにHTTP応答を取得する

ExecutorServiceFuture<>構造体を使用して、このプロセスに並行処理を実装しようとしています。サーバーが返信する応答メッセージを処理する必要があるため、Runnableの代わりにCallableを使用する必要があります。ここで私がやっているかの小さな概要です:reqMsgは(XMLで)要求メッセージをある

ExecutorService executorService = Executors.newSingleThreadExecutor(); 
    Future<String> future = executorService.submit(new Callable<String>() { 
    @Override 
    public String call() throws Exception { 
     return postRequest(reqMsg); 
    } 
    }); 

は、とpostRequest方法は、(また、XMLで)文字列として応答メッセージを返します。今、このCallableタスクの戻り値を取得するために、future.get()を使用する必要があります。ただし、このメソッドはブロッキング呼び出しです。つまり、応答が利用可能になるまでメインスレッドをブロックします。これは私が望むものではありません。

私はAndroidにiOSアプリケーションを移植しています。これらのプラットフォーム間でクロスプラットフォームの共有ライブラリを使用するにはJ2ObjCを使用します。 iOSバージョン(ライブラリのObj-Cバージョンを意味します)には、HTTPリクエストの結果を処理する完了ハンドラがあり、非同期で行われます。残念ながら、JavaはCompletableFutureを使用してこのコールバックをJava 8で処理する方法を導入しました。しかし、AndroidはAPIレベル24から始まるCompletableFutureのみをサポートしています。私はJelly Bean(API 16)に戻るAPIレベルをサポートできるようにしたいと考えています。そして、私が知る限り、「JARファイルがAndroidと互換性があるため、Androidの一部として利用可能なクラスや、JAR自体に特別に実装された他のクラスのみを参照できます。 AsyncTasksを使用することをお勧めします。しかし、このライブラリは2つのプラットフォーム間で共有される可能性が高いため、Javaネットワーキング側でHTTP要求の同時実行性を処理したいと考えています。

スレッドを明示的に使用しようとしました。しかし、Callablesを使うためには、ExecutorServiceとFutureを使用する必要があることが分かりました。さらに、<の1000msのオーバーヘッドは許容されるとは思うが、明示的にスレッドを作成する際のパフォーマンス上のオーバーヘッドがあるようだ。 )。それは絶対に必要でない限り、私は、サードパーティのライブラリに依存したくない

  • :そして再び、ちょうど(:DRすなわちTL)を改めて表明しました。私は私の最小APIレベルは16

  • になりたいと、私はもともと、これは中に処理されるように私は、AsyncTasksとAndroidの側に、この同時実行を処理したくない、CompletableFutureを使用することはできません

  • CompletionHandler(Objective-C)のネットワークライブラリです。

ブロックすることなくFuture.get()を使用する方法はありますか? (whileループチェックFuture.isDone()もメインスレッドをブロックすることを通知します)。

+1

[How to Ask](https://stackoverflow.com/help/how-to-ask)をお読みください。あなたの質問のテキストは非常に長く、このサイトのほとんどの人はそれを読んであきらめます。 – litelite

答えて

2

Future.get()はブロッキング操作であり、変更することはできません。

ここで必要なのは、ジョブが完了するとコールバックを取得することです。このためには、Futureをまったく使用する必要はありません。 Executor.execute()Runnableは、Callableと全く同じことを行うことができますが、値を返す代わりに、カスタムと呼ばれる値を返す代わりに、メソッドのparameter-callbackに値を指定して使用できます。基本的に毎回executorを作成しないでください。また

ExecutorService executorService = Executors.newSingleThreadExecutor(); 

public void execute(YourRequestObject reqMsg, Consumer<String> consumer) { 
    executorService.execute(new Runnable() { 
     @Override 
     public void run() { 
      String result = postRequest(reqMsg); 
      consumer.accept(result); 
     } 
    }); 
} 

のJava 8にConsumerインターフェースの同等導入されたこと。すべての操作に1つのエグゼキュータを使用してください。おそらくsingleThreadの代わりにキャッシュされたものでしょう。

コールバックはエグゼキュータスレッドで呼び出されることに注意してください。 UIを更新する場合は、UIハンドラに投稿する必要があります。

+0

ありがとう、私はそれを試してみましょう! – epekel

0

ご質問はあまり意味がありません。一方では、別のスレッドでデータをフェッチしたいが、フェッチスレッドが完了するのを待つことなく別のスレッドで取得する。

あなたがしなければならないことは、フェッチをラップし、「取得したデータを何であれ」を実行可能にして、別のスレッドで実行することです。

フェッチされたデータでイベントディスパッチスレッドを更新する必要がある場合は、必ずイベントディスパッチスレッドのUIを更新してください。

+0

ありがとう、それは今行くよ! – epekel

関連する問題