2017-01-12 2 views
4

私はアプリを持っています。私は、ユーザーがすべてのデータを一度にクラウドに同期できる大きなボタンを持っています。すべてのデータを再度送信できる再同期機能。 (300以上のエントリ)Rxjava2 + Retrofit2 + Android。何百ものネットワーク通話を行う最良の方法

私はRXjava2とretrofit2を使用しています。私は私の単体テストを1回の呼び出しで処理します。しかし、私はNネットワークコールを行う必要があります。

私が避けたいのは、観測可能なコールをキュー内の次のアイテムに呼び出すことです。私は私のrunnableを実装する必要がある時点です。私はマップについて少しは見ましたが、誰もそれをキューとして使用していることは見ていません。また、私は1つのアイテムが失敗するのを避けるために、Zip機能のように、すべてのアイテムが失敗するため、レポートを返します。私はちょうどキューを追跡する厄介なマネージャクラスを行うべきですか?または、数百のアイテムを送るためのクリーンな方法がありますか?

注意:解決策は、JAVA8/LAMBDASに従うことはできません。それは、正当化されたよりも多くの仕事があることが判明しています。

すべての項目は同じオブジェクトです。私のレトロフィットのもの

public class ClientSecureDataToolKit { 

    private static ClientSecureDataToolKit mClientSecureDataToolKit; 
    private static Retrofit mRetrofit; 

    private ClientSecureDataToolKit(){ 
     mRetrofit = new Retrofit.Builder() 
     .baseUrl(Utilities.getSecureDataToolkitURL()) 
     .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 
     .addConverterFactory(GsonConverterFactory.create()) 
     .build(); 
    } 

    public static ClientSecureDataToolKit getClientSecureDataKit(){ 
     if(mClientSecureDataToolKit == null){ 
      mClientSecureDataToolKit = new ClientSecureDataToolKit(); 
     } 
     return mClientSecureDataToolKit; 
    } 

    public Observable<Record> putUserDataToSDK(PayloadSecureDataToolKit payloadSecureDataToolKit){ 
     InterfaceSecureDataToolKit interfaceSecureDataToolKit = mRetrofit.create(InterfaceSecureDataToolKit.class); 
     Observable<Record> observable = interfaceSecureDataToolKit.putRecord(NetworkUtils.SECURE_DATA_TOOL_KIT_AUTH, payloadSecureDataToolKit); 
     return observable; 
    } 

} 

public interface InterfaceSecureDataToolKit { 

@Headers({ 
     "Content-Type: application/json" 
}) 

@POST("/api/create") 
Observable<Record> putRecord(@Query("api_token") String api_token, @Body PayloadSecureDataToolKit payloadSecureDataToolKit); 
} 

更新

public class SecureDataToolKitHelper { 
private final static String TAG = "SecureDataToolKitHelper"; 
private final static SimpleDateFormat timeStampSimpleDateFormat = 
     new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 


public static void uploadAll(Context context, RuntimeExceptionDao<EventModel, UUID> eventDao) { 
    List<EventModel> eventModels = eventDao.queryForAll(); 

    QueryBuilder<EventModel, UUID> eventsQuery = eventDao.queryBuilder(); 
    String[] columns = {...}; 

    eventsQuery.selectColumns(columns); 

    try { 
     List<EventModel> models; 

     models = eventsQuery.orderBy("timeStamp", false).query(); 
     if (models == null || models.size() == 0) { 
      return; 
     } 

     ArrayList<PayloadSecureDataToolKit> toSendList = new ArrayList<>(); 
     for (EventModel eventModel : models) { 
      try { 
       PayloadSecureDataToolKit payloadSecureDataToolKit = new PayloadSecureDataToolKit(); 

       if (eventModel != null) { 


        // map my items ... not shown 

        toSendList.add(payloadSecureDataToolKit); 
       } 
      } catch (Exception e) { 
       Log.e(TAG, "Error adding payload! " + e + " ..... Skipping entry"); 
      } 
     } 

     doAllNetworkCalls(toSendList); 

    } catch (SQLException e) { 
     e.printStackTrace(); 
    } 

} 

すべての私のアイテムを収集し、送信するために

@Test 
public void test_Upload() { 
    TestSubscriber<Record> testSubscriber = new TestSubscriber<>(); 
    ClientSecureDataToolKit clientSecureDataToolKit = ClientSecureDataToolKit.getClientSecureDataKit(); 
    clientSecureDataToolKit.putUserDataToSDK(mPayloadSecureDataToolKit).subscribe(testSubscriber); 

    testSubscriber.awaitTerminalEvent(); 
    testSubscriber.assertNoErrors(); 
    testSubscriber.assertValueCount(1); 
    testSubscriber.assertCompleted(); 
} 

マイヘルパー。私は多くの運にこの答えを適用しようとしています。私は今夜​​のために蒸気を使い果たしている。私は1つのアイテムの元のコールのために行ったように私は..

public class RxJavaBatchTest { 
    Context context; 
    final static List<EventModel> models = new ArrayList<>(); 

    @Before 
    public void before() throws Exception { 
     context = new MockContext(); 
     EventModel eventModel = new EventModel(); 
     //manually set all my eventmodel data here.. not shown 

     eventModel.setSampleId("SAMPLE0"); 
     models.add(eventModel); 
     eventModel.setSampleId("SAMPLE1"); 
     models.add(eventModel); 
     eventModel.setSampleId("SAMPLE3"); 
     models.add(eventModel); 


    } 

    @Test 
    public void testSetupData() { 
     Assert.assertEquals(3, models.size()); 
    } 

    @Test 
    public void testBatchSDK_Upload() { 


     Callable<List<EventModel> > callable = new Callable<List<EventModel> >() { 

      @Override 
      public List<EventModel> call() throws Exception { 
       return models; 
      } 
     }; 

     Observable.fromCallable(callable) 
       .flatMapIterable(models -> models) 
       .flatMap(eventModel -> { 
        PayloadSecureDataToolKit payloadSecureDataToolKit = new PayloadSecureDataToolKit(eventModel); 
        return doNetworkCall(payloadSecureDataToolKit) // I assume this is just my normal network call.. I am getting incompatibility errors when I apply a testsubscriber... 
          .subscribeOn(Schedulers.io()); 
       }, true, 1); 
    } 

    private Observable<Record> doNetworkCall(PayloadSecureDataToolKit payloadSecureDataToolKit) { 

     ClientSecureDataToolKit clientSecureDataToolKit = ClientSecureDataToolKit.getClientSecureDataKit(); 
     Observable observable = clientSecureDataToolKit.putUserDataToSDK(payloadSecureDataToolKit);//.subscribe((Observer<? super Record>) testSubscriber); 
     return observable; 
    } 

結果が..です何かが多分右ラムダを使用していないように見えます..ユニットテストとしてこれを実装する

をしようとしています
An exception has occurred in the compiler (1.8.0_112-release). Please file a bug against the Java compiler via the Java bug reporting page (http://bugreport.java.com) after checking the Bug Database (http://bugs.java.com) for duplicates. Include your program and the following diagnostic in your report. Thank you. 
com.sun.tools.javac.code.Symbol$CompletionFailure: class file for java.lang.invoke.MethodType not found 


FAILURE: Build failed with an exception. 

* What went wrong: 
Execution failed for task ':app:compile<MyBuildFlavorhere>UnitTestJavaWithJavac'. 
> Compilation failed; see the compiler error output for details. 

編集。もはやLambdasを試していない。私のMacでパスを設定した後でも、javahomeが1.8などを指すようにしても、動作させることができませんでした。これが新しいプロジェクトであれば、私はもっと力を入れるだろう。しかし、これはアンドロイドを試してWeb開発者によって書かれた継承されたアンドロイドアプリケーションであるため、それは素晴らしい選択肢ではありません。それを稼働させるには、時間をとる価値がありません。今半日ではなく、この割り当ての日に、それが取られていたはずです。

いいえラムダフラットマップの例が見つかりませんでした。私は自分自身でそれを試して、それは乱雑になっていた。

+0

にこの部分

Observable.fromCallable(() -> eventsQuery.orderBy("timeStamp", false).query()) .flatMapIterable(models -> models) .flatMap(model -> { // map your model //avoid throwing exceptions in a chain, just return Observable.error(e) if you really need to //try to wrap your methods that throw exceptions in an Observable via Observable.fromCallable() return doNetworkCall(someParameter) .subscribeOn(Schedulers.io()); }, true /*because you don't want to terminate a stream if error occurs*/, maxConcurrent /* specify number of concurrent calls, typically available processors + 1 */) .subscribe(result -> {/* handle result */}, error -> {/* handle error */}); 

:これを行うの

だから、RX-yの方法は次のようになりますそれはすべて1つのストリームです。私の編集された答えを見て、それはあなたが購読するべきです。また、https://medium.com/@peter.tackage/overriding-rxandroid-schedulers-in-rxjava-2-5561b3d14212#をご覧ください。86w266e9r –

+0

あなたのテストの 'models'リストには、同じオブジェクトが3回繰り返されています。 sampleIdは "SAMPLE3"に等しい。 –

+0

ええと私は思っていた。私のコンパイラはフラットマップの最初の引数の実装が好きではないと思っている。 <??スーパーT、拡張ObservableSource > (機能マッパー、 – StarWind0

答えて

1

私が正しく理解していれば、通話を並行して行いたいですか?ので、あなたのClientSecureDataToolKit動きであなたは、内側に観察に加入する必要はありませんコンストラクタ

InterfaceSecureDataToolKit interfaceSecureDataToolKit = mRetrofit.create(InterfaceSecureDataToolKit.class); 
+0

私はそれを後で試してみる。 – StarWind0

+0

これを見ると、Lambdaは問題です...これはJava 7です。土地(andr oid)しかし、それは素晴らしい出発点です。しかし、Java 8を実行することは可能ですが、この継承プロジェクトには問題がある可能性があります。 – StarWind0

+0

retrolambdaを見てください。それはアンドロイドで誰もが使用しています。 –

関連する問題