4

アプリがあります。ユーザーがすべてのデータを一度にクラウドに同期できるようにする大きなボタンがあります。すべてのデータを再度送信できるようにする再同期機能。(300以上のエントリー)

RXjava2 と retrofit2 を使用しています。単一の呼び出しで単体テストを実行しています。ただし、N 個のネットワーク呼び出しを行う必要があります。

私が避けたいのは、オブザーバブルがキュー内の次のアイテムを呼び出すことです。ランナブルを実装する必要があるところです。マップについては少し見たことがありますが、マップをキューとして使用している人は見たことがありません。また、Zip機能のように、1つのアイテムが失敗し、すべてのアイテムが失敗したと報告されることを避けたい. キューを追跡する厄介なマネージャー クラスを実行する必要がありますか? または、数百のアイテムを送信するためのよりクリーンな方法はありますか?

注: ソリューションは、JAVA8 / ラムダに依存することはできません。それは正当化されるよりもはるかに多くの作業であることが証明されています。

すべてのアイテムが同じオブジェクトであることに注意してください。

    @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();
}

すべてのアイテムを収集して送信するヘルパー

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();
    }

}

私のレトロフィットのもの

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);
 }

アップデート。私はこの答えを運が悪いことに適用しようとしています。私は今夜​​のために蒸気を使い果たしています。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.

編集。もうラムダを試していません。Mac でパスを設定した後でも、javahome が 1.8 を指すように設定した後でも、動作させることができませんでした。これがもっと新しいプロジェクトだったら、もっと頑張るだろう。ただし、これは Android を試している Web 開発者によって作成された継承された Android アプリケーションであるため、優れたオプションではありません。また、それを機能させるために時間を浪費する価値もありません。かかるはずだった半日ではなく、すでにこの割り当ての日々に入っています。

非ラムダ フラットマップの良い例が見つかりませんでした。私はそれを自分で試してみましたが、めちゃくちゃになりました。

4

1 に答える 1

1

私の理解が正しければ、並行して電話をかけたいですか?

したがって、これを行う rx-y の方法は次のようになります。

    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 */});

ClientSecureDataToolKitこの部分をコンストラクターに移動する

    InterfaceSecureDataToolKit interfaceSecureDataToolKit = mRetrofit.create(InterfaceSecureDataToolKit.class);
于 2017-01-12T12:50:38.540 に答える