Skip to content

Commit 69b28cb

Browse files
committed
Migrate to ListAdapter [2/2]
Signed-off-by: Muntashir Al-Islam <muntashirakon@riseup.net>
1 parent 8cf2c1e commit 69b28cb

12 files changed

Lines changed: 328 additions & 504 deletions

File tree

app/src/main/java/io/github/muntashirakon/AppManager/debloat/DebloaterActivity.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ protected void onAuthenticated(@Nullable Bundle savedInstanceState) {
103103

104104
viewModel.getDebloatObjectListLiveData().observe(this, debloatObjects -> {
105105
mProgressIndicator.hide();
106-
mAdapter.setAdapterList(debloatObjects);
106+
mAdapter.submitList(debloatObjects);
107107
});
108108
viewModel.loadPackages();
109109
}

app/src/main/java/io/github/muntashirakon/AppManager/debloat/DebloaterRecyclerViewAdapter.java

Lines changed: 42 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,21 @@
1717
import androidx.annotation.StringRes;
1818
import androidx.appcompat.widget.AppCompatImageView;
1919
import androidx.fragment.app.FragmentActivity;
20+
import androidx.recyclerview.widget.DiffUtil;
21+
import androidx.recyclerview.widget.RecyclerView;
2022

2123
import com.google.android.material.card.MaterialCardView;
2224
import com.google.android.material.color.MaterialColors;
2325
import com.google.android.material.textview.MaterialTextView;
2426

25-
import java.util.ArrayList;
26-
import java.util.List;
27+
import java.util.Objects;
2728

2829
import io.github.muntashirakon.AppManager.R;
2930
import io.github.muntashirakon.AppManager.utils.appearance.ColorCodes;
3031
import io.github.muntashirakon.util.AccessibilityUtils;
31-
import io.github.muntashirakon.util.AdapterUtils;
3232
import io.github.muntashirakon.widget.MultiSelectionView;
3333

34-
public class DebloaterRecyclerViewAdapter extends MultiSelectionView.Adapter<DebloaterRecyclerViewAdapter.ViewHolder> {
35-
private final List<DebloatObject> mAdapterList = new ArrayList<>();
36-
34+
public class DebloaterRecyclerViewAdapter extends MultiSelectionView.Adapter<DebloatObject, DebloaterRecyclerViewAdapter.ViewHolder> {
3735
private final FragmentActivity mActivity;
3836
@ColorInt
3937
private final int mRemovalSafeColor;
@@ -45,13 +43,29 @@ public class DebloaterRecyclerViewAdapter extends MultiSelectionView.Adapter<Deb
4543
private final int mRemovalCautionColor;
4644
@ColorInt
4745
private final int mColorSurface;
48-
private final Object mLock = new Object();
4946
@NonNull
5047
private final DebloaterViewModel mViewModel;
5148
@NonNull
5249
private final Drawable mDefaultIcon;
5350

51+
private static final DiffUtil.ItemCallback<DebloatObject> DIFF_CALLBACK = new DiffUtil.ItemCallback<DebloatObject>() {
52+
@Override
53+
public boolean areItemsTheSame(@NonNull DebloatObject oldItem, @NonNull DebloatObject newItem) {
54+
return oldItem.getId() == newItem.getId()
55+
&& Objects.equals(oldItem.packageName, newItem.packageName);
56+
}
57+
58+
@Override
59+
public boolean areContentsTheSame(@NonNull DebloatObject oldItem, @NonNull DebloatObject newItem) {
60+
return oldItem.getRemoval() == newItem.getRemoval()
61+
&& Objects.equals(oldItem.type, newItem.type)
62+
&& Objects.equals(oldItem.getWarning(), newItem.getWarning())
63+
&& Objects.equals(oldItem.getLabelOrPackageName(), newItem.getLabelOrPackageName());
64+
}
65+
};
66+
5467
public DebloaterRecyclerViewAdapter(DebloaterActivity activity) {
68+
super(DIFF_CALLBACK);
5569
mActivity = activity;
5670
mRemovalSafeColor = ColorCodes.getRemovalSafeIndicatorColor(activity);
5771
mRemovalReplaceColor = ColorCodes.getRemovalReplaceIndicatorColor(activity);
@@ -63,12 +77,6 @@ public DebloaterRecyclerViewAdapter(DebloaterActivity activity) {
6377
mDefaultIcon = activity.getPackageManager().getDefaultActivityIcon();
6478
}
6579

66-
public void setAdapterList(List<DebloatObject> adapterList) {
67-
synchronized (mLock) {
68-
AdapterUtils.notifyDataSetChanged(this, mAdapterList, adapterList);
69-
}
70-
}
71-
7280
@NonNull
7381
@Override
7482
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
@@ -78,10 +86,7 @@ public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
7886

7987
@Override
8088
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
81-
DebloatObject debloatObject;
82-
synchronized (mLock) {
83-
debloatObject = mAdapterList.get(position);
84-
}
89+
DebloatObject debloatObject = getItem(position);
8590
Context context = holder.itemView.getContext();
8691
Drawable icon = debloatObject.getIcon() != null ? debloatObject.getIcon() : mDefaultIcon;
8792
String warning = debloatObject.getWarning();
@@ -120,17 +125,26 @@ public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
120125
holder.itemView.setStrokeColor(removalColor);
121126
holder.labelView.setText(label);
122127
holder.itemView.setOnLongClickListener(v -> {
123-
toggleSelection(position);
124-
AccessibilityUtils.requestAccessibilityFocus(holder.itemView);
128+
int currentPos = holder.getBindingAdapterPosition();
129+
if (currentPos != RecyclerView.NO_POSITION) {
130+
toggleSelection(currentPos);
131+
AccessibilityUtils.requestAccessibilityFocus(holder.itemView);
132+
}
125133
return true;
126134
});
135+
127136
holder.iconView.setOnClickListener(v -> {
128-
toggleSelection(position);
129-
AccessibilityUtils.requestAccessibilityFocus(holder.itemView);
137+
int currentPos = holder.getBindingAdapterPosition();
138+
if (currentPos != RecyclerView.NO_POSITION) {
139+
toggleSelection(currentPos);
140+
AccessibilityUtils.requestAccessibilityFocus(holder.itemView);
141+
}
130142
});
131143
holder.itemView.setOnClickListener(v -> {
144+
int currentPos = holder.getBindingAdapterPosition();
145+
if (currentPos == RecyclerView.NO_POSITION) return;
132146
if (isInSelectionMode()) {
133-
toggleSelection(position);
147+
toggleSelection(currentPos);
134148
AccessibilityUtils.requestAccessibilityFocus(holder.itemView);
135149
} else {
136150
BloatwareDetailsDialog dialog = BloatwareDetailsDialog.getInstance(debloatObject.packageName);
@@ -142,32 +156,19 @@ public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
142156

143157
@Override
144158
public long getItemId(int position) {
145-
synchronized (mLock) {
146-
return mAdapterList.get(position).getId();
147-
}
148-
}
149-
150-
@Override
151-
public int getItemCount() {
152-
synchronized (mLock) {
153-
return mAdapterList.size();
154-
}
159+
return getItem(position).getId();
155160
}
156161

157162
@Override
158163
protected boolean select(int position) {
159-
synchronized (mLock) {
160-
mViewModel.select(mAdapterList.get(position));
161-
return true;
162-
}
164+
mViewModel.select(getItem(position));
165+
return true;
163166
}
164167

165168
@Override
166169
protected boolean deselect(int position) {
167-
synchronized (mLock) {
168-
mViewModel.deselect(mAdapterList.get(position));
169-
return true;
170-
}
170+
mViewModel.deselect(getItem(position));
171+
return true;
171172
}
172173

173174
@Override
@@ -178,9 +179,7 @@ protected void cancelSelection() {
178179

179180
@Override
180181
protected boolean isSelected(int position) {
181-
synchronized (mLock) {
182-
return mViewModel.isSelected(mAdapterList.get(position));
183-
}
182+
return mViewModel.isSelected(getItem(position));
184183
}
185184

186185
@Override

app/src/main/java/io/github/muntashirakon/AppManager/fm/FmAdapter.java

Lines changed: 52 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
import androidx.appcompat.widget.LinearLayoutCompat;
1717
import androidx.appcompat.widget.PopupMenu;
1818
import androidx.core.content.ContextCompat;
19+
import androidx.recyclerview.widget.DiffUtil;
20+
import androidx.recyclerview.widget.RecyclerView;
1921

2022
import com.google.android.material.button.MaterialButton;
2123
import com.google.android.material.card.MaterialCardView;
@@ -44,20 +46,35 @@
4446
import io.github.muntashirakon.util.AdapterUtils;
4547
import io.github.muntashirakon.widget.MultiSelectionView;
4648

47-
class FmAdapter extends MultiSelectionView.Adapter<FmAdapter.ViewHolder> {
49+
class FmAdapter extends MultiSelectionView.Adapter<FmItem, FmAdapter.ViewHolder> {
4850
private static final List<String> DEX_EXTENSIONS = Arrays.asList("dex", "jar");
4951

50-
private final List<FmItem> mAdapterList = Collections.synchronizedList(new ArrayList<>());
5152
private final FmViewModel mViewModel;
5253
private final FmActivity mFmActivity;
5354

55+
private static final DiffUtil.ItemCallback<FmItem> DIFF_CALLBACK = new DiffUtil.ItemCallback<FmItem>() {
56+
@Override
57+
public boolean areItemsTheSame(@NonNull FmItem oldItem, @NonNull FmItem newItem) {
58+
return Objects.equals(oldItem.path, newItem.path);
59+
}
60+
61+
@Override
62+
public boolean areContentsTheSame(@NonNull FmItem oldItem, @NonNull FmItem newItem) {
63+
return oldItem.isDirectory == newItem.isDirectory
64+
&& oldItem.getSize() == newItem.getSize()
65+
&& oldItem.getLastModified() == newItem.getLastModified()
66+
&& Objects.equals(oldItem.getName(), newItem.getName());
67+
}
68+
};
69+
5470
public FmAdapter(FmViewModel viewModel, FmActivity activity) {
71+
super(DIFF_CALLBACK);
5572
mViewModel = viewModel;
5673
mFmActivity = activity;
5774
}
5875

5976
public void setFmList(List<FmItem> list) {
60-
AdapterUtils.notifyDataSetChanged(this, mAdapterList, list);
77+
submitList(list != null ? new ArrayList<>(list) : null);
6178
notifySelectionChange();
6279
}
6380

@@ -73,24 +90,28 @@ public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
7390

7491
@Override
7592
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
76-
FmItem item = mAdapterList.get(position);
93+
FmItem item = getItem(position);
7794
holder.itemView.setTag(item.path);
7895
holder.title.setText(item.getName());
7996
// Load attributes
8097
cacheAndLoadAttributes(holder, item);
8198
if (item.isDirectory) {
8299
holder.itemView.setOnClickListener(v -> {
100+
int currentPos = holder.getBindingAdapterPosition();
101+
if (currentPos == RecyclerView.NO_POSITION) return;
83102
if (isInSelectionMode()) {
84-
toggleSelection(position);
103+
toggleSelection(currentPos);
85104
AccessibilityUtils.requestAccessibilityFocus(holder.itemView);
86105
return;
87106
}
88107
mViewModel.loadFiles(item.path.getUri());
89108
});
90109
} else {
91110
holder.itemView.setOnClickListener(v -> {
111+
int currentPos = holder.getBindingAdapterPosition();
112+
if (currentPos == RecyclerView.NO_POSITION) return;
92113
if (isInSelectionMode()) {
93-
toggleSelection(position);
114+
toggleSelection(currentPos);
94115
AccessibilityUtils.requestAccessibilityFocus(holder.itemView);
95116
return;
96117
}
@@ -105,33 +126,37 @@ public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
105126
holder.itemView.setCardBackgroundColor(ContextCompat.getColor(holder.itemView.getContext(), android.R.color.transparent));
106127
// Set selections
107128
holder.icon.setOnClickListener(v -> {
108-
toggleSelection(position);
109-
AccessibilityUtils.requestAccessibilityFocus(holder.itemView);
129+
int currentPos = holder.getBindingAdapterPosition();
130+
if (currentPos != RecyclerView.NO_POSITION) {
131+
toggleSelection(currentPos);
132+
AccessibilityUtils.requestAccessibilityFocus(holder.itemView);
133+
}
110134
});
111135
// Set actions
112-
PopupMenu popupMenu = getPopupMenu(holder.action, item, position);
136+
PopupMenu popupMenu = getPopupMenu(holder.action, item, holder);
113137
holder.action.setOnClickListener(v -> popupMenu.show());
114138
holder.itemView.setOnLongClickListener(v -> {
139+
int currentPos = holder.getBindingAdapterPosition();
140+
if (currentPos == RecyclerView.NO_POSITION) return false;
115141
// Long click listener: Select/deselect an app.
116142
// 1) Turn selection mode on if this is the first item in the selection list
117143
// 2) Select between last selection position and this position (inclusive) if selection mode is on
118144
Path lastSelectedItem = mViewModel.getLastSelectedItem();
119145
int lastSelectedItemPosition = -1;
120146
if (lastSelectedItem != null) {
121-
int i = 0;
122-
for (FmItem fmItem : mAdapterList) {
123-
if (fmItem.path.equals(lastSelectedItem)) {
147+
List<FmItem> currentList = getCurrentList();
148+
for (int i = 0; i < currentList.size(); i++) {
149+
if (currentList.get(i).path.equals(lastSelectedItem)) {
124150
lastSelectedItemPosition = i;
125151
break;
126152
}
127-
++i;
128153
}
129154
}
130155
if (lastSelectedItemPosition >= 0) {
131156
// Select from last selection to this selection
132-
selectRange(lastSelectedItemPosition, position);
157+
selectRange(lastSelectedItemPosition, currentPos);
133158
} else {
134-
toggleSelection(position);
159+
toggleSelection(currentPos);
135160
AccessibilityUtils.requestAccessibilityFocus(holder.itemView);
136161
}
137162
return true;
@@ -180,29 +205,24 @@ private void loadAttributes(@NonNull ViewHolder holder, @NonNull FmItem item) {
180205

181206
@Override
182207
public long getItemId(int position) {
183-
return mAdapterList.get(position).hashCode();
184-
}
185-
186-
@Override
187-
public int getItemCount() {
188-
return mAdapterList.size();
208+
return getItem(position).hashCode();
189209
}
190210

191211
@Override
192212
protected boolean select(int position) {
193-
mViewModel.setSelectedItem(mAdapterList.get(position).path, true);
213+
mViewModel.setSelectedItem(getItem(position).path, true);
194214
return true;
195215
}
196216

197217
@Override
198218
protected boolean deselect(int position) {
199-
mViewModel.setSelectedItem(mAdapterList.get(position).path, false);
219+
mViewModel.setSelectedItem(getItem(position).path, false);
200220
return true;
201221
}
202222

203223
@Override
204224
protected boolean isSelected(int position) {
205-
return mViewModel.isSelected(mAdapterList.get(position).path);
225+
return mViewModel.isSelected(getItem(position).path);
206226
}
207227

208228
@Override
@@ -218,10 +238,10 @@ protected int getSelectedItemCount() {
218238

219239
@Override
220240
protected int getTotalItemCount() {
221-
return mAdapterList.size();
241+
return getCurrentList().size();
222242
}
223243

224-
private PopupMenu getPopupMenu(@NonNull View anchor, @NonNull FmItem item, int position) {
244+
private PopupMenu getPopupMenu(@NonNull View anchor, @NonNull FmItem item, @NonNull ViewHolder holder) {
225245
PopupMenu popupMenu = new PopupMenu(anchor.getContext(), anchor);
226246
popupMenu.setForceShowIcon(true);
227247
popupMenu.inflate(R.menu.fragment_fm_item_actions);
@@ -299,9 +319,12 @@ private PopupMenu getPopupMenu(@NonNull View anchor, @NonNull FmItem item, int p
299319
return true;
300320
});
301321
selectAction.setOnMenuItemClickListener(menuItem -> {
302-
select(position);
303-
notifySelectionChange();
304-
notifyItemChanged(position, AdapterUtils.STUB);
322+
int currentPos = holder.getBindingAdapterPosition();
323+
if (currentPos != RecyclerView.NO_POSITION) {
324+
select(currentPos);
325+
notifySelectionChange();
326+
notifyItemChanged(currentPos, AdapterUtils.STUB);
327+
}
305328
return true;
306329
});
307330
boolean isVfs = mViewModel.getOptions().isVfs();

app/src/main/java/io/github/muntashirakon/AppManager/logcat/AbsLogViewerFragment.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public abstract class AbsLogViewerFragment extends Fragment implements MenuProvi
5151
LogViewerViewModel.LogLinesAvailableInterface,
5252
MultiSelectionActionsView.OnItemSelectedListener,
5353
MultiSelectionView.OnSelectionModeChangeListener,
54-
LogViewerActivity.SearchingInterface, Filter.FilterListener{
54+
LogViewerActivity.SearchingInterface, Filter.FilterListener {
5555
public static final String TAG = AbsLogViewerFragment.class.getSimpleName();
5656

5757
protected RecyclerView mRecyclerView;
@@ -210,7 +210,7 @@ public boolean onMenuItemSelected(@NonNull MenuItem item) {
210210
mActivity.displayLogViewerSettings();
211211
} else if (id == R.id.action_show_saved_filters) {
212212
mViewModel.loadFilters();
213-
} else if (id == R.id.action_share) {
213+
} else if (id == R.id.action_share) {
214214
displaySaveDebugLogsDialog(true, false);
215215
} else if (id == R.id.action_export) {
216216
displaySaveDebugLogsDialog(false, false);
@@ -244,9 +244,10 @@ public final void onFilterComplete(int count) {
244244

245245
@NonNull
246246
protected final List<String> getCurrentLogsAsListOfStrings() {
247-
List<String> result = new ArrayList<>(mLogListAdapter.getItemCount());
248-
for (int i = 0; i < mLogListAdapter.getItemCount(); i++) {
249-
result.add(mLogListAdapter.getItem(i).getOriginalLine());
247+
List<LogLine> currentList = mLogListAdapter.getCurrentList();
248+
List<String> result = new ArrayList<>(currentList.size());
249+
for (LogLine logLine : currentList) {
250+
result.add(logLine.getOriginalLine());
250251
}
251252
return result;
252253
}

0 commit comments

Comments
 (0)