Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #41 from novoda/movies/arch-components/lifecycle
Architecture Components refactor: LiveData & ViewModel
- Loading branch information
Showing
9 changed files
with
118 additions
and
111 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
99 changes: 28 additions & 71 deletions
99
MoviesExample/app/src/main/java/com/novoda/demo/movies/MovieService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,107 +1,64 @@ | ||
package com.novoda.demo.movies; | ||
|
||
import android.arch.lifecycle.LiveData; | ||
import android.arch.lifecycle.MutableLiveData; | ||
import android.util.Log; | ||
|
||
import com.novoda.demo.movies.api.MoviesApi; | ||
import com.novoda.demo.movies.api.MoviesResponse; | ||
import com.novoda.demo.movies.api.VideosResponse; | ||
import com.novoda.demo.movies.model.Movie; | ||
import com.novoda.demo.movies.model.Video; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
import retrofit2.Call; | ||
import retrofit2.Callback; | ||
import retrofit2.Response; | ||
import rx.Observable; | ||
import rx.Observer; | ||
import rx.functions.Func1; | ||
import rx.schedulers.Schedulers; | ||
|
||
public class MovieService { | ||
|
||
private final MoviesApi api; | ||
private MoviesSate moviesSate = new MoviesSate(new ArrayList<Movie>(), 1); | ||
|
||
private Callback callback; | ||
private final MutableLiveData<List<Movie>> moviesLiveData = new MutableLiveData<>(); | ||
private final MutableLiveData<List<Video>> videosLiveData = new MutableLiveData<>(); | ||
|
||
public MovieService(MoviesApi api) { | ||
this.api = api; | ||
} | ||
|
||
public void subscribe(Callback callback) { | ||
this.callback = callback; | ||
callback.onNewData(moviesSate); | ||
if (moviesSate.isEmpty()) { | ||
loadMore(); | ||
} | ||
} | ||
|
||
public void unsubscribe(Callback callback) { | ||
this.callback = null; | ||
} | ||
|
||
public void loadMore() { | ||
api.topRated(moviesSate.pageNumber()).enqueue(new retrofit2.Callback<MoviesResponse>() { | ||
public LiveData<List<Movie>> loadMore(int page) { | ||
api.topRated(page).enqueue(new Callback<MoviesResponse>() { | ||
@Override | ||
public void onResponse(Call<MoviesResponse> call, Response<MoviesResponse> response) { | ||
if (response == null || response.body() == null || response.body().results == null) { | ||
return; | ||
} | ||
List<Movie> movies = moviesSate.movies(); | ||
movies.addAll(response.body().results); | ||
moviesSate = new MoviesSate(movies, moviesSate.pageNumber() + 1); | ||
callback.onNewData(moviesSate); | ||
moviesLiveData.postValue(response.body().results); | ||
} | ||
|
||
@Override | ||
public void onFailure(Call<MoviesResponse> call, Throwable throwable) { | ||
callback.onFailure(throwable); | ||
public void onFailure(Call<MoviesResponse> call, Throwable e) { | ||
Log.e("Movies", "while loading movies", e); | ||
} | ||
}); | ||
return moviesLiveData; | ||
} | ||
|
||
public void loadTrailerFor(Movie movie, final TrailerCallback trailerCallback) { | ||
api.videos(movie.id) | ||
.flatMapObservable(new Func1<VideosResponse, Observable<Video>>() { | ||
@Override | ||
public Observable<Video> call(final VideosResponse videosResponse) { | ||
return Observable.from(videosResponse.results); | ||
} | ||
}) | ||
.takeFirst(new Func1<Video, Boolean>() { | ||
@Override | ||
public Boolean call(final Video video) { | ||
return video.trailerUrl() != null; | ||
} | ||
}) | ||
.subscribeOn(Schedulers.io()) | ||
.subscribe(new Observer<Video>() { | ||
@Override | ||
public void onCompleted() { | ||
// noop | ||
} | ||
|
||
@Override | ||
public void onError(final Throwable e) { | ||
trailerCallback.onFailure(e); | ||
} | ||
|
||
@Override | ||
public void onNext(final Video video) { | ||
trailerCallback.onTrailerLoaded(video); | ||
} | ||
}); | ||
} | ||
|
||
interface Callback { | ||
void onNewData(MoviesSate moviesSate); | ||
|
||
void onFailure(Throwable e); | ||
} | ||
|
||
interface TrailerCallback { | ||
void onTrailerLoaded(Video video); | ||
public LiveData<List<Video>> loadTrailerFor(Movie movie) { | ||
api.videos(movie.id).enqueue(new Callback<VideosResponse>() { | ||
@Override | ||
public void onResponse(Call<VideosResponse> call, Response<VideosResponse> response) { | ||
if (response == null || response.body() == null || response.body().results == null) { | ||
return; | ||
} | ||
videosLiveData.postValue(response.body().results); | ||
} | ||
|
||
void onFailure(Throwable e); | ||
@Override | ||
public void onFailure(Call<VideosResponse> call, Throwable e) { | ||
Log.e("Movies", "while loading videos", e); | ||
} | ||
}); | ||
return videosLiveData; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
51 changes: 51 additions & 0 deletions
51
MoviesExample/app/src/main/java/com/novoda/demo/movies/MoviesViewModel.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package com.novoda.demo.movies; | ||
|
||
import android.arch.core.util.Function; | ||
import android.arch.lifecycle.LiveData; | ||
import android.arch.lifecycle.Transformations; | ||
import android.arch.lifecycle.ViewModel; | ||
|
||
import com.novoda.demo.movies.model.Movie; | ||
import com.novoda.demo.movies.model.Video; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
public class MoviesViewModel extends ViewModel { | ||
|
||
private final MovieService movieService; | ||
private MoviesSate moviesSate = new MoviesSate(new ArrayList<Movie>(), 1); | ||
|
||
MoviesViewModel(MovieService movieService) { | ||
this.movieService = movieService; | ||
} | ||
|
||
public LiveData<MoviesSate> moviesLiveData() { | ||
return Transformations.map(movieService.loadMore(moviesSate.pageNumber()), | ||
new Function<List<Movie>, MoviesSate>() { | ||
@Override | ||
public MoviesSate apply(List<Movie> input) { | ||
List<Movie> movies = moviesSate.movies(); | ||
movies.addAll(input); | ||
moviesSate = new MoviesSate(movies, moviesSate.pageNumber() + 1); | ||
return moviesSate; | ||
} | ||
}); | ||
} | ||
|
||
public void loadMore() { | ||
movieService.loadMore(moviesSate.pageNumber()); | ||
} | ||
|
||
public LiveData<Video> loadTrailerFor(Movie movie) { | ||
return Transformations.map(movieService.loadTrailerFor(movie), new Function<List<Video>, Video>() { | ||
@Override | ||
public Video apply(List<Video> input) { | ||
if (input.size() > 0) { | ||
return input.get(0); | ||
} | ||
return null; | ||
} | ||
}); | ||
} | ||
} |
23 changes: 23 additions & 0 deletions
23
MoviesExample/app/src/main/java/com/novoda/demo/movies/MoviesViewModelFactory.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package com.novoda.demo.movies; | ||
|
||
import android.arch.lifecycle.ViewModel; | ||
import android.arch.lifecycle.ViewModelProvider; | ||
import android.support.annotation.NonNull; | ||
|
||
public class MoviesViewModelFactory implements ViewModelProvider.Factory { | ||
|
||
private MovieService movieService; | ||
|
||
MoviesViewModelFactory(MovieService movieService) { | ||
this.movieService = movieService; | ||
} | ||
|
||
@NonNull | ||
@Override | ||
public <T extends ViewModel> T create(@NonNull Class<T> modelClass) { | ||
if (modelClass.isAssignableFrom(MoviesViewModel.class)) { | ||
return (T) new MoviesViewModel(movieService); | ||
} | ||
throw new IllegalArgumentException("Unknown ViewModel class"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters