· 4 years ago · Aug 23, 2021, 04:00 PM
1public class FeedDataSource extends PageKeyedDataSource<Long, Article> {
2
3 private static final String TAG = FeedDataSource.class.getSimpleName();
4
5 /*
6 * Step 1: Initialize the restApiFactory.
7 * The networkState and initialLoading variables
8 * are for updating the UI when data is being fetched
9 * by displaying a progress bar
10 */
11 private RestApiFactory restApiFactory;
12
13 private MutableLiveData networkState;
14 private MutableLiveData initialLoading;
15
16 public FeedDataSource() {
17 this.restApiFactory = RestApiFactory.create();
18
19 networkState = new MutableLiveData();
20 initialLoading = new MutableLiveData();
21 }
22
23
24 public MutableLiveData getNetworkState() {
25 return networkState;
26 }
27
28 public MutableLiveData getInitialLoading() {
29 return initialLoading;
30 }
31
32
33 /*
34 * Step 2: This method is responsible to load the data initially
35 * when app screen is launched for the first time.
36 * We are fetching the first page data from the api
37 * and passing it via the callback method to the UI.
38 */
39 @Override
40 public void loadInitial(@NonNull LoadInitialParams<Long> params,
41 @NonNull LoadInitialCallback<Long, Article> callback) {
42
43 initialLoading.postValue(NetworkState.LOADING);
44 networkState.postValue(NetworkState.LOADING);
45
46 appController.getRestApi().fetchFeed(QUERY, API_KEY, 1, params.requestedLoadSize)
47 .enqueue(new Callback<Feed>() {
48 @Override
49 public void onResponse(Call<Feed> call, Response<Feed> response) {
50 if(response.isSuccessful()) {
51 callback.onResult(response.body().getArticles(), null, 2l);
52 initialLoading.postValue(NetworkState.LOADED);
53 networkState.postValue(NetworkState.LOADED);
54
55 } else {
56 initialLoading.postValue(new NetworkState(NetworkState.Status.FAILED, response.message()));
57 networkState.postValue(new NetworkState(NetworkState.Status.FAILED, response.message()));
58 }
59 }
60
61 @Override
62 public void onFailure(Call<Feed> call, Throwable t) {
63 String errorMessage = t == null ? "unknown error" : t.getMessage();
64 networkState.postValue(new NetworkState(NetworkState.Status.FAILED, errorMessage));
65 }
66 });
67 }
68
69
70
71 @Override
72 public void loadBefore(@NonNull LoadParams<Long> params,
73 @NonNull LoadCallback<Long, Article> callback) {
74
75 }
76
77
78 /*
79 * Step 3: This method it is responsible for the subsequent call to load the data page wise.
80 * This method is executed in the background thread
81 * We are fetching the next page data from the api
82 * and passing it via the callback method to the UI.
83 * The "params.key" variable will have the updated value.
84 */
85 @Override
86 public void loadAfter(@NonNull LoadParams<Long> params,
87 @NonNull LoadCallback<Long, Article> callback) {
88
89 Log.i(TAG, "Loading Rang " + params.key + " Count " + params.requestedLoadSize);
90
91 networkState.postValue(NetworkState.LOADING);
92
93 appController.getRestApi().fetchFeed(QUERY, API_KEY, params.key, params.requestedLoadSize).enqueue(new Callback<Feed>() {
94 @Override
95 public void onResponse(Call<Feed> call, Response<Feed> response) {
96 /*
97 * If the request is successful, then we will update the callback
98 * with the latest feed items and
99 * "params.key+1" -> set the next key for the next iteration.
100 */
101 if(response.isSuccessful()) {
102 long nextKey = (params.key == response.body().getTotalResults()) ? null : params.key+1;
103 callback.onResult(response.body().getArticles(), nextKey);
104 networkState.postValue(NetworkState.LOADED);
105
106 } else networkState.postValue(new NetworkState(NetworkState.Status.FAILED, response.message()));
107 }
108
109 @Override
110 public void onFailure(Call<Feed> call, Throwable t) {
111 String errorMessage = t == null ? "unknown error" : t.getMessage();
112 networkState.postValue(new NetworkState(NetworkState.Status.FAILED, errorMessage));
113 }
114 });
115 }
116}