Moves loading of accounts, notifications, and statuses to use link headers. Also remedies an issue where duplicate calls for the same chunk of items in a list can occur.

This commit is contained in:
Vavassor 2017-06-30 02:31:58 -04:00
commit 3955649b9c
10 changed files with 755 additions and 374 deletions

View file

@ -21,12 +21,16 @@ import android.support.v7.widget.RecyclerView;
import com.keylesspalace.tusky.entity.Account;
import com.keylesspalace.tusky.interfaces.AccountActionListener;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
public abstract class AccountAdapter extends RecyclerView.Adapter {
List<Account> accountList;
AccountActionListener accountActionListener;
private String topId;
private String bottomId;
AccountAdapter(AccountActionListener accountActionListener) {
super();
@ -39,12 +43,20 @@ public abstract class AccountAdapter extends RecyclerView.Adapter {
return accountList.size() + 1;
}
public void update(List<Account> newAccounts) {
public void update(@Nullable List<Account> newAccounts, @Nullable String fromId,
@Nullable String uptoId) {
if (newAccounts == null || newAccounts.isEmpty()) {
return;
}
if (fromId != null) {
bottomId = fromId;
}
if (uptoId != null) {
topId = uptoId;
}
if (accountList.isEmpty()) {
accountList = newAccounts;
// This construction removes duplicates.
accountList = new ArrayList<>(new HashSet<>(newAccounts));
} else {
int index = accountList.indexOf(newAccounts.get(newAccounts.size() - 1));
for (int i = 0; i < index; i++) {
@ -60,10 +72,25 @@ public abstract class AccountAdapter extends RecyclerView.Adapter {
notifyDataSetChanged();
}
public void addItems(List<Account> newAccounts) {
public void addItems(List<Account> newAccounts, @Nullable String fromId) {
if (fromId != null) {
bottomId = fromId;
}
int end = accountList.size();
accountList.addAll(newAccounts);
notifyItemRangeInserted(end, newAccounts.size());
Account last = accountList.get(end - 1);
if (last != null && !findAccount(accountList, last.id)) {
accountList.addAll(newAccounts);
notifyItemRangeInserted(end, newAccounts.size());
}
}
private static boolean findAccount(List<Account> accounts, String id) {
for (Account account : accounts) {
if (account.id.equals(id)) {
return true;
}
}
return false;
}
@Nullable
@ -84,10 +111,21 @@ public abstract class AccountAdapter extends RecyclerView.Adapter {
notifyItemInserted(position);
}
@Nullable
public Account getItem(int position) {
if (position >= 0 && position < accountList.size()) {
return accountList.get(position);
}
return null;
}
@Nullable
public String getBottomId() {
return bottomId;
}
@Nullable
public String getTopId() {
return topId;
}
}

View file

@ -37,6 +37,7 @@ import com.keylesspalace.tusky.interfaces.StatusActionListener;
import com.squareup.picasso.Picasso;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
public class NotificationsAdapter extends RecyclerView.Adapter implements AdapterItemRemover {
@ -56,6 +57,8 @@ public class NotificationsAdapter extends RecyclerView.Adapter implements Adapte
private NotificationActionListener notificationActionListener;
private FooterState footerState = FooterState.END;
private boolean mediaPreviewEnabled;
private String bottomId;
private String topId;
public NotificationsAdapter(StatusActionListener statusListener,
NotificationActionListener notificationActionListener) {
@ -186,19 +189,28 @@ public class NotificationsAdapter extends RecyclerView.Adapter implements Adapte
}
}
public @Nullable Notification getItem(int position) {
@Nullable
public Notification getItem(int position) {
if (position >= 0 && position < notifications.size()) {
return notifications.get(position);
}
return null;
}
public void update(List<Notification> newNotifications) {
public void update(@Nullable List<Notification> newNotifications, @Nullable String fromId,
@Nullable String uptoId) {
if (newNotifications == null || newNotifications.isEmpty()) {
return;
}
if (fromId != null) {
bottomId = fromId;
}
if (uptoId != null) {
topId = uptoId;
}
if (notifications.isEmpty()) {
notifications = newNotifications;
// This construction removes duplicates.
notifications = new ArrayList<>(new HashSet<>(newNotifications));
} else {
int index = notifications.indexOf(newNotifications.get(newNotifications.size() - 1));
for (int i = 0; i < index; i++) {
@ -214,10 +226,25 @@ public class NotificationsAdapter extends RecyclerView.Adapter implements Adapte
notifyDataSetChanged();
}
public void addItems(List<Notification> new_notifications) {
public void addItems(List<Notification> newNotifications, @Nullable String fromId) {
if (fromId != null) {
bottomId = fromId;
}
int end = notifications.size();
notifications.addAll(new_notifications);
notifyItemRangeInserted(end, new_notifications.size());
Notification last = notifications.get(end - 1);
if (last != null && !findNotification(notifications, last.id)) {
notifications.addAll(newNotifications);
notifyItemRangeInserted(end, newNotifications.size());
}
}
private static boolean findNotification(List<Notification> notifications, String id) {
for (Notification notification : notifications) {
if (notification.id.equals(id)) {
return true;
}
}
return false;
}
public void clear() {
@ -233,6 +260,16 @@ public class NotificationsAdapter extends RecyclerView.Adapter implements Adapte
}
}
@Nullable
public String getBottomId() {
return bottomId;
}
@Nullable
public String getTopId() {
return topId;
}
public void setMediaPreviewEnabled(boolean enabled) {
mediaPreviewEnabled = enabled;
}

View file

@ -27,6 +27,7 @@ import com.keylesspalace.tusky.interfaces.StatusActionListener;
import com.keylesspalace.tusky.entity.Status;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
public class TimelineAdapter extends RecyclerView.Adapter implements AdapterItemRemover {
@ -43,6 +44,8 @@ public class TimelineAdapter extends RecyclerView.Adapter implements AdapterItem
private StatusActionListener statusListener;
private FooterState footerState = FooterState.END;
private boolean mediaPreviewEnabled;
private String topId;
private String bottomId;
public TimelineAdapter(StatusActionListener statusListener) {
super();
@ -126,12 +129,20 @@ public class TimelineAdapter extends RecyclerView.Adapter implements AdapterItem
}
}
public void update(List<Status> newStatuses) {
public void update(@Nullable List<Status> newStatuses, @Nullable String fromId,
@Nullable String uptoId) {
if (newStatuses == null || newStatuses.isEmpty()) {
return;
}
if (fromId != null) {
bottomId = fromId;
}
if (uptoId != null) {
topId = uptoId;
}
if (statuses.isEmpty()) {
statuses = newStatuses;
// This construction removes duplicates.
statuses = new ArrayList<>(new HashSet<>(newStatuses));
} else {
int index = statuses.indexOf(newStatuses.get(newStatuses.size() - 1));
for (int i = 0; i < index; i++) {
@ -147,10 +158,25 @@ public class TimelineAdapter extends RecyclerView.Adapter implements AdapterItem
notifyDataSetChanged();
}
public void addItems(List<Status> newStatuses) {
public void addItems(List<Status> newStatuses, @Nullable String fromId) {
if (fromId != null) {
bottomId = fromId;
}
int end = statuses.size();
statuses.addAll(newStatuses);
notifyItemRangeInserted(end, newStatuses.size());
Status last = statuses.get(end - 1);
if (last != null && !findStatus(statuses, last.id)) {
statuses.addAll(newStatuses);
notifyItemRangeInserted(end, newStatuses.size());
}
}
private static boolean findStatus(List<Status> statuses, String id) {
for (Status status : statuses) {
if (status.id.equals(id)) {
return true;
}
}
return false;
}
public void clear() {
@ -177,4 +203,14 @@ public class TimelineAdapter extends RecyclerView.Adapter implements AdapterItem
public void setMediaPreviewEnabled(boolean enabled) {
mediaPreviewEnabled = enabled;
}
@Nullable
public String getBottomId() {
return bottomId;
}
@Nullable
public String getTopId() {
return topId;
}
}