2016-01-12 17 views
7

私は2つの非同期タスクを実行したい。私はZIPやFlatについて何かを読んだことがありますが、私はそれをよく理解していませんでした。Android RxJava Observableで2つのクエリを順番に実行するにはどうすればよいですか?

私の目的はローカルSQLiteからデータをロードすることです。終了すると、リモート)。

誰かが私にそれを達成する方法を提案できますか?

これは私が(単一のタスク)を使用していますRxJava観察可能なスケルトンです:

// RxJava Observable 
    Observable.OnSubscribe<Object> onSubscribe = subscriber -> { 
     try { 

      // Do the query or long task... 

      subscriber.onNext(object); 
      subscriber.onCompleted(); 
     } catch (Exception e) { 
      subscriber.onError(e); 
     } 
    }; 

    // RxJava Observer 
    Subscriber<Object> subscriber = new Subscriber<Object>() { 
     @Override 
     public void onCompleted() { 
      // Handle the completion 
     } 

     @Override 
     public void onError(Throwable e) { 
      // Handle the error 
     } 

     @Override 
     public void onNext(Object result) { 

      // Handle the result 

     } 
    }; 

    Observable.create(onSubscribe) 
      .subscribeOn(Schedulers.newThread()) 
      .observeOn(AndroidSchedulers.mainThread()) 
      .subscribe(subscriber); 
+1

[RxJava:chaining observables]の可能な複製(http://stackoverflow.com/questions/26935821/rxjava-chaining-observables) –

答えて

6

それを行うには、オペレータがmergeなり、http://reactivex.io/documentation/operators/merge.htmlを参照してください。

私のアプローチは、2つの観測を作成するのがobservableLocalobservableRemoteを言わせて、出力をマージするために、次のようになります。

Observable<Object> observableLocal = Observable.create(...) 
Observable<Object> observableRemote = Observable.create(...) 
Observable.merge(observableLocal, observableRemote) 
      .subscribe(subscriber) 

あなたは、リモート、ローカル後に実行されていることを確認したい場合は、concatを使用することができます。

+1

これは、observableLocalおよびobservableRemoteが、同じオブジェクトまたはこのオブジェクトが拡張するものを返す場合にのみ機能します – Sniper

6

ルーカスバトーの答えは、クエリが互いに依存していない場合に最適です。しかし、のデータをの前に取得する必要がある場合(リモートクエリのパラメータやヘッダーのデータが必要な場合など)、ローカルの観測可能なフラットマップから開始することができますそれはあなたがローカルクエリからデータを取得後2つの観測を結合する:

Observable<Object> localObservable = Observable.create(...) 
    localObservable.flatMap(object -> 
    { 
     return Observable.zip(Observable.just(object), *create remote observable here*, 
      (localObservable, remoteObservable) -> 
      { 
       *combining function* 
      }); 
    }).subscribe(subscriber); 

flatmap機能を使用すると、ジップ機能を介してローカル&遠隔観測の組み合わせにローカルに観察を変換することができます。繰り返して言うと、ここでの利点は、2つの観測値が連続的であり、zip関数は両方の従属観測値が実行された後にのみ実行されることです。

さらに、zip関数を使用すると、基になるオブジェクトのタイプが異なる場合でも、オブザーバブルを組み合わせることができます。その場合、3番目のパラメータとして結合関数を指定します。基になるデータが同じタイプの場合は、zip関数をマージで置き換えます。

1

私の解決策を試すことができます。問題を解決するにはいくつかの方法があります。それが働いていることを確認する
は、私は例の作業だけでスタンドを作成し、テストするには、このAPIを使用します。https://jsonplaceholder.typicode.com/posts/1

private final Retrofit retrofit = new Retrofit.Builder() 
      .baseUrl("https://jsonplaceholder.typicode.com/posts/") 
      .addConverterFactory(GsonConverterFactory.create()) 
      .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 
      .build(); 

    private final RestPostsService restPostsService = retrofit.create(RestPostsService.class); 

    private Observable<Posts> getPostById(int id) { 
     return restPostsService.getPostsById(id); 
    } 

RestPostServiceを。Javaの

package app.com.rxretrofit; 

import retrofit2.http.GET; 
import retrofit2.http.Path; 
import rx.Observable; 

/** 
* -> Created by Think-Twice-Code-Once on 11/26/2017. 
*/ 

public interface RestPostsService { 

    @GET("{id}") 
    Observable<Posts> getPostsById(@Path("id") int id); 
} 

ソリューション1:配列中に使用呼び出し、複数のタスク、前回のタスクの結果は、常に次のタスク

getPostById(1) 
       .concatMap(posts1 -> { 
        //get post 1 success 
        return getPostById(posts1.getId() + 1); 
       }) 
       .concatMap(posts2 -> { 
        //get post 2 success 
        return getPostById(posts2.getId() + 1); 
       }) 
       .concatMap(posts3 -> { 
        //get post 3success 
        return getPostById(posts3.getId() + 1); 
       }) 
       .subscribeOn(Schedulers.io()) 
       .observeOn(AndroidSchedulers.mainThread()) 
       .subscribe(finalPosts -> { 
        //get post 4 success 
        Toast.makeText(this, "Final result: " + finalPosts.getId() + " - " + finalPosts.getTitle(), 
          Toast.LENGTH_LONG).show(); 
       }); 

の入力である対処方法2複数のタスクを連続して呼び出す場合に使用します。以前のタスクのすべての結果はin (例:アバター画像と表紙画像をアップロードした後、これらの画像のURLを持つ新しいユーザーを作成するためのAPIを呼び出す)、最終的なタスクのプット

Observable 
       .zip(getPostById(1), getPostById(2), getPostById(3), (posts1, posts2, posts3) -> { 
        //this method defines how to zip all separate results into one 
        return posts1.getId() + posts2.getId() + posts3.getId(); 
       }) 
       .flatMap(finalPostId -> { 
        //after get all first three posts, get the final posts, 
        // the final posts-id is sum of these posts-id 
        return getPostById(finalPostId); 
       }) 
       .subscribeOn(Schedulers.io()) 
       .observeOn(AndroidSchedulers.mainThread()) 
       .subscribe(finalPosts -> { 
        Toast.makeText(this, "Final posts: " + finalPosts.getId() + " - " + finalPosts.getTitle(), 
          Toast.LENGTH_SHORT).show(); 
       }); 

AndroidManifest

<uses-permission android:name="android.permission.INTERNET"/> 

ルートbuild.gradle

// Top-level build file where you can add configuration options common to all sub-projects/modules. 

buildscript { 
    repositories { 
     jcenter() 
    } 
    dependencies { 
     classpath 'com.android.tools.build:gradle:2.3.3' 
     classpath 'me.tatarka:gradle-retrolambda:3.2.0' 
     classpath 'me.tatarka.retrolambda.projectlombok:lombok.ast:0.2.3.a2' 

     // NOTE: Do not place your application dependencies here; they belong 
     // in the individual module build.gradle files 
    } 

    // Exclude the version that the android plugin depends on. 
    configurations.classpath.exclude group: 'com.android.tools.external.lombok' 
} 

allprojects { 
    repositories { 
     jcenter() 
    } 
} 

task clean(type: Delete) { 
    delete rootProject.buildDir 
} 

アプリ/ build.gradle

apply plugin: 'me.tatarka.retrolambda' 
apply plugin: 'com.android.application' 

android { 
    compileSdkVersion 26 
    buildToolsVersion "26.0.1" 
    defaultConfig { 
     applicationId "app.com.rxretrofit" 
     minSdkVersion 15 
     targetSdkVersion 26 
     versionCode 1 
     versionName "1.0" 
     testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 
    } 
    buildTypes { 
     release { 
      minifyEnabled false 
      proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 
     } 
    } 

    compileOptions { 
     sourceCompatibility JavaVersion.VERSION_1_8 
     targetCompatibility JavaVersion.VERSION_1_8 
    } 
} 

dependencies { 
    compile fileTree(dir: 'libs', include: ['*.jar']) 
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 
     exclude group: 'com.android.support', module: 'support-annotations' 
    }) 
    compile 'com.android.support:appcompat-v7:26.+' 
    compile 'com.android.support.constraint:constraint-layout:1.0.2' 
    testCompile 'junit:junit:4.12' 

    provided 'org.projectlombok:lombok:1.16.6' 
    compile 'com.squareup.retrofit2:retrofit:2.3.0' 
    compile 'com.squareup.retrofit2:converter-gson:2.3.0' 
    compile 'com.squareup.retrofit2:adapter-rxjava:2.3.0' 
    compile 'io.reactivex:rxandroid:1.2.1' 
} 

モデル

package app.com.rxretrofit; 
import com.google.gson.annotations.SerializedName; 
/** 
* -> Created by Think-Twice-Code-Once on 11/26/2017. 
*/ 
public class Posts { 
    @SerializedName("userId") 
    private int userId; 
    @SerializedName("id") 
    private int id; 
    @SerializedName("title") 
    private String title; 
    @SerializedName("body") 
    private String body; 
    public int getUserId() { 
     return userId; 
    } 
    public void setUserId(int userId) { 
     this.userId = userId; 
    } 
    public int getId() { 
     return id; 
    } 
    public void setId(int id) { 
     this.id = id; 
    } 
    public String getTitle() { 
     return title; 
    } 
    public void setTitle(String title) { 
     this.title = title; 
    } 
    public String getBody() { 
     return body; 
    } 
    public void setBody(String body) { 
     this.body = body; 
    } 
} 

ところで、のRx +レトロフィット+ダガー+ MVPパターンコンバイン素晴らしいです使用しています。

関連する問題