Browse Source
redo follower/ing viewer
redo follower/ing viewer
Follower/ing viewer now uses the i endpoint (which returns more users at once) as well as caching (less requests needed) so its response time has decreased significantly (to 1/3 in my case)renovate/org.robolectric-robolectric-4.x
Austin Huang
4 years ago
No known key found for this signature in database
GPG Key ID: 84C23AA04587A91F
8 changed files with 276 additions and 296 deletions
-
111app/src/main/java/awais/instagrabber/adapters/FeedAdapter.java
-
101app/src/main/java/awais/instagrabber/asyncs/FollowFetcher.java
-
181app/src/main/java/awais/instagrabber/fragments/FollowViewerFragment.java
-
2app/src/main/java/awais/instagrabber/fragments/main/ProfileFragment.java
-
9app/src/main/java/awais/instagrabber/repositories/FriendshipRepository.java
-
79app/src/main/java/awais/instagrabber/repositories/responses/FriendshipRepoListFetchResponse.java
-
88app/src/main/java/awais/instagrabber/webservices/FriendshipService.java
-
1app/src/main/res/values/strings.xml
@ -1,111 +0,0 @@ |
|||||
// package awais.instagrabber.adapters; |
|
||||
// |
|
||||
// import android.content.Context; |
|
||||
// import android.view.LayoutInflater; |
|
||||
// import android.view.View; |
|
||||
// import android.view.ViewGroup; |
|
||||
// |
|
||||
// import androidx.annotation.NonNull; |
|
||||
// import androidx.recyclerview.widget.DiffUtil; |
|
||||
// import androidx.recyclerview.widget.ListAdapter; |
|
||||
// |
|
||||
// import awais.instagrabber.adapters.viewholder.feed.FeedItemViewHolder; |
|
||||
// import awais.instagrabber.adapters.viewholder.feed.FeedPhotoViewHolder; |
|
||||
// import awais.instagrabber.adapters.viewholder.feed.FeedSliderViewHolder; |
|
||||
// import awais.instagrabber.adapters.viewholder.feed.FeedVideoViewHolder; |
|
||||
// import awais.instagrabber.customviews.RamboTextView; |
|
||||
// import awais.instagrabber.databinding.ItemFeedPhotoBinding; |
|
||||
// import awais.instagrabber.databinding.ItemFeedSliderBinding; |
|
||||
// import awais.instagrabber.databinding.ItemFeedVideoBinding; |
|
||||
// import awais.instagrabber.interfaces.MentionClickListener; |
|
||||
// import awais.instagrabber.models.FeedModel; |
|
||||
// import awais.instagrabber.models.enums.MediaItemType; |
|
||||
// import awais.instagrabber.utils.Utils; |
|
||||
// |
|
||||
// public final class FeedAdapter extends ListAdapter<FeedModel, FeedItemViewHolder> { |
|
||||
// private static final String TAG = "FeedAdapter"; |
|
||||
// private final View.OnClickListener clickListener; |
|
||||
// private final MentionClickListener mentionClickListener; |
|
||||
// private final View.OnLongClickListener longClickListener = v -> { |
|
||||
// final Object tag; |
|
||||
// if (v instanceof RamboTextView && (tag = v.getTag()) instanceof FeedModel) |
|
||||
// Utils.copyText(v.getContext(), ((FeedModel) tag).getPostCaption()); |
|
||||
// return true; |
|
||||
// }; |
|
||||
// |
|
||||
// private static final DiffUtil.ItemCallback<FeedModel> diffCallback = new DiffUtil.ItemCallback<FeedModel>() { |
|
||||
// @Override |
|
||||
// public boolean areItemsTheSame(@NonNull final FeedModel oldItem, @NonNull final FeedModel newItem) { |
|
||||
// return oldItem.getPostId().equals(newItem.getPostId()); |
|
||||
// } |
|
||||
// |
|
||||
// @Override |
|
||||
// public boolean areContentsTheSame(@NonNull final FeedModel oldItem, @NonNull final FeedModel newItem) { |
|
||||
// return oldItem.getPostId().equals(newItem.getPostId()); |
|
||||
// } |
|
||||
// }; |
|
||||
// |
|
||||
// public FeedAdapter(final View.OnClickListener clickListener, |
|
||||
// final MentionClickListener mentionClickListener) { |
|
||||
// super(diffCallback); |
|
||||
// // private final static String ellipsize = "… more"; |
|
||||
// this.clickListener = clickListener; |
|
||||
// this.mentionClickListener = mentionClickListener; |
|
||||
// } |
|
||||
// |
|
||||
// @NonNull |
|
||||
// @Override |
|
||||
// public FeedItemViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int viewType) { |
|
||||
// final Context context = parent.getContext(); |
|
||||
// final LayoutInflater layoutInflater = LayoutInflater.from(context); |
|
||||
// final MediaItemType type = MediaItemType.valueOf(viewType); |
|
||||
// switch (type) { |
|
||||
// case MEDIA_TYPE_VIDEO: { |
|
||||
// final ItemFeedVideoBinding binding = ItemFeedVideoBinding.inflate(layoutInflater, parent, false); |
|
||||
// return new FeedVideoViewHolder(binding, mentionClickListener, clickListener, longClickListener); |
|
||||
// } |
|
||||
// case MEDIA_TYPE_SLIDER: { |
|
||||
// final ItemFeedSliderBinding binding = ItemFeedSliderBinding.inflate(layoutInflater, parent, false); |
|
||||
// return new FeedSliderViewHolder(binding, mentionClickListener, clickListener, longClickListener); |
|
||||
// } |
|
||||
// case MEDIA_TYPE_IMAGE: |
|
||||
// default: { |
|
||||
// final ItemFeedPhotoBinding binding = ItemFeedPhotoBinding.inflate(layoutInflater, parent, false); |
|
||||
// return new FeedPhotoViewHolder(binding, mentionClickListener, clickListener, longClickListener); |
|
||||
// } |
|
||||
// } |
|
||||
// } |
|
||||
// |
|
||||
// @Override |
|
||||
// public void onBindViewHolder(@NonNull final FeedItemViewHolder viewHolder, final int position) { |
|
||||
// final FeedModel feedModel = getItem(position); |
|
||||
// if (feedModel == null) { |
|
||||
// return; |
|
||||
// } |
|
||||
// feedModel.setPosition(position); |
|
||||
// viewHolder.bind(feedModel, (feedModel1, view, postImage) -> {}); |
|
||||
// } |
|
||||
// |
|
||||
// @Override |
|
||||
// public int getItemViewType(final int position) { |
|
||||
// return getItem(position).getItemType().getId(); |
|
||||
// } |
|
||||
// |
|
||||
// @Override |
|
||||
// public void onViewAttachedToWindow(@NonNull final FeedItemViewHolder holder) { |
|
||||
// super.onViewAttachedToWindow(holder); |
|
||||
// // Log.d(TAG, "attached holder: " + holder); |
|
||||
// if (!(holder instanceof FeedSliderViewHolder)) return; |
|
||||
// final FeedSliderViewHolder feedSliderViewHolder = (FeedSliderViewHolder) holder; |
|
||||
// feedSliderViewHolder.startPlayingVideo(); |
|
||||
// } |
|
||||
// |
|
||||
// @Override |
|
||||
// public void onViewDetachedFromWindow(@NonNull final FeedItemViewHolder holder) { |
|
||||
// super.onViewDetachedFromWindow(holder); |
|
||||
// // Log.d(TAG, "detached holder: " + holder); |
|
||||
// if (!(holder instanceof FeedSliderViewHolder)) return; |
|
||||
// final FeedSliderViewHolder feedSliderViewHolder = (FeedSliderViewHolder) holder; |
|
||||
// feedSliderViewHolder.stopPlayingVideo(); |
|
||||
// } |
|
||||
// } |
|
@ -1,101 +0,0 @@ |
|||||
package awais.instagrabber.asyncs; |
|
||||
|
|
||||
import android.os.AsyncTask; |
|
||||
import android.util.Log; |
|
||||
|
|
||||
import org.json.JSONArray; |
|
||||
import org.json.JSONObject; |
|
||||
|
|
||||
import java.net.HttpURLConnection; |
|
||||
import java.net.URL; |
|
||||
|
|
||||
import awais.instagrabber.BuildConfig; |
|
||||
import awais.instagrabber.interfaces.FetchListener; |
|
||||
import awais.instagrabber.models.FollowModel; |
|
||||
import awais.instagrabber.utils.Constants; |
|
||||
import awais.instagrabber.utils.NetworkUtils; |
|
||||
import awaisomereport.LogCollector; |
|
||||
|
|
||||
import static awais.instagrabber.utils.Utils.logCollector; |
|
||||
|
|
||||
public final class FollowFetcher extends AsyncTask<Void, Void, FollowModel[]> { |
|
||||
private final String endCursor, id; |
|
||||
private final boolean isFollowers; |
|
||||
private final FetchListener<FollowModel[]> fetchListener; |
|
||||
|
|
||||
public FollowFetcher(final String id, final boolean isFollowers, final FetchListener<FollowModel[]> fetchListener) { |
|
||||
this.id = id; |
|
||||
this.endCursor = ""; |
|
||||
this.isFollowers = isFollowers; |
|
||||
this.fetchListener = fetchListener; |
|
||||
} |
|
||||
|
|
||||
public FollowFetcher(final String id, final boolean isFollowers, final String endCursor, final FetchListener<FollowModel[]> fetchListener) { |
|
||||
this.id = id; |
|
||||
this.endCursor = endCursor == null ? "" : endCursor; |
|
||||
this.isFollowers = isFollowers; |
|
||||
this.fetchListener = fetchListener; |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
protected void onPreExecute() { |
|
||||
if (fetchListener != null) fetchListener.doBefore(); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
protected FollowModel[] doInBackground(final Void... voids) { |
|
||||
FollowModel[] result = null; |
|
||||
final String url = "https://www.instagram.com/graphql/query/?query_id=" + (isFollowers ? "17851374694183129" : "17874545323001329") |
|
||||
+ "&id=" + id + "&first=50&after=" + endCursor; |
|
||||
|
|
||||
try { |
|
||||
final HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection(); |
|
||||
conn.setInstanceFollowRedirects(false); |
|
||||
conn.setUseCaches(false); |
|
||||
conn.connect(); |
|
||||
|
|
||||
if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) { |
|
||||
final JSONObject data = new JSONObject(NetworkUtils.readFromConnection(conn)).getJSONObject("data") |
|
||||
.getJSONObject(Constants.EXTRAS_USER).getJSONObject(isFollowers ? "edge_followed_by" : "edge_follow"); |
|
||||
|
|
||||
final String endCursor; |
|
||||
final boolean hasNextPage; |
|
||||
|
|
||||
final JSONObject pageInfo = data.getJSONObject("page_info"); |
|
||||
if (pageInfo.has("has_next_page")) { |
|
||||
hasNextPage = pageInfo.getBoolean("has_next_page"); |
|
||||
endCursor = hasNextPage ? pageInfo.getString("end_cursor") : null; |
|
||||
} else { |
|
||||
hasNextPage = false; |
|
||||
endCursor = null; |
|
||||
} |
|
||||
|
|
||||
final JSONArray edges = data.getJSONArray("edges"); |
|
||||
final FollowModel[] models = new FollowModel[edges.length()]; |
|
||||
for (int i = 0; i < models.length; ++i) { |
|
||||
final JSONObject followNode = edges.getJSONObject(i).getJSONObject("node"); |
|
||||
models[i] = new FollowModel(followNode.getString(Constants.EXTRAS_ID), followNode.getString(Constants.EXTRAS_USERNAME), |
|
||||
followNode.getString("full_name"), followNode.getString("profile_pic_url")); |
|
||||
} |
|
||||
|
|
||||
if (models[models.length - 1] != null) |
|
||||
models[models.length - 1].setPageCursor(hasNextPage, endCursor); |
|
||||
|
|
||||
result = models; |
|
||||
} |
|
||||
|
|
||||
conn.disconnect(); |
|
||||
} catch (final Exception e) { |
|
||||
if (logCollector != null) |
|
||||
logCollector.appendException(e, LogCollector.LogFile.ASYNC_FOLLOW_FETCHER, "doInBackground"); |
|
||||
if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); |
|
||||
} |
|
||||
|
|
||||
return result; |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
protected void onPostExecute(final FollowModel[] result) { |
|
||||
if (fetchListener != null) fetchListener.onResult(result); |
|
||||
} |
|
||||
} |
|
@ -0,0 +1,79 @@ |
|||||
|
package awais.instagrabber.repositories.responses; |
||||
|
|
||||
|
import androidx.annotation.NonNull; |
||||
|
|
||||
|
import java.util.List; |
||||
|
import java.util.Objects; |
||||
|
|
||||
|
import awais.instagrabber.models.FollowModel; |
||||
|
import awais.instagrabber.utils.TextUtils; |
||||
|
|
||||
|
public class FriendshipRepoListFetchResponse { |
||||
|
private String nextMaxId; |
||||
|
private String status; |
||||
|
private List<FollowModel> items; |
||||
|
|
||||
|
public FriendshipRepoListFetchResponse(final String nextMaxId, |
||||
|
final String status, |
||||
|
final List<FollowModel> items) { |
||||
|
this.nextMaxId = nextMaxId; |
||||
|
this.status = status; |
||||
|
this.items = items; |
||||
|
} |
||||
|
|
||||
|
public boolean isMoreAvailable() { |
||||
|
return !TextUtils.isEmpty(nextMaxId); |
||||
|
} |
||||
|
|
||||
|
public String getNextMaxId() { |
||||
|
return nextMaxId; |
||||
|
} |
||||
|
|
||||
|
public FriendshipRepoListFetchResponse setNextMaxId(final String nextMaxId) { |
||||
|
this.nextMaxId = nextMaxId; |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
public String getStatus() { |
||||
|
return status; |
||||
|
} |
||||
|
|
||||
|
public FriendshipRepoListFetchResponse setStatus(final String status) { |
||||
|
this.status = status; |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
public List<FollowModel> getItems() { |
||||
|
return items; |
||||
|
} |
||||
|
|
||||
|
public FriendshipRepoListFetchResponse setItems(final List<FollowModel> items) { |
||||
|
this.items = items; |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean equals(final Object o) { |
||||
|
if (this == o) return true; |
||||
|
if (o == null || getClass() != o.getClass()) return false; |
||||
|
final FriendshipRepoListFetchResponse that = (FriendshipRepoListFetchResponse) o; |
||||
|
return Objects.equals(nextMaxId, that.nextMaxId) && |
||||
|
Objects.equals(status, that.status) && |
||||
|
Objects.equals(items, that.items); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public int hashCode() { |
||||
|
return Objects.hash(nextMaxId, status, items); |
||||
|
} |
||||
|
|
||||
|
@NonNull |
||||
|
@Override |
||||
|
public String toString() { |
||||
|
return "FriendshipRepoListFetchResponse{" + |
||||
|
"nextMaxId='" + nextMaxId + '\'' + |
||||
|
", status='" + status + '\'' + |
||||
|
", items=" + items + |
||||
|
'}'; |
||||
|
} |
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue