2017-01-17 8 views
2

"SortBy"を変更すると、私のプログラムはNetworkIOを実行して最上位のムービーを取得して表示します。Android RxJava非同期呼び出しマップ機能

しかし、私がmapに機能callsubscribeOn(Schedulers.io())、NETWORKIO MovieDB.getPopular()MovieDB.getTopRated()を行っているものの、メインスレッド上でexcutedているようだと私はandroid.os.NetworkOnMainThreadExceptionを取得します。

私はpublic Movie[] call(SortBy sortBy)を非同期にする方法を知りました。

sortObservable.map(new Func1<SortBy, Movie[]>() { 
    @Override 
    public Movie[] call(SortBy sortBy) { 
     try { 
      switch (sortBy) { 
       case POPULAR: 
        return MovieDB.getPopular(); // NETWORK IO 
       case TOP_RATED: 
        return MovieDB.getTopRated(); // NETWORK IO 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } catch (JSONException e) { 
      e.printStackTrace(); 
     } 
     return new Movie[0]; 
    } 
}) 
     .subscribeOn(Schedulers.io()) 
     .observeOn(AndroidSchedulers.mainThread()) 
     .subscribe(new Action1<Movie[]>() { 
      @Override 
      public void call(Movie[] movies) { 
       imageAdapter.loadData(movies); 
      } 
     }); 
+0

、およびラップをあなたのioは観察可能な状態で呼び出します。 – njzk2

+0

'subscribeOn'は' subscribe'が呼び出される場所です。先のobservableのスレッドを制御するには 'observeOn'を使います。 – njzk2

+0

@ njzk2私はまだ 'android.os.NetworkOnMainThreadException'を取得しています。ソースコードはhttps://github.com/zizhengwu/Popular-Movies-Stage-1/blob/load-image/app/src/main/java/です。 com/zizhengwu/popular_movies_stage_1/MainActivity.java#L75 – knx54693

答えて

0

最後に、私は自分でそれを整理返すことができます:あなたの代わりに `flatMap`を使用することができます

sortObservable.flatMap(new Func1<SortBy, Observable<Movie[]>>() { 

    @Override 
    public Observable<Movie[]> call(SortBy sortBy) { 
     switch (sortBy) { 
      case POPULAR: 
       return Observable.fromCallable(() -> MovieDB.getPopular()).subscribeOn(Schedulers.io()); 
      case TOP_RATED: 
       return Observable.fromCallable(() -> MovieDB.getTopRated()).subscribeOn(Schedulers.io()); 
      default: 
       return Observable.fromCallable(() -> new Movie[0]).subscribeOn(Schedulers.io()); 
     } 
    } 
}) 
     .observeOn(AndroidSchedulers.mainThread()) 
     .subscribe(new Action1<Movie[]>() { 
      @Override 
      public void call(Movie[] movies) { 
       imageAdapter.loadData(movies); 
      } 
     }); 
0

以下が有効かどうかをご確認ください。 mapの代わりにflatMapを使用します。 Githubの上のあなたのソースコードから

sortObservable.flatMap(new Func1<SortBy, Observable<Movie[]>>() { 

     @Override 
     public Observable<Movie[]> call(SortBy sortBy) { 
      try { 
       switch (sortBy) { 
        case POPULAR: 
         return Observable.just(MovieDB.getPopular()); // NETWORK IO 
        case TOP_RATED: 
         return Observable.just(MovieDB.getTopRated()); // NETWORK IO 
       } 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } catch (JSONException e) { 
       e.printStackTrace(); 
      } 
      return Observable.just(new Movie[0]); 
     } 
    }).subscribe(new Action1<Movie[]>() { 
     @Override 
     public void call(Movie[] movies) { 
      imageAdapter.loadData(movies); 
     } 
    }); 

あなたがOkHttpを使用して要求を実行する同期モードを使用しているように、それはそうです。 OkHttpは非同期要求もサポートしています。以下は、いくつかの方法で必要とされる変更です。

  1. run方法はenqueue代わりのexecuteを消費する必要があります。

    Observable<String> runAsync(String url){ 
    return Observable.create(subscriber -> { 
        Request request = new Request.Builder().url(url).build(); 
    
        client.newCall(request).enqueue(new Callback() { 
    
         @Override 
         public void onResponse(Call call, Response response) throws IOException { 
          subscriber.onNext(response.body().string()); 
         } 
    
         @Override 
         public void onFailure(Call call, IOException e) { 
          subscriber.onError(e); 
         } 
        }); 
    }); 
    } 
    
  2. getApiObservable<Movie[]>代わりのMovie[]

    public Observable<Movie[]> getApiAsync(String type){ 
    return runAsync("http://api.themoviedb.org/3/movie/" + type 
         + "?api_key=412e9780d02673b7599233b1636a0f0e").flatMap(response -> { 
          Gson gson = new Gson(); 
          Map<String, Object> map = gson.fromJson(response, 
            new TypeToken<Map<String, Object>>() { 
            }.getType()); 
          Movie[] movies = gson.fromJson(gson.toJson(map.get("results")), 
            Movie[].class); 
          return Observable.just(movies); 
         }); 
    } 
    
+0

'android.os.NetworkOnMainThreadException'が表示されます。ソースコードはこちら:https://github.com/zizhengwu/Popular-Movies-Stage-1/blob/load-image/app/src/main/java/com/zizhengwu/popular_movies_stage_1/MainActivity.java#L75 – knx54693

+0

その問題rxとは関係ないので、[AsyncTask](https://developer.android.com/reference/android/os/AsyncTask.html)を使ってそれを克服することができます。 http://stackoverflow.com/a/6343299/3940047 –

+0

https://github.com/ReactiveX/RxJavaAsyncUtilも試すことができますか? –

関連する問題