Use Android Paging Library to load and display best posts. Loading best posts in a specific subreddit is broken. Fixed a bug which is PostViewModel's data becoming null after the app restart. Add notch support for Android Pie.

This commit is contained in:
Alex Ning 2018-12-27 11:29:02 +08:00
parent 60b659e651
commit 45f67457fa
13 changed files with 389 additions and 520 deletions

Binary file not shown.

2
.idea/misc.xml generated
View File

@ -25,7 +25,7 @@
</value>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">

View File

@ -16,6 +16,10 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility = '1.8'
targetCompatibility = '1.8'
}
}
repositories {
@ -66,4 +70,5 @@ dependencies {
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
implementation 'com.github.santalu:aspect-ratio-imageview:1.0.6'
implementation 'com.felipecsl:gifimageview:2.2.0'
implementation "android.arch.paging:runtime:1.0.1"
}

View File

@ -0,0 +1,34 @@
package ml.docilealligator.infinityforreddit;
class NetworkState {
public enum Status{
RUNNING,
SUCCESS,
FAILED
}
private final Status status;
private final String msg;
static final NetworkState LOADED;
static final NetworkState LOADING;
NetworkState(Status status, String msg) {
this.status = status;
this.msg = msg;
}
static {
LOADED=new NetworkState(Status.SUCCESS,"Success");
LOADING=new NetworkState(Status.RUNNING,"Running");
}
public Status getStatus() {
return status;
}
public String getMsg() {
return msg;
}
}

View File

@ -0,0 +1,124 @@
package ml.docilealligator.infinityforreddit;
import android.arch.lifecycle.MutableLiveData;
import android.arch.paging.PageKeyedDataSource;
import android.support.annotation.NonNull;
import android.util.Log;
import java.util.ArrayList;
import java.util.Locale;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Retrofit;
class PostDataSource extends PageKeyedDataSource<String, Post> {
private Retrofit retrofit;
private String accessToken;
private Locale locale;
private boolean isBestPost;
//private MutableLiveData networkState;
private MutableLiveData initialLoading;
PostDataSource(Retrofit retrofit, String accessToken, Locale locale, boolean isBestPost) {
this.retrofit = retrofit;
this.accessToken = accessToken;
this.locale = locale;
this.isBestPost = isBestPost;
//networkState = new MutableLiveData();
initialLoading = new MutableLiveData();
}
/*public MutableLiveData getNetworkState() {
return networkState;
}*/
public MutableLiveData getInitialLoading() {
return initialLoading;
}
@Override
public void loadInitial(@NonNull LoadInitialParams<String> params, @NonNull final LoadInitialCallback<String, Post> callback) {
initialLoading.postValue(NetworkState.LOADING);
//networkState.postValue(NetworkState.LOADING);
RedditAPI api = retrofit.create(RedditAPI.class);
Call<String> bestPost = api.getBestPost(null, RedditUtils.getOAuthHeader(accessToken));
bestPost.enqueue(new Callback<String>() {
@Override
public void onResponse(Call<String> call, retrofit2.Response<String> response) {
if (response.isSuccessful()) {
ParsePost.parsePost(response.body(), locale,
new ParsePost.ParsePostListener() {
@Override
public void onParsePostSuccess(ArrayList<Post> newPosts, String lastItem) {
callback.onResult(newPosts, null, lastItem);
initialLoading.postValue(NetworkState.LOADED);
//networkState.postValue(NetworkState.LOADED);
}
@Override
public void onParsePostFail() {
Log.i("Post fetch error", "Error parsing data");
}
});
} else {
Log.i("Post fetch error", response.message());
initialLoading.postValue(new NetworkState(NetworkState.Status.FAILED, response.message()));
//networkState.postValue(new NetworkState(NetworkState.Status.FAILED, response.message()));
}
}
@Override
public void onFailure(Call<String> call, Throwable t) {
String errorMessage = t == null ? "unknown error" : t.getMessage();
//networkState.postValue(new NetworkState(NetworkState.Status.FAILED, errorMessage));
}
});
}
@Override
public void loadBefore(@NonNull LoadParams<String> params, @NonNull LoadCallback<String, Post> callback) {
}
@Override
public void loadAfter(@NonNull LoadParams<String> params, @NonNull final LoadCallback<String, Post> callback) {
//networkState.postValue(NetworkState.LOADING);
RedditAPI api = retrofit.create(RedditAPI.class);
Call<String> bestPost = api.getBestPost(params.key, RedditUtils.getOAuthHeader(accessToken));
bestPost.enqueue(new Callback<String>() {
@Override
public void onResponse(Call<String> call, retrofit2.Response<String> response) {
if(response.isSuccessful()) {
ParsePost.parsePost(response.body(), locale, new ParsePost.ParsePostListener() {
@Override
public void onParsePostSuccess(ArrayList<Post> newPosts, String lastItem) {
callback.onResult(newPosts, lastItem);
//networkState.postValue(NetworkState.LOADED);
}
@Override
public void onParsePostFail() {
Log.i("Best post", "Error parsing data");
}
});
} else {
Log.i("best post", response.message());
//networkState.postValue(new NetworkState(NetworkState.Status.FAILED, response.message()));
}
}
@Override
public void onFailure(Call<String> call, Throwable t) {
String errorMessage = t == null ? "unknown error" : t.getMessage();
//networkState.postValue(new NetworkState(NetworkState.Status.FAILED, errorMessage));
}
});
}
}

View File

@ -0,0 +1,37 @@
package ml.docilealligator.infinityforreddit;
import android.arch.lifecycle.MutableLiveData;
import android.arch.paging.DataSource;
import android.arch.paging.PageKeyedDataSource;
import java.util.Locale;
import retrofit2.Retrofit;
class PostDataSourceFactory extends DataSource.Factory {
private Retrofit retrofit;
private String accessToken;
private Locale locale;
private boolean isBestPost;
private MutableLiveData<PageKeyedDataSource<String, Post>> mutableLiveData;
PostDataSourceFactory(Retrofit retrofit, String accessToken, Locale locale, boolean isBestPost) {
this.retrofit = retrofit;
this.accessToken = accessToken;
this.locale = locale;
this.isBestPost = isBestPost;
mutableLiveData = new MutableLiveData<>();
}
@Override
public DataSource create() {
PostDataSource postDataSource = new PostDataSource(retrofit, accessToken, locale, isBestPost);
mutableLiveData.postValue(postDataSource);
return postDataSource;
}
public MutableLiveData<PageKeyedDataSource<String, Post>> getMutableLiveData() {
return mutableLiveData;
}
}

View File

@ -1,19 +1,15 @@
package ml.docilealligator.infinityforreddit;
import android.arch.lifecycle.Observer;
import android.arch.lifecycle.ViewModelProviders;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.Snackbar;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -21,15 +17,9 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import com.bumptech.glide.Glide;
import java.util.ArrayList;
import javax.inject.Inject;
import javax.inject.Named;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Retrofit;
@ -53,9 +43,6 @@ public class PostFragment extends Fragment implements FragmentCommunicator {
private LinearLayout mFetchPostErrorLinearLayout;
private ImageView mFetchPostErrorImageView;
private String mLastItem;
private PaginationSynchronizer mPaginationSynchronizer;
private boolean mIsBestPost;
private String mSubredditName;
@ -76,14 +63,6 @@ public class PostFragment extends Fragment implements FragmentCommunicator {
// Required empty public constructor
}
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(LAST_ITEM_STATE, mLastItem);
outState.putBoolean(LOADING_STATE_STATE, mPaginationSynchronizer.isLoading());
outState.putBoolean(LOAD_SUCCESS_STATE, mPaginationSynchronizer.isLoadingMorePostsSuccess());
}
@Override
public void onResume() {
super.onResume();
@ -117,10 +96,11 @@ public class PostFragment extends Fragment implements FragmentCommunicator {
});*/
mIsBestPost = getArguments().getBoolean(IS_BEST_POST_KEY);
if(!mIsBestPost) {
mSubredditName = getArguments().getString(SUBREDDIT_NAME_KEY);
} else {
mFetchPostErrorLinearLayout.setOnClickListener(new View.OnClickListener() {
/*mFetchPostErrorLinearLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(mIsBestPost) {
@ -129,159 +109,35 @@ public class PostFragment extends Fragment implements FragmentCommunicator {
fetchPost();
}
}
});
});*/
}
mPaginationSynchronizer = new PaginationSynchronizer();
mPaginationSynchronizer.addLastItemSynchronizer(new LastItemSynchronizer() {
@Override
public void lastItemChanged(String lastItem) {
mLastItem = lastItem;
}
});
mPostViewModel = ViewModelProviders.of(this).get(PostViewModel.class);
mPostViewModel.getPosts().observe(this, new Observer<ArrayList<Post>>() {
@Override
public void onChanged(@Nullable ArrayList<Post> posts) {
if(posts == null) {
Log.i("datachange", Integer.toString(0));
} else {
Log.i("datachange", Integer.toString(posts.size()));
mAdapter.changeDataSet(posts);
}
}
});
if(mIsBestPost) {
mAdapter = new PostRecyclerViewAdapter(getActivity(), mOauthRetrofit,
mSharedPreferences, mPaginationSynchronizer, mIsBestPost);
mPostRecyclerView.addOnScrollListener(new PostPaginationScrollListener(
getActivity(), mOauthRetrofit, mPostViewModel, mLinearLayoutManager,
mLastItem, mPaginationSynchronizer, mSubredditName, mIsBestPost,
mPaginationSynchronizer.isLoading(), mPaginationSynchronizer.isLoadingMorePostsSuccess(),
getResources().getConfiguration().locale));
mSharedPreferences, mIsBestPost);
} else {
mAdapter = new PostRecyclerViewAdapter(getActivity(), mRetrofit,
mSharedPreferences, mPaginationSynchronizer, mIsBestPost);
mPostRecyclerView.addOnScrollListener(new PostPaginationScrollListener(
getActivity(), mRetrofit, mPostViewModel, mLinearLayoutManager,
mLastItem, mPaginationSynchronizer, mSubredditName, mIsBestPost,
mPaginationSynchronizer.isLoading(), mPaginationSynchronizer.isLoadingMorePostsSuccess(),
getResources().getConfiguration().locale));
mSharedPreferences, mIsBestPost);
}
mPostRecyclerView.setAdapter(mAdapter);
if(savedInstanceState != null && savedInstanceState.containsKey(LAST_ITEM_STATE)) {
mLastItem = savedInstanceState.getString(LAST_ITEM_STATE);
String accessToken = getActivity().getSharedPreferences(SharedPreferencesUtils.AUTH_CODE_FILE_KEY, Context.MODE_PRIVATE)
.getString(SharedPreferencesUtils.ACCESS_TOKEN_KEY, "");
mPaginationSynchronizer.notifyLastItemChanged(mLastItem);
mPaginationSynchronizer.setLoadSuccess(savedInstanceState.getBoolean(LOAD_SUCCESS_STATE));
mPaginationSynchronizer.setLoadingState(savedInstanceState.getBoolean(LOADING_STATE_STATE));
mProgressBar.setVisibility(View.GONE);
} else {
if(mIsBestPost) {
fetchBestPost();
} else {
fetchPost();
}
}
PostViewModel.Factory factory = new PostViewModel.Factory(mOauthRetrofit, accessToken,
getResources().getConfiguration().locale, mIsBestPost);
mPostViewModel = ViewModelProviders.of(this, factory).get(PostViewModel.class);
mPostViewModel.getPosts().observe(this, posts -> mAdapter.submitList(posts));
return rootView;
}
private void fetchBestPost() {
mFetchPostErrorLinearLayout.setVisibility(View.GONE);
mProgressBar.setVisibility(View.VISIBLE);
@Override
public void refresh() {
RedditAPI api = mOauthRetrofit.create(RedditAPI.class);
String accessToken = getActivity().getSharedPreferences(SharedPreferencesUtils.AUTH_CODE_FILE_KEY, Context.MODE_PRIVATE)
.getString(SharedPreferencesUtils.ACCESS_TOKEN_KEY, "");
Call<String> bestPost = api.getBestPost(mLastItem, RedditUtils.getOAuthHeader(accessToken));
bestPost.enqueue(new Callback<String>() {
@Override
public void onResponse(Call<String> call, retrofit2.Response<String> response) {
if(getActivity() != null) {
if(response.isSuccessful()) {
ParsePost.parsePost(response.body(), getResources().getConfiguration().locale,
new ParsePost.ParsePostListener() {
@Override
public void onParsePostSuccess(ArrayList<Post> newPosts, String lastItem) {
if(isAdded() && getActivity() != null) {
mLastItem = lastItem;
mPaginationSynchronizer.notifyLastItemChanged(lastItem);
mPostViewModel.setPosts(newPosts);
mProgressBar.setVisibility(View.GONE);
}
}
@Override
public void onParsePostFail() {
Log.i("Post fetch error", "Error parsing data");
showErrorView();
}
});
} else {
Log.i("Post fetch error", response.message());
showErrorView();
}
}
}
@Override
public void onFailure(Call<String> call, Throwable t) {
showErrorView();
}
});
}
private void fetchPost() {
mFetchPostErrorLinearLayout.setVisibility(View.GONE);
mProgressBar.setVisibility(View.VISIBLE);
RedditAPI api = mRetrofit.create(RedditAPI.class);
Call<String> getPost = api.getPost(mSubredditName, mLastItem);
getPost.enqueue(new Callback<String>() {
@Override
public void onResponse(Call<String> call, retrofit2.Response<String> response) {
if(getActivity() != null) {
if(response.isSuccessful()) {
ParsePost.parsePost(response.body(), getResources().getConfiguration().locale,
new ParsePost.ParsePostListener() {
@Override
public void onParsePostSuccess(ArrayList<Post> newPosts, String lastItem) {
if(isAdded() && getActivity() != null) {
mLastItem = lastItem;
mPaginationSynchronizer.notifyLastItemChanged(lastItem);
mPostViewModel.setPosts(newPosts);
mProgressBar.setVisibility(View.GONE);
}
}
@Override
public void onParsePostFail() {
Log.i("Post fetch error", "Error parsing data");
showErrorView();
}
});
} else {
Log.i("Post fetch error", response.message());
showErrorView();
}
}
}
@Override
public void onFailure(Call<String> call, Throwable t) {
showErrorView();
}
});
}
/*
private void showErrorView() {
mProgressBar.setVisibility(View.GONE);
if(mIsBestPost) {
@ -303,32 +159,5 @@ public class PostFragment extends Fragment implements FragmentCommunicator {
});
snackbar.show();
}
}
@Override
public void refresh() {
mLastItem = null;
mPostRecyclerView.clearOnScrollListeners();
mPostRecyclerView.getRecycledViewPool().clear();
mPostViewModel.setPosts(null);
if(mIsBestPost) {
mPostRecyclerView.addOnScrollListener(new PostPaginationScrollListener(
getActivity(), mOauthRetrofit, mPostViewModel, mLinearLayoutManager,
mLastItem, mPaginationSynchronizer, mSubredditName, mIsBestPost,
mPaginationSynchronizer.isLoading(), mPaginationSynchronizer.isLoadingMorePostsSuccess(),
getResources().getConfiguration().locale));
fetchBestPost();
} else {
mPostRecyclerView.addOnScrollListener(new PostPaginationScrollListener(
getActivity(), mRetrofit, mPostViewModel, mLinearLayoutManager,
mLastItem, mPaginationSynchronizer, mSubredditName, mIsBestPost,
mPaginationSynchronizer.isLoading(), mPaginationSynchronizer.isLoadingMorePostsSuccess(),
getResources().getConfiguration().locale));
fetchPost();
}
}
}*/
}

View File

@ -1,197 +0,0 @@
package ml.docilealligator.infinityforreddit;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.Locale;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Retrofit;
/**
* Created by alex on 3/12/18.
*/
class PostPaginationScrollListener extends RecyclerView.OnScrollListener {
private Context mContext;
private Retrofit mRetrofit;
private PostViewModel mPostViewModel;
private LinearLayoutManager mLayoutManager;
private PaginationSynchronizer mPaginationSynchronizer;
private String mSubredditName;
private boolean isBestPost;
private boolean isLoading;
private boolean loadSuccess;
private Locale locale;
private String mLastItem;
PostPaginationScrollListener(Context context, Retrofit retrofit, PostViewModel postViewModel,
LinearLayoutManager layoutManager, String lastItem,
PaginationSynchronizer paginationSynchronizer, final String subredditName,
final boolean isBestPost, boolean isLoading, boolean loadSuccess, Locale locale) {
if(context != null) {
mContext = context;
mRetrofit = retrofit;
mPostViewModel = postViewModel;
mLayoutManager = layoutManager;
mLastItem = lastItem;
mPaginationSynchronizer = paginationSynchronizer;
mSubredditName = subredditName;
this.isBestPost = isBestPost;
this.isLoading = isLoading;
this.loadSuccess = loadSuccess;
this.locale = locale;
PaginationRetryNotifier paginationRetryNotifier = new PaginationRetryNotifier() {
@Override
public void retry() {
if (isBestPost) {
fetchBestPost();
} else {
fetchPost(subredditName);
}
}
};
mPaginationSynchronizer.setPaginationRetryNotifier(paginationRetryNotifier);
mPaginationSynchronizer.addLastItemSynchronizer(new LastItemSynchronizer() {
@Override
public void lastItemChanged(String lastItem) {
mLastItem = lastItem;
}
});
}
}
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if(!isLoading && loadSuccess) {
int visibleItemCount = mLayoutManager.getChildCount();
int totalItemCount = mLayoutManager.getItemCount();
int firstVisibleItemPosition = mLayoutManager.findFirstVisibleItemPosition();
if((visibleItemCount + firstVisibleItemPosition >= totalItemCount) && firstVisibleItemPosition >= 0) {
if(isBestPost) {
fetchBestPost();
} else {
fetchPost(mSubredditName);
}
}
}
}
private void fetchBestPost() {
isLoading = true;
loadSuccess = false;
mPaginationSynchronizer.setLoadingState(true);
RedditAPI api = mRetrofit.create(RedditAPI.class);
String accessToken = mContext.getSharedPreferences(SharedPreferencesUtils.AUTH_CODE_FILE_KEY, Context.MODE_PRIVATE)
.getString(SharedPreferencesUtils.ACCESS_TOKEN_KEY, "");
Call<String> bestPost = api.getBestPost(mLastItem, RedditUtils.getOAuthHeader(accessToken));
bestPost.enqueue(new Callback<String>() {
@Override
public void onResponse(Call<String> call, retrofit2.Response<String> response) {
if(response.isSuccessful()) {
ParsePost.parsePost(response.body(), locale, new ParsePost.ParsePostListener() {
@Override
public void onParsePostSuccess(ArrayList<Post> newPosts, String lastItem) {
if(mPostViewModel != null) {
mPostViewModel.addPosts(newPosts);
mLastItem = lastItem;
mPaginationSynchronizer.notifyLastItemChanged(lastItem);
isLoading = false;
loadSuccess = true;
mPaginationSynchronizer.setLoadingState(false);
mPaginationSynchronizer.loadSuccess(true);
}
}
@Override
public void onParsePostFail() {
Toast.makeText(mContext, "Error parsing data", Toast.LENGTH_SHORT).show();
Log.i("Best post", "Error parsing data");
loadFailed();
}
});
} else {
Toast.makeText(mContext, "Error getting best post", Toast.LENGTH_SHORT).show();
Log.i("best post", response.message());
loadFailed();
}
}
@Override
public void onFailure(Call<String> call, Throwable t) {
loadFailed();
}
});
}
private void fetchPost(final String subredditName) {
isLoading = true;
loadSuccess = false;
mPaginationSynchronizer.setLoadingState(true);
RedditAPI api = mRetrofit.create(RedditAPI.class);
Call<String> getPost = api.getPost(subredditName, mLastItem);
getPost.enqueue(new Callback<String>() {
@Override
public void onResponse(Call<String> call, retrofit2.Response<String> response) {
if(response.isSuccessful()) {
ParsePost.parsePost(response.body(), locale, new ParsePost.ParsePostListener() {
@Override
public void onParsePostSuccess(ArrayList<Post> newPosts, String lastItem) {
if(mPostViewModel != null) {
mPostViewModel.addPosts(newPosts);
mLastItem = lastItem;
mPaginationSynchronizer.notifyLastItemChanged(lastItem);
isLoading = false;
loadSuccess = true;
mPaginationSynchronizer.setLoadingState(false);
mPaginationSynchronizer.loadSuccess(true);
}
}
@Override
public void onParsePostFail() {
Toast.makeText(mContext, "Error parsing data", Toast.LENGTH_SHORT).show();
Log.i("Best post", "Error parsing data");
loadFailed();
}
});
} else {
Toast.makeText(mContext, "Error getting best post", Toast.LENGTH_SHORT).show();
Log.i("best post", response.message());
loadFailed();
}
}
@Override
public void onFailure(Call<String> call, Throwable t) {
Toast.makeText(mContext, "Error getting best post", Toast.LENGTH_SHORT).show();
loadFailed();
}
});
}
private void loadFailed() {
isLoading = false;
loadSuccess = false;
mPaginationSynchronizer.setLoadingState(false);
mPaginationSynchronizer.loadSuccess(false);
}
}

View File

@ -1,5 +1,6 @@
package ml.docilealligator.infinityforreddit;
import android.arch.paging.PagedListAdapter;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
@ -11,6 +12,7 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.customtabs.CustomTabsIntent;
import android.support.v4.content.ContextCompat;
import android.support.v7.util.DiffUtil;
import android.support.v7.widget.CardView;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
@ -34,7 +36,7 @@ import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.Target;
import java.util.ArrayList;
import java.util.List;
import CustomView.AspectRatioGifImageView;
import butterknife.BindView;
@ -47,12 +49,10 @@ import retrofit2.Retrofit;
* Created by alex on 2/25/18.
*/
class PostRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private ArrayList<Post> mPostData;
class PostRecyclerViewAdapter extends PagedListAdapter<Post, RecyclerView.ViewHolder> {
private Context mContext;
private Retrofit mOauthRetrofit;
private SharedPreferences mSharedPreferences;
private PaginationSynchronizer mPaginationSynchronizer;
private RequestManager glide;
private SubredditDao subredditDao;
private boolean isLoadingMorePostSuccess = true;
@ -62,21 +62,32 @@ class PostRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
private static final int VIEW_TYPE_DATA = 0;
private static final int VIEW_TYPE_LOADING = 1;
private int dataSize;
private NetworkState networkState;
PostRecyclerViewAdapter(Context context, Retrofit oauthRetrofit, SharedPreferences sharedPreferences, PaginationSynchronizer paginationSynchronizer, boolean hasMultipleSubreddits) {
PostRecyclerViewAdapter(Context context, Retrofit oauthRetrofit, SharedPreferences sharedPreferences, boolean hasMultipleSubreddits) {
super(DIFF_CALLBACK);
if(context != null) {
mContext = context;
mOauthRetrofit = oauthRetrofit;
mSharedPreferences = sharedPreferences;
mPostData = new ArrayList<>();
mPaginationSynchronizer = paginationSynchronizer;
this.hasMultipleSubreddits = hasMultipleSubreddits;
glide = Glide.with(mContext.getApplicationContext());
subredditDao = SubredditRoomDatabase.getDatabase(mContext.getApplicationContext()).subredditDao();
}
}
static final DiffUtil.ItemCallback<Post> DIFF_CALLBACK = new DiffUtil.ItemCallback<Post>() {
@Override
public boolean areItemsTheSame(@NonNull Post post, @NonNull Post t1) {
return post.getId().equals(t1.getId());
}
@Override
public boolean areContentsTheSame(@NonNull Post post, @NonNull Post t1) {
return post.getTitle().equals(t1.getTitle());
}
};
void setCanStartActivity(boolean canStartActivity) {
this.canStartActivity = canStartActivity;
}
@ -93,27 +104,33 @@ class PostRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
}
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position, @NonNull List<Object> payloads) {
onBindViewHolder(holder, position);
}
@Override
public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder holder, int position) {
if(holder instanceof DataViewHolder) {
if(mPostData.get(holder.getAdapterPosition()) == null) {
Post post = getItem(position);
if(post == null) {
Log.i("is null", Integer.toString(holder.getAdapterPosition()));
} else {
final String id = mPostData.get(holder.getAdapterPosition()).getFullName();
final String subredditName = mPostData.get(holder.getAdapterPosition()).getSubredditNamePrefixed();
final String postTime = mPostData.get(holder.getAdapterPosition()).getPostTime();
final String title = mPostData.get(holder.getAdapterPosition()).getTitle();
final String permalink = mPostData.get(holder.getAdapterPosition()).getPermalink();
int voteType = mPostData.get(holder.getAdapterPosition()).getVoteType();
int gilded = mPostData.get(holder.getAdapterPosition()).getGilded();
boolean nsfw = mPostData.get(holder.getAdapterPosition()).isNSFW();
final String id = post.getFullName();
final String subredditName = post.getSubredditNamePrefixed();
final String postTime = post.getPostTime();
final String title = post.getTitle();
final String permalink = post.getPermalink();
int voteType = post.getVoteType();
int gilded = post.getGilded();
boolean nsfw = post.isNSFW();
if(mPostData.get(holder.getAdapterPosition()).getSubredditIconUrl() == null) {
if(post.getSubredditIconUrl() == null) {
new LoadSubredditIconAsyncTask(subredditDao, subredditName,
new LoadSubredditIconAsyncTask.LoadSubredditIconAsyncTaskListener() {
@Override
public void loadIconSuccess(String iconImageUrl) {
if(mContext != null && !mPostData.isEmpty()) {
if(mContext != null && getItemCount() > 0) {
if(!iconImageUrl.equals("")) {
glide.load(iconImageUrl)
.apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))
@ -142,13 +159,13 @@ class PostRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
}
if(holder.getAdapterPosition() >= 0) {
mPostData.get(holder.getAdapterPosition()).setSubredditIconUrl(iconImageUrl);
post.setSubredditIconUrl(iconImageUrl);
}
}
}
}).execute();
} else if(!mPostData.get(position).getSubredditIconUrl().equals("")) {
glide.load(mPostData.get(position).getSubredditIconUrl())
} else if(!post.getSubredditIconUrl().equals("")) {
glide.load(post.getSubredditIconUrl())
.apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))
.error(glide.load(R.drawable.subreddit_default_icon))
.listener(new RequestListener<Drawable>() {
@ -181,7 +198,7 @@ class PostRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
canStartActivity = false;
Intent intent = new Intent(mContext, ViewPostDetailActivity.class);
intent.putExtra(ViewPostDetailActivity.EXTRA_TITLE, title);
intent.putExtra(ViewPostDetailActivity.EXTRA_POST_DATA, mPostData.get(holder.getAdapterPosition()));
intent.putExtra(ViewPostDetailActivity.EXTRA_POST_DATA, post);
mContext.startActivity(intent);
}
}
@ -194,9 +211,9 @@ class PostRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
canStartActivity = false;
Intent intent = new Intent(mContext, ViewSubredditDetailActivity.class);
intent.putExtra(ViewSubredditDetailActivity.EXTRA_SUBREDDIT_NAME_KEY,
mPostData.get(holder.getAdapterPosition()).getSubredditNamePrefixed().substring(2));
post.getSubredditNamePrefixed().substring(2));
intent.putExtra(ViewSubredditDetailActivity.EXTRA_SUBREDDIT_VALUE_KEY,
mPostData.get(holder.getAdapterPosition()).getSubredditNamePrefixed());
post.getSubredditNamePrefixed());
intent.putExtra(ViewSubredditDetailActivity.EXTRA_QUERY_BY_ID_KEY, false);
mContext.startActivity(intent);
}
@ -212,9 +229,9 @@ class PostRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
canStartActivity = false;
Intent intent = new Intent(mContext, ViewSubredditDetailActivity.class);
intent.putExtra(ViewSubredditDetailActivity.EXTRA_SUBREDDIT_NAME_KEY,
mPostData.get(holder.getAdapterPosition()).getSubredditNamePrefixed().substring(2));
post.getSubredditNamePrefixed().substring(2));
intent.putExtra(ViewSubredditDetailActivity.EXTRA_SUBREDDIT_VALUE_KEY,
mPostData.get(holder.getAdapterPosition()).getSubredditNamePrefixed());
post.getSubredditNamePrefixed());
intent.putExtra(ViewSubredditDetailActivity.EXTRA_QUERY_BY_ID_KEY, false);
mContext.startActivity(intent);
}
@ -222,7 +239,7 @@ class PostRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
});
((DataViewHolder) holder).postTimeTextView.setText(postTime);
((DataViewHolder) holder).titleTextView.setText(title);
((DataViewHolder) holder).scoreTextView.setText(Integer.toString(mPostData.get(position).getScore()));
((DataViewHolder) holder).scoreTextView.setText(Integer.toString(post.getScore()));
if(gilded > 0) {
((DataViewHolder) holder).gildedImageView.setVisibility(View.VISIBLE);
@ -247,29 +264,29 @@ class PostRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
break;
}
if(mPostData.get(position).getPostType() != Post.TEXT_TYPE && mPostData.get(position).getPostType() != Post.NO_PREVIEW_LINK_TYPE) {
if(post.getPostType() != Post.TEXT_TYPE && post.getPostType() != Post.NO_PREVIEW_LINK_TYPE) {
((DataViewHolder) holder).relativeLayout.setVisibility(View.VISIBLE);
((DataViewHolder) holder).progressBar.setVisibility(View.VISIBLE);
((DataViewHolder) holder).imageView.setVisibility(View.VISIBLE);
((DataViewHolder) holder).imageView
.setRatio((float) mPostData.get(position).getPreviewHeight() / mPostData.get(position).getPreviewWidth());
loadImage(holder, mPostData.get(holder.getAdapterPosition()));
.setRatio((float) post.getPreviewHeight() / post.getPreviewWidth());
loadImage(holder, post);
}
if(!hasMultipleSubreddits && mPostData.get(position).isStickied()) {
if(!hasMultipleSubreddits && post.isStickied()) {
((DataViewHolder) holder).stickiedPostImageView.setVisibility(View.VISIBLE);
glide.load(R.drawable.thumbtack).into(((DataViewHolder) holder).stickiedPostImageView);
}
if(mPostData.get(holder.getAdapterPosition()).isCrosspost()) {
if(post.isCrosspost()) {
((DataViewHolder) holder).crosspostImageView.setVisibility(View.VISIBLE);
}
switch (mPostData.get(position).getPostType()) {
switch (post.getPostType()) {
case Post.IMAGE_TYPE:
((DataViewHolder) holder).typeTextView.setText("IMAGE");
final String imageUrl = mPostData.get(position).getUrl();
final String imageUrl = post.getUrl();
((DataViewHolder) holder).imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
@ -293,24 +310,24 @@ class PostRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
builder.addDefaultShareMenuItem();
builder.setToolbarColor(mContext.getResources().getColor(R.color.colorPrimary));
CustomTabsIntent customTabsIntent = builder.build();
customTabsIntent.launchUrl(mContext, Uri.parse(mPostData.get(holder.getAdapterPosition()).getUrl()));
customTabsIntent.launchUrl(mContext, Uri.parse(post.getUrl()));
}
});
break;
case Post.GIF_VIDEO_TYPE:
((DataViewHolder) holder).typeTextView.setText("GIF");
final Uri gifVideoUri = Uri.parse(mPostData.get(position).getVideoUrl());
final Uri gifVideoUri = Uri.parse(post.getVideoUrl());
((DataViewHolder) holder).imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(mContext, ViewVideoActivity.class);
intent.setData(gifVideoUri);
intent.putExtra(ViewVideoActivity.TITLE_KEY, title);
intent.putExtra(ViewVideoActivity.IS_DASH_VIDEO_KEY, mPostData.get(holder.getAdapterPosition()).isDashVideo());
intent.putExtra(ViewVideoActivity.IS_DOWNLOADABLE_KEY, mPostData.get(holder.getAdapterPosition()).isDownloadableGifOrVideo());
if(mPostData.get(holder.getAdapterPosition()).isDownloadableGifOrVideo()) {
intent.putExtra(ViewVideoActivity.DOWNLOAD_URL_KEY, mPostData.get(holder.getAdapterPosition()).getGifOrVideoDownloadUrl());
intent.putExtra(ViewVideoActivity.IS_DASH_VIDEO_KEY, post.isDashVideo());
intent.putExtra(ViewVideoActivity.IS_DOWNLOADABLE_KEY, post.isDownloadableGifOrVideo());
if(post.isDownloadableGifOrVideo()) {
intent.putExtra(ViewVideoActivity.DOWNLOAD_URL_KEY, post.getGifOrVideoDownloadUrl());
intent.putExtra(ViewVideoActivity.SUBREDDIT_KEY, subredditName);
intent.putExtra(ViewVideoActivity.ID_KEY, id);
}
@ -321,17 +338,17 @@ class PostRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
case Post.VIDEO_TYPE:
((DataViewHolder) holder).typeTextView.setText("VIDEO");
final Uri videoUri = Uri.parse(mPostData.get(position).getVideoUrl());
final Uri videoUri = Uri.parse(post.getVideoUrl());
((DataViewHolder) holder).imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(mContext, ViewVideoActivity.class);
intent.setData(videoUri);
intent.putExtra(ViewVideoActivity.TITLE_KEY, title);
intent.putExtra(ViewVideoActivity.IS_DASH_VIDEO_KEY, mPostData.get(holder.getAdapterPosition()).isDashVideo());
intent.putExtra(ViewVideoActivity.IS_DOWNLOADABLE_KEY, mPostData.get(holder.getAdapterPosition()).isDownloadableGifOrVideo());
if(mPostData.get(holder.getAdapterPosition()).isDownloadableGifOrVideo()) {
intent.putExtra(ViewVideoActivity.DOWNLOAD_URL_KEY, mPostData.get(holder.getAdapterPosition()).getGifOrVideoDownloadUrl());
intent.putExtra(ViewVideoActivity.IS_DASH_VIDEO_KEY, post.isDashVideo());
intent.putExtra(ViewVideoActivity.IS_DOWNLOADABLE_KEY, post.isDownloadableGifOrVideo());
if(post.isDownloadableGifOrVideo()) {
intent.putExtra(ViewVideoActivity.DOWNLOAD_URL_KEY, post.getGifOrVideoDownloadUrl());
intent.putExtra(ViewVideoActivity.SUBREDDIT_KEY, subredditName);
intent.putExtra(ViewVideoActivity.ID_KEY, id);
}
@ -341,7 +358,7 @@ class PostRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
break;
case Post.NO_PREVIEW_LINK_TYPE:
((DataViewHolder) holder).typeTextView.setText("LINK");
final String noPreviewLinkUrl = mPostData.get(position).getUrl();
final String noPreviewLinkUrl = post.getUrl();
((DataViewHolder) holder).noPreviewLinkImageView.setVisibility(View.VISIBLE);
((DataViewHolder) holder).noPreviewLinkImageView.setOnClickListener(new View.OnClickListener() {
@Override
@ -371,19 +388,19 @@ class PostRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
if (((DataViewHolder) holder).upvoteButton.getColorFilter() == null) {
((DataViewHolder) holder).upvoteButton.setColorFilter(ContextCompat.getColor(mContext, R.color.colorPrimary), android.graphics.PorterDuff.Mode.SRC_IN);
if(isDownvotedBefore) {
((DataViewHolder) holder).scoreTextView.setText(Integer.toString(mPostData.get(holder.getAdapterPosition()).getScore() + 2));
((DataViewHolder) holder).scoreTextView.setText(Integer.toString(post.getScore() + 2));
} else {
((DataViewHolder) holder).scoreTextView.setText(Integer.toString(mPostData.get(holder.getAdapterPosition()).getScore() + 1));
((DataViewHolder) holder).scoreTextView.setText(Integer.toString(post.getScore() + 1));
}
VoteThing.voteThing(mOauthRetrofit, mSharedPreferences, new VoteThing.VoteThingListener() {
@Override
public void onVoteThingSuccess(int position) {
mPostData.get(position).setVoteType(1);
post.setVoteType(1);
if(isDownvotedBefore) {
mPostData.get(position).setScore(mPostData.get(position).getScore() + 2);
post.setScore(post.getScore() + 2);
} else {
mPostData.get(position).setScore(mPostData.get(position).getScore() + 1);
post.setScore(post.getScore() + 1);
}
}
@ -391,28 +408,28 @@ class PostRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
public void onVoteThingFail(int position) {
Toast.makeText(mContext, "Cannot upvote this post", Toast.LENGTH_SHORT).show();
((DataViewHolder) holder).upvoteButton.clearColorFilter();
((DataViewHolder) holder).scoreTextView.setText(Integer.toString(mPostData.get(position).getScore()));
((DataViewHolder) holder).scoreTextView.setText(Integer.toString(post.getScore()));
((DataViewHolder) holder).downvoteButton.setColorFilter(downvoteButtonColorFilter);
}
}, id, RedditUtils.DIR_UPVOTE, holder.getAdapterPosition());
} else {
//Upvoted before
((DataViewHolder) holder).upvoteButton.clearColorFilter();
((DataViewHolder) holder).scoreTextView.setText(Integer.toString(mPostData.get(holder.getAdapterPosition()).getScore() - 1));
((DataViewHolder) holder).scoreTextView.setText(Integer.toString(post.getScore() - 1));
VoteThing.voteThing(mOauthRetrofit, mSharedPreferences, new VoteThing.VoteThingListener() {
@Override
public void onVoteThingSuccess(int position) {
mPostData.get(position).setVoteType(0);
mPostData.get(position).setScore(mPostData.get(position).getScore() - 1);
post.setVoteType(0);
post.setScore(post.getScore() - 1);
}
@Override
public void onVoteThingFail(int position) {
Toast.makeText(mContext, "Cannot unvote this post", Toast.LENGTH_SHORT).show();
((DataViewHolder) holder).scoreTextView.setText(Integer.toString(mPostData.get(position).getScore() + 1));
((DataViewHolder) holder).scoreTextView.setText(Integer.toString(post.getScore() + 1));
((DataViewHolder) holder).upvoteButton.setColorFilter(ContextCompat.getColor(mContext, R.color.colorPrimary), android.graphics.PorterDuff.Mode.SRC_IN);
mPostData.get(position).setScore(mPostData.get(position).getScore() + 1);
post.setScore(post.getScore() + 1);
}
}, id, RedditUtils.DIR_UNVOTE, holder.getAdapterPosition());
}
@ -429,19 +446,19 @@ class PostRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
if (((DataViewHolder) holder).downvoteButton.getColorFilter() == null) {
((DataViewHolder) holder).downvoteButton.setColorFilter(ContextCompat.getColor(mContext, R.color.minusButtonColor), android.graphics.PorterDuff.Mode.SRC_IN);
if (isUpvotedBefore) {
((DataViewHolder) holder).scoreTextView.setText(Integer.toString(mPostData.get(holder.getAdapterPosition()).getScore() - 2));
((DataViewHolder) holder).scoreTextView.setText(Integer.toString(post.getScore() - 2));
} else {
((DataViewHolder) holder).scoreTextView.setText(Integer.toString(mPostData.get(holder.getAdapterPosition()).getScore() - 1));
((DataViewHolder) holder).scoreTextView.setText(Integer.toString(post.getScore() - 1));
}
VoteThing.voteThing(mOauthRetrofit, mSharedPreferences, new VoteThing.VoteThingListener() {
@Override
public void onVoteThingSuccess(int position) {
mPostData.get(position).setVoteType(-1);
post.setVoteType(-1);
if(isUpvotedBefore) {
mPostData.get(position).setScore(mPostData.get(position).getScore() - 2);
post.setScore(post.getScore() - 2);
} else {
mPostData.get(position).setScore(mPostData.get(position).getScore() - 1);
post.setScore(post.getScore() - 1);
}
}
@ -449,28 +466,28 @@ class PostRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
public void onVoteThingFail(int position) {
Toast.makeText(mContext, "Cannot downvote this post", Toast.LENGTH_SHORT).show();
((DataViewHolder) holder).downvoteButton.clearColorFilter();
((DataViewHolder) holder).scoreTextView.setText(Integer.toString(mPostData.get(position).getScore()));
((DataViewHolder) holder).scoreTextView.setText(Integer.toString(post.getScore()));
((DataViewHolder) holder).upvoteButton.setColorFilter(upvoteButtonColorFilter);
}
}, id, RedditUtils.DIR_DOWNVOTE, holder.getAdapterPosition());
} else {
//Down voted before
((DataViewHolder) holder).downvoteButton.clearColorFilter();
((DataViewHolder) holder).scoreTextView.setText(Integer.toString(mPostData.get(holder.getAdapterPosition()).getScore() + 1));
((DataViewHolder) holder).scoreTextView.setText(Integer.toString(post.getScore() + 1));
VoteThing.voteThing(mOauthRetrofit, mSharedPreferences, new VoteThing.VoteThingListener() {
@Override
public void onVoteThingSuccess(int position) {
mPostData.get(position).setVoteType(0);
mPostData.get(position).setScore(mPostData.get(position).getScore());
post.setVoteType(0);
post.setScore(post.getScore());
}
@Override
public void onVoteThingFail(int position) {
Toast.makeText(mContext, "Cannot unvote this post", Toast.LENGTH_SHORT).show();
((DataViewHolder) holder).downvoteButton.setColorFilter(ContextCompat.getColor(mContext, R.color.minusButtonColor), android.graphics.PorterDuff.Mode.SRC_IN);
((DataViewHolder) holder).scoreTextView.setText(Integer.toString(mPostData.get(position).getScore()));
mPostData.get(position).setScore(mPostData.get(position).getScore());
((DataViewHolder) holder).scoreTextView.setText(Integer.toString(post.getScore()));
post.setScore(post.getScore());
}
}, id, RedditUtils.DIR_UNVOTE, holder.getAdapterPosition());
}
@ -492,7 +509,7 @@ class PostRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
((LoadingViewHolder) holder).retryButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mPaginationSynchronizer.getPaginationRetryNotifier().retry();
//mPaginationSynchronizer.getPaginationRetryNotifier().retry();
((LoadingViewHolder) holder).progressBar.setVisibility(View.VISIBLE);
((LoadingViewHolder) holder).relativeLayout.setVisibility(View.GONE);
}
@ -512,12 +529,12 @@ class PostRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
}
};
mPaginationSynchronizer.setPaginationNotifier(mPaginationNotifier);
/*mPaginationSynchronizer.setPaginationNotifier(mPaginationNotifier);
if(!mPaginationSynchronizer.isLoadingMorePostsSuccess()) {
((LoadingViewHolder) holder).progressBar.setVisibility(View.GONE);
((LoadingViewHolder) holder).relativeLayout.setVisibility(View.VISIBLE);
}
}*/
}
}
@ -553,27 +570,30 @@ class PostRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
imageRequestBuilder.into(((DataViewHolder) holder).imageView);
}
}
@Override
public int getItemCount() {
if(mPostData == null || mPostData.isEmpty()) {
return 0;
}
return mPostData.size() + 1;
}
@Override
public int getItemViewType(int position) {
return (position >= mPostData.size() ? VIEW_TYPE_LOADING : VIEW_TYPE_DATA);
return (position >= getItemCount() ? VIEW_TYPE_LOADING : VIEW_TYPE_DATA);
}
void changeDataSet(ArrayList<Post> posts) {
mPostData = posts;
if(dataSize == 0 || posts.size() <= dataSize) {
notifyDataSetChanged();
} else {
notifyItemRangeInserted(dataSize, posts.size() - dataSize);
private boolean hasExtraRow() {
return networkState != null && networkState != NetworkState.LOADED;
}
public void setNetworkState(NetworkState newNetworkState) {
NetworkState previousState = this.networkState;
boolean previousExtraRow = hasExtraRow();
this.networkState = newNetworkState;
boolean newExtraRow = hasExtraRow();
if (previousExtraRow != newExtraRow) {
if (previousExtraRow) {
notifyItemRemoved(getItemCount());
} else {
notifyItemInserted(getItemCount());
}
} else if (newExtraRow && previousState != newNetworkState) {
notifyItemChanged(getItemCount() - 1);
}
dataSize = posts.size();
}
class DataViewHolder extends RecyclerView.ViewHolder {

View File

@ -1,30 +1,66 @@
package ml.docilealligator.infinityforreddit;
import android.arch.lifecycle.LiveData;
import android.arch.lifecycle.MutableLiveData;
import android.arch.lifecycle.ViewModel;
import android.arch.lifecycle.ViewModelProvider;
import android.arch.paging.LivePagedListBuilder;
import android.arch.paging.PageKeyedDataSource;
import android.arch.paging.PagedList;
import android.support.annotation.NonNull;
import java.util.ArrayList;
import java.util.Locale;
import java.util.concurrent.Executor;
import retrofit2.Retrofit;
public class PostViewModel extends ViewModel {
private MutableLiveData<ArrayList<Post>> posts = new MutableLiveData<>();
private Executor executor;
LiveData<NetworkState> networkState;
LiveData<PagedList<Post>> posts;
LiveData<PageKeyedDataSource<String, Post>> liveDataSource;
LiveData<ArrayList<Post>> getPosts() {
if(posts == null) {
setPosts(new ArrayList<Post>());
}
public PostViewModel(Retrofit retrofit, String accessToken, Locale locale, boolean isBestPost) {
//executor = Executors.newFixedThreadPool(5);
PostDataSourceFactory postDataSourceFactory = new PostDataSourceFactory(retrofit, accessToken, locale, isBestPost);
/*networkState = Transformations.switchMap(postDataSourceFactory.getMutableLiveData(),
(Function<PostDataSource, LiveData<NetworkState>>) PostDataSource::getNetworkState);*/
liveDataSource = postDataSourceFactory.getMutableLiveData();
PagedList.Config pagedListConfig =
(new PagedList.Config.Builder())
.setEnablePlaceholders(false)
.setPageSize(25)
.build();
posts = (new LivePagedListBuilder(postDataSourceFactory, pagedListConfig)).build();
}
LiveData<PagedList<Post>> getPosts() {
return posts;
}
void setPosts(ArrayList<Post> posts) {
this.posts.postValue(posts);
}
/*public LiveData<NetworkState> getNetworkState() {
return networkState;
}*/
void addPosts(ArrayList<Post> newPosts) {
ArrayList<Post> posts = this.posts.getValue();
if(posts != null) {
posts.addAll(newPosts);
this.posts.postValue(posts);
public static class Factory extends ViewModelProvider.NewInstanceFactory {
private Retrofit retrofit;
private String accessToken;
private Locale locale;
private boolean isBestPost;
public Factory(Retrofit retrofit, String accessToken, Locale locale, boolean isBestPost) {
this.retrofit = retrofit;
this.accessToken = accessToken;
this.locale = locale;
this.isBestPost = isBestPost;
}
@NonNull
@Override
public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
return (T) new PostViewModel(retrofit, accessToken, locale, isBestPost);
}
}
}

View File

@ -321,40 +321,6 @@ public class ViewPostDetailActivity extends AppCompatActivity {
}
queryComment();
/*final Observable<Integer> observable = Observable.create(
new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(mPost.getVoteType());
emitter.onComplete();
Log.i("asdasdf", "adasdfasdf");
Toast.makeText(ViewPostDetailActivity.this, "observable", Toast.LENGTH_SHORT).show();
}
}
);
final Observer observer = new Observer() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Object o) {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
Toast.makeText(ViewPostDetailActivity.this, "complete", Toast.LENGTH_SHORT).show();
}
};*/
mUpvoteButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {

View File

@ -0,0 +1,12 @@
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
</style>
</resources>

View File

@ -20,6 +20,9 @@ allprojects {
google()
jcenter()
maven { url 'https://jitpack.io' }
maven { url 'https://dl.bintray.com/sysdata/maven' }
maven { url 'http://repo.pageturner-reader.org' }
mavenCentral()
}
}