Load parent-level comments using pagination. Only load comments of comments once more.

This commit is contained in:
Alex Ning 2019-02-22 17:00:09 +08:00
parent a4f664d428
commit 2e72f0d4aa
7 changed files with 85 additions and 55 deletions

View File

@ -1,16 +1,10 @@
package ml.docilealligator.infinityforreddit; package ml.docilealligator.infinityforreddit;
import androidx.paging.PagedListAdapter;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.graphics.ColorFilter; import android.graphics.ColorFilter;
import android.net.Uri; import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.browser.customtabs.CustomTabsIntent;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@ -21,9 +15,16 @@ import android.widget.Toast;
import com.multilevelview.models.RecyclerViewItem; import com.multilevelview.models.RecyclerViewItem;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import androidx.annotation.NonNull;
import androidx.browser.customtabs.CustomTabsIntent;
import androidx.core.content.ContextCompat;
import androidx.paging.PagedListAdapter;
import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.RecyclerView;
import butterknife.BindView; import butterknife.BindView;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import retrofit2.Retrofit; import retrofit2.Retrofit;
@ -128,7 +129,7 @@ public class CommentAdapter extends PagedListAdapter<CommentData, RecyclerView.V
locale, false, commentItem.getDepth(), new FetchComment.FetchCommentListener() { locale, false, commentItem.getDepth(), new FetchComment.FetchCommentListener() {
@Override @Override
public void onFetchCommentSuccess(List<?> commentData, public void onFetchCommentSuccess(List<?> commentData,
String parentId, String commaSeparatedChildren) { String parentId, ArrayList<String> children) {
commentItem.addChildren((List<RecyclerViewItem>) commentData); commentItem.addChildren((List<RecyclerViewItem>) commentData);
((CommentViewHolder) viewHolder).loadMoreCommentsProgressBar ((CommentViewHolder) viewHolder).loadMoreCommentsProgressBar
.setVisibility(View.GONE); .setVisibility(View.GONE);
@ -140,7 +141,7 @@ public class CommentAdapter extends PagedListAdapter<CommentData, RecyclerView.V
new ParseComment.ParseCommentListener() { new ParseComment.ParseCommentListener() {
@Override @Override
public void onParseCommentSuccess(List<?> commentData, public void onParseCommentSuccess(List<?> commentData,
String parentId, String commaSeparatedChildren) { String parentId, String children) {
commentItem.addChildren((List<RecyclerViewItem>) commentData); commentItem.addChildren((List<RecyclerViewItem>) commentData);
((CommentViewHolder) viewHolder).loadMoreCommentsProgressBar ((CommentViewHolder) viewHolder).loadMoreCommentsProgressBar
.setVisibility(View.GONE); .setVisibility(View.GONE);

View File

@ -1,17 +1,11 @@
package ml.docilealligator.infinityforreddit; package ml.docilealligator.infinityforreddit;
import androidx.lifecycle.MutableLiveData;
import androidx.paging.PageKeyedDataSource;
import androidx.annotation.NonNull;
import android.util.Log;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale; import java.util.Locale;
import androidx.annotation.NonNull;
import androidx.lifecycle.MutableLiveData;
import androidx.paging.PageKeyedDataSource;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit; import retrofit2.Retrofit;
public class CommentDataSource extends PageKeyedDataSource<String, Post> { public class CommentDataSource extends PageKeyedDataSource<String, Post> {
@ -69,7 +63,7 @@ public class CommentDataSource extends PageKeyedDataSource<String, Post> {
RedditAPI api = retrofit.create(RedditAPI.class); RedditAPI api = retrofit.create(RedditAPI.class);
Call<String> comments = api.getComments(subredditNamePrefixed, article, comment); Call<String> comments = api.getComments(subredditNamePrefixed, article, comment);
comments.enqueue(new Callback<String>() { /*comments.enqueue(new Callback<String>() {
@Override @Override
public void onResponse(@NonNull Call<String> call, @NonNull Response<String> response) { public void onResponse(@NonNull Call<String> call, @NonNull Response<String> response) {
if(response.isSuccessful()) { if(response.isSuccessful()) {
@ -104,7 +98,7 @@ public class CommentDataSource extends PageKeyedDataSource<String, Post> {
public void onFailure(@NonNull Call<String> call, @NonNull Throwable t) { public void onFailure(@NonNull Call<String> call, @NonNull Throwable t) {
initialLoadStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, "Error fetching comment")); initialLoadStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, "Error fetching comment"));
} }
}); });*/
} }
@Override @Override
@ -126,7 +120,7 @@ public class CommentDataSource extends PageKeyedDataSource<String, Post> {
RedditAPI api = retrofit.create(RedditAPI.class); RedditAPI api = retrofit.create(RedditAPI.class);
Call<String> moreChildrenBasicInfo = api.getMoreChildren(mParentId, params.key); Call<String> moreChildrenBasicInfo = api.getMoreChildren(mParentId, params.key);
moreChildrenBasicInfo.enqueue(new Callback<String>() { /*moreChildrenBasicInfo.enqueue(new Callback<String>() {
@Override @Override
public void onResponse(Call<String> call, Response<String> response) { public void onResponse(Call<String> call, Response<String> response) {
if(response.isSuccessful()) { if(response.isSuccessful()) {
@ -182,7 +176,7 @@ public class CommentDataSource extends PageKeyedDataSource<String, Post> {
String errorMessage = t == null ? "unknown error" : t.getMessage(); String errorMessage = t == null ? "unknown error" : t.getMessage();
paginationNetworkStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, errorMessage)); paginationNetworkStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, errorMessage));
} }
}); });*/
} }
void retry() { void retry() {

View File

@ -15,12 +15,12 @@ import retrofit2.Retrofit;
class FetchComment { class FetchComment {
interface FetchCommentListener { interface FetchCommentListener {
void onFetchCommentSuccess(List<?> commentData, void onFetchCommentSuccess(List<?> commentData,
String parentId, String commaSeparatedChildren); String parentId, ArrayList<String> children);
void onFetchCommentFailed(); void onFetchCommentFailed();
} }
interface FetchMoreCommentListener { interface FetchMoreCommentListener {
void onFetchMoreCommentSuccess(List<?> commentData); void onFetchMoreCommentSuccess(List<?> commentData, int childrenStartingIndex);
void onFetchMoreCommentFailed(); void onFetchMoreCommentFailed();
} }
@ -43,9 +43,9 @@ class FetchComment {
new ParseComment.ParseCommentListener() { new ParseComment.ParseCommentListener() {
@Override @Override
public void onParseCommentSuccess(List<?> commentData, public void onParseCommentSuccess(List<?> commentData,
String parentId, String commaSeparatedChildren) { String parentId, ArrayList<String> children) {
fetchCommentListener.onFetchCommentSuccess(commentData, parentId, fetchCommentListener.onFetchCommentSuccess(commentData, parentId,
commaSeparatedChildren); children);
} }
@Override @Override
@ -69,9 +69,25 @@ class FetchComment {
} }
static void fetchMoreComment(Retrofit retrofit, String subredditNamePrefixed, String mParentId, static void fetchMoreComment(Retrofit retrofit, String subredditNamePrefixed, String mParentId,
String children, Locale locale, FetchMoreCommentListener fetchMoreCommentListener) { ArrayList<String> allChildren, int startingIndex, Locale locale,
FetchMoreCommentListener fetchMoreCommentListener) {
StringBuilder stringBuilder = new StringBuilder();
for(int i = 0; i < 100; i++) {
if(allChildren.size() <= startingIndex + i) {
break;
}
stringBuilder.append(allChildren.get(startingIndex + i)).append(",");
}
if(stringBuilder.length() == 0) {
return;
}
stringBuilder.deleteCharAt(stringBuilder.length() - 1);
//final int finalStartingIndex = startingIndex + 100;
RedditAPI api = retrofit.create(RedditAPI.class); RedditAPI api = retrofit.create(RedditAPI.class);
Call<String> moreChildrenBasicInfo = api.getMoreChildren(mParentId, children); Call<String> moreChildrenBasicInfo = api.getMoreChildren(mParentId, stringBuilder.toString());
moreChildrenBasicInfo.enqueue(new Callback<String>() { moreChildrenBasicInfo.enqueue(new Callback<String>() {
@Override @Override
public void onResponse(Call<String> call, Response<String> response) { public void onResponse(Call<String> call, Response<String> response) {
@ -88,8 +104,11 @@ class FetchComment {
0, new ParseComment.ParseCommentListener() { 0, new ParseComment.ParseCommentListener() {
@Override @Override
public void onParseCommentSuccess(List<?> commentData, String parentId, public void onParseCommentSuccess(List<?> commentData, String parentId,
String commaSeparatedChildren) { ArrayList<String> children) {
fetchMoreCommentListener.onFetchMoreCommentSuccess(commentData); fetchMoreCommentListener.onFetchMoreCommentSuccess(commentData, startingIndex + 100);
/*fetchMoreComment(retrofit, subredditNamePrefixed,
mParentId, allChildren, finalStartingIndex,
locale, fetchMoreCommentListener);*/
} }
@Override @Override
@ -138,12 +157,13 @@ class FetchComment {
fetchComment(retrofit, subredditNamePrefixed, article, comment, locale, isPost, parentDepth, fetchComment(retrofit, subredditNamePrefixed, article, comment, locale, isPost, parentDepth,
new FetchCommentListener() { new FetchCommentListener() {
@Override @Override
public void onFetchCommentSuccess(List<?> commentData, String parentId, String commaSeparatedChildren) { public void onFetchCommentSuccess(List<?> commentData, String parentId, ArrayList<String> children) {
if(!commaSeparatedChildren.equals("")) { if(children.size() != 0) {
fetchMoreComment(retrofit, subredditNamePrefixed, parentId, commaSeparatedChildren, fetchMoreComment(retrofit, subredditNamePrefixed, parentId, children,
locale, new FetchMoreCommentListener() { 0, locale, new FetchMoreCommentListener() {
@Override @Override
public void onFetchMoreCommentSuccess(List<?> moreCommentData) { public void onFetchMoreCommentSuccess(List<?> moreCommentData,
int childrenStartingIndex) {
((ArrayList<CommentData>)commentData).addAll((ArrayList<CommentData>) moreCommentData); ((ArrayList<CommentData>)commentData).addAll((ArrayList<CommentData>) moreCommentData);
fetchAllCommentListener.onFetchAllCommentSuccess(commentData); fetchAllCommentListener.onFetchAllCommentSuccess(commentData);
} }

View File

@ -147,7 +147,7 @@ public class MainActivity extends AppCompatActivity {
@Override @Override
public void onSearchViewClosed() { public void onSearchViewClosed() {
transparentOverlay.setVisibility(View.GONE); transparentOverlay.setVisibility(View.GONE);
getWindow().setStatusBarColor(getResources().getColor(R.color.colorPrimaryDark)); getWindow().setStatusBarColor(Color.TRANSPARENT);
} }
@Override @Override

View File

@ -15,7 +15,7 @@ import java.util.Locale;
class ParseComment { class ParseComment {
interface ParseCommentListener { interface ParseCommentListener {
void onParseCommentSuccess(List<?> commentData, String parentId, String commaSeparatedChildren); void onParseCommentSuccess(List<?> commentData, String parentId, ArrayList<String> children);
void onParseCommentFailed(); void onParseCommentFailed();
} }
@ -64,7 +64,7 @@ class ParseComment {
private JSONArray comments; private JSONArray comments;
private ArrayList<CommentData> commentData; private ArrayList<CommentData> commentData;
private ArrayList<CommentData> newcommentData; private ArrayList<CommentData> newcommentData;
private StringBuilder commaSeparatedChildren; private ArrayList<String> children;
private Locale locale; private Locale locale;
private int parentDepth; private int parentDepth;
private ParseCommentListener parseCommentListener; private ParseCommentListener parseCommentListener;
@ -76,7 +76,7 @@ class ParseComment {
this.comments = comments; this.comments = comments;
this.commentData = commentData; this.commentData = commentData;
newcommentData = new ArrayList<>(); newcommentData = new ArrayList<>();
commaSeparatedChildren = new StringBuilder(); children = new ArrayList<>();
this.locale = locale; this.locale = locale;
this.parentDepth = parentDepth; this.parentDepth = parentDepth;
parseFailed = false; parseFailed = false;
@ -87,7 +87,6 @@ class ParseComment {
protected Void doInBackground(Void... voids) { protected Void doInBackground(Void... voids) {
try { try {
int actualCommentLength; int actualCommentLength;
ArrayList<String> children = new ArrayList<>();
if(comments.length() == 0) { if(comments.length() == 0) {
return null; return null;
@ -104,11 +103,6 @@ class ParseComment {
children.add(childrenArray.getString(i)); children.add(childrenArray.getString(i));
} }
for(String c : children) {
commaSeparatedChildren.append(c).append(",");
}
commaSeparatedChildren.deleteCharAt(commaSeparatedChildren.length() - 1);
actualCommentLength = comments.length() - 1; actualCommentLength = comments.length() - 1;
} else { } else {
actualCommentLength = comments.length(); actualCommentLength = comments.length();
@ -156,7 +150,7 @@ class ParseComment {
protected void onPostExecute(Void aVoid) { protected void onPostExecute(Void aVoid) {
if(!parseFailed) { if(!parseFailed) {
commentData.addAll(newcommentData); commentData.addAll(newcommentData);
parseCommentListener.onParseCommentSuccess(commentData, parentId, commaSeparatedChildren.toString()); parseCommentListener.onParseCommentSuccess(commentData, parentId, children);
} else { } else {
parseCommentListener.onParseCommentFailed(); parseCommentListener.onParseCommentFailed();
} }

View File

@ -9,6 +9,7 @@ import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.ProgressBar; import android.widget.ProgressBar;
@ -44,6 +45,7 @@ import androidx.browser.customtabs.CustomTabsIntent;
import androidx.cardview.widget.CardView; import androidx.cardview.widget.CardView;
import androidx.coordinatorlayout.widget.CoordinatorLayout; import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import androidx.core.widget.NestedScrollView;
import androidx.recyclerview.widget.DividerItemDecoration; import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import butterknife.BindView; import butterknife.BindView;
@ -66,9 +68,12 @@ public class ViewPostDetailActivity extends AppCompatActivity {
private Post mPost; private Post mPost;
private String mCommaSeparatedChildren; private boolean isLoadingMoreChildren = false;
private ArrayList<String> children;
private int mChildrenStartingIndex = 0;
@BindView(R.id.coordinator_layout_view_post_detail) CoordinatorLayout mCoordinatorLayout; @BindView(R.id.coordinator_layout_view_post_detail) CoordinatorLayout mCoordinatorLayout;
@BindView(R.id.nested_scroll_view_view_post_detail_activity) NestedScrollView mNestedScrollView;
@BindView(R.id.subreddit_icon_name_linear_layout_view_post_detail) LinearLayout mSubredditIconNameLinearLayout; @BindView(R.id.subreddit_icon_name_linear_layout_view_post_detail) LinearLayout mSubredditIconNameLinearLayout;
@BindView(R.id.subreddit_icon_circle_image_view_view_post_detail) AspectRatioGifImageView mSubredditIconGifImageView; @BindView(R.id.subreddit_icon_circle_image_view_view_post_detail) AspectRatioGifImageView mSubredditIconGifImageView;
@BindView(R.id.subreddit_text_view_view_post_detail) TextView mSubredditTextView; @BindView(R.id.subreddit_text_view_view_post_detail) TextView mSubredditTextView;
@ -446,8 +451,8 @@ public class ViewPostDetailActivity extends AppCompatActivity {
null, getResources().getConfiguration().locale, true, 0, new FetchComment.FetchCommentListener() { null, getResources().getConfiguration().locale, true, 0, new FetchComment.FetchCommentListener() {
@Override @Override
public void onFetchCommentSuccess(List<?> commentData, public void onFetchCommentSuccess(List<?> commentData,
String parentId, String commaSeparatedChildren) { String parentId, ArrayList<String> children) {
mCommaSeparatedChildren = commaSeparatedChildren; ViewPostDetailActivity.this.children = children;
mCommentProgressbar.setVisibility(View.GONE); mCommentProgressbar.setVisibility(View.GONE);
if (commentData.size() > 0) { if (commentData.size() > 0) {
mAdapter = new CommentMultiLevelRecyclerViewAdapter( mAdapter = new CommentMultiLevelRecyclerViewAdapter(
@ -461,9 +466,19 @@ public class ViewPostDetailActivity extends AppCompatActivity {
mRecyclerView.setAdapter(mAdapter); mRecyclerView.setAdapter(mAdapter);
mCommentCardView.setVisibility(View.VISIBLE); mCommentCardView.setVisibility(View.VISIBLE);
if(!mCommaSeparatedChildren.equals("")) { mNestedScrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
fetchMoreComment(); @Override
} public void onScrollChanged() {
if(!isLoadingMoreChildren) {
View view = mNestedScrollView.getChildAt(mNestedScrollView.getChildCount() - 1);
int diff = view.getBottom() - (mNestedScrollView.getHeight() +
mNestedScrollView.getScrollY());
if(diff == 0) {
fetchMoreComment(mChildrenStartingIndex);
}
}
}
});
} else { } else {
mNoCommentWrapperLinearLayout.setVisibility(View.VISIBLE); mNoCommentWrapperLinearLayout.setVisibility(View.VISIBLE);
glide.load(R.drawable.no_comment_indicator).into(mNoCommentImageView); glide.load(R.drawable.no_comment_indicator).into(mNoCommentImageView);
@ -478,18 +493,23 @@ public class ViewPostDetailActivity extends AppCompatActivity {
}); });
} }
private void fetchMoreComment() { private void fetchMoreComment(int startingIndex) {
isLoadingMoreChildren = true;
FetchComment.fetchMoreComment(mRetrofit, mPost.getSubredditNamePrefixed(), mPost.getFullName(), FetchComment.fetchMoreComment(mRetrofit, mPost.getSubredditNamePrefixed(), mPost.getFullName(),
mCommaSeparatedChildren, getResources().getConfiguration().locale, new FetchComment.FetchMoreCommentListener() { children, startingIndex, getResources().getConfiguration().locale,
new FetchComment.FetchMoreCommentListener() {
@Override @Override
public void onFetchMoreCommentSuccess(List<?> commentData) { public void onFetchMoreCommentSuccess(List<?> commentData, int childrenStartingIndex) {
mAdapter.addComments((ArrayList<CommentData>) commentData); mAdapter.addComments((ArrayList<CommentData>) commentData);
mChildrenStartingIndex = childrenStartingIndex;
isLoadingMoreChildren = false;
} }
@Override @Override
public void onFetchMoreCommentFailed() { public void onFetchMoreCommentFailed() {
isLoadingMoreChildren = false;
Snackbar snackbar = Snackbar.make(mCoordinatorLayout, R.string.load_more_comment_failed, Snackbar.LENGTH_INDEFINITE); Snackbar snackbar = Snackbar.make(mCoordinatorLayout, R.string.load_more_comment_failed, Snackbar.LENGTH_INDEFINITE);
snackbar.setAction(R.string.retry, view -> fetchMoreComment()); snackbar.setAction(R.string.retry, view -> fetchMoreComment(startingIndex));
snackbar.show(); snackbar.show();
} }
}); });

View File

@ -8,6 +8,7 @@
tools:context=".ViewPostDetailActivity"> tools:context=".ViewPostDetailActivity">
<androidx.core.widget.NestedScrollView <androidx.core.widget.NestedScrollView
android:id="@+id/nested_scroll_view_view_post_detail_activity"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">