Sur le changement "SortBy", mon programme fera un NetworkIO pour récupérer les meilleurs films et les afficher.

Cependant, il semble que bien que j'aie fait subscribeOn(Schedulers.io()), le NetworkIO MovieDB.getPopular() et MovieDB.getTopRated() dans la fonction call dans map sont exécutés sur le fil principal et je obtenir un android.os.NetworkOnMainThreadException.

Je me demandais comment rendre le public Movie[] call(SortBy sortBy) asynchrone.

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);
            }
        });
3
knx54693 17 janv. 2017 à 06:42

2 réponses

Meilleure réponse

Enfin je le trie moi-même:

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);
            }
        });
1
knx54693 19 janv. 2017 à 13:19

Veuillez vérifier si ce qui suit fonctionne pour vous. Il utilise flatMap au lieu de map.

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

À partir de votre code source sur Github, il semble que vous utilisez le mode synchrone d'exécution des requêtes à l'aide d'OkHttp. OkHttp prend également en charge les requêtes asynchrones et cela peut être préféré. Voici les changements requis dans quelques-unes des méthodes.

  1. La méthode run doit consommer enqueue au lieu de 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. getApi peut renvoyer un Observable<Movie[]> au lieu de 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
Pavan Kumar 17 janv. 2017 à 08:06