Skip to content

Commit acf7ca9

Browse files
kasnderclaude
andcommitted
Improve scroll and navigation performance in main app list
- Strip ~40 unused legacy views from rule.xml (MaterialSwitch, CheckBox, Button, ListView, etc.) that were inflated but never displayed - Reduce ViewHolder to 3 fields and 3 findViewById calls (was ~35) - Cache sort preference and greyscale ColorFilter to avoid per-bind allocations and SharedPreferences I/O - Fix icon size double-density scaling bug in Glide override - Replace full Rule.getRules() reload on back-navigation from details with notifyDataSetChanged, since SharedPreferences listeners already handle data changes Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent b2197e4 commit acf7ca9

5 files changed

Lines changed: 31 additions & 267 deletions

File tree

app/src/main/java/eu/faircode/netguard/ActivityMain.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -588,7 +588,11 @@ protected void onActivityResult(int requestCode, int resultCode, final Intent da
588588
// Do nothing
589589

590590
} else if (requestCode == REQUEST_DETAILS_UPDATED) {
591-
updateApplicationList(null);
591+
// Only rebind visible items to reflect any state changes (e.g. internet
592+
// blocking, tracker protection). A full updateApplicationList reload is
593+
// unnecessary since SharedPreferences listeners already handle data changes.
594+
if (adapter != null)
595+
adapter.notifyDataSetChanged();
592596

593597
} else if (requestCode == REQUEST_EXPORT) {
594598
if (resultCode == RESULT_OK && data != null)
@@ -735,6 +739,8 @@ public void onSharedPreferenceChanged(SharedPreferences prefs, String name) {
735739
"show_unprotected".equals(name) ||
736740
"sort".equals(name) ||
737741
"imported".equals(name)) {
742+
if ("sort".equals(name))
743+
adapter.updateSortPreference(prefs.getString("sort", "trackers_week"));
738744
updateApplicationList(null);
739745

740746
final LinearLayout llWhitelist = findViewById(R.id.llWhitelist);

app/src/main/java/eu/faircode/netguard/AdapterLog.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -242,8 +242,6 @@ public void bindView(final View view, final Context context, final Cursor cursor
242242
Uri uri = Uri.parse("android.resource://" + info.packageName + "/" + info.icon);
243243
GlideApp.with(context)
244244
.load(uri)
245-
//.diskCacheStrategy(DiskCacheStrategy.NONE)
246-
//.skipMemoryCache(true)
247245
.override(iconSize, iconSize)
248246
.into(ivIcon);
249247
}

app/src/main/java/eu/faircode/netguard/AdapterRule.java

Lines changed: 23 additions & 179 deletions
Original file line numberDiff line numberDiff line change
@@ -33,25 +33,15 @@
3333
import android.graphics.Color;
3434
import android.graphics.ColorMatrix;
3535
import android.graphics.ColorMatrixColorFilter;
36-
import android.graphics.Rect;
3736
import android.net.Uri;
3837
import android.util.Log;
3938
import android.util.TypedValue;
4039
import android.view.LayoutInflater;
41-
import android.view.TouchDelegate;
4240
import android.view.View;
4341
import android.view.ViewGroup;
44-
import android.widget.Button;
45-
import android.widget.CheckBox;
46-
import android.widget.CompoundButton;
4742
import android.widget.Filter;
4843
import android.widget.Filterable;
49-
import android.widget.ImageButton;
5044
import android.widget.ImageView;
51-
import android.widget.LinearLayout;
52-
import android.widget.ListView;
53-
import android.widget.RelativeLayout;
54-
import com.google.android.material.materialswitch.MaterialSwitch;
5545
import android.widget.TextView;
5646
import android.widget.Toast;
5747

@@ -72,7 +62,6 @@
7262
import net.kollnig.missioncontrol.data.InternetBlocklist;
7363

7464
import java.util.ArrayList;
75-
import java.util.Arrays;
7665
import java.util.List;
7766

7867
public class AdapterRule extends RecyclerView.Adapter<AdapterRule.ViewHolder> implements Filterable {
@@ -86,177 +75,32 @@ public class AdapterRule extends RecyclerView.Adapter<AdapterRule.ViewHolder> im
8675
private int colorOn;
8776
private int colorOff;
8877
private int colorGrayed;
89-
private int iconSize;
9078
private boolean wifiActive = true;
9179
private boolean otherActive = true;
9280
private boolean live = true;
9381
private List<Rule> listAll = new ArrayList<>();
9482
private List<Rule> listFiltered = new ArrayList<>();
83+
private int iconSize;
9584
private final RequestOptions glideOptions;
85+
private String cachedSort;
9686

97-
private List<String> messaging = Arrays.asList(
98-
"com.discord",
99-
"com.facebook.mlite",
100-
"com.facebook.orca",
101-
"com.instagram.android",
102-
"com.Slack",
103-
"com.skype.raider",
104-
"com.snapchat.android",
105-
"com.whatsapp",
106-
"com.whatsapp.w4b");
107-
108-
private List<String> download = Arrays.asList(
109-
"com.google.android.youtube");
87+
private static final ColorMatrixColorFilter GREYSCALE_FILTER;
88+
static {
89+
ColorMatrix matrix = new ColorMatrix();
90+
matrix.setSaturation(0);
91+
GREYSCALE_FILTER = new ColorMatrixColorFilter(matrix);
92+
}
11093

11194
public static class ViewHolder extends RecyclerView.ViewHolder {
112-
public View view;
113-
114-
public LinearLayout llApplication;
115-
public ImageView ivIcon;
116-
public ImageView ivExpander;
117-
public TextView tvName;
118-
119-
public TextView tvHosts;
120-
121-
public RelativeLayout rlLockdown;
122-
public ImageView ivLockdown;
123-
124-
public CheckBox cbWifi;
125-
public ImageView ivScreenWifi;
126-
127-
public CheckBox cbOther;
128-
public ImageView ivScreenOther;
129-
public TextView tvRoaming;
130-
131-
public TextView tvRemarkMessaging;
132-
public TextView tvRemarkDownload;
133-
134-
public LinearLayout llConfiguration;
135-
public TextView tvUid;
136-
public TextView tvPackage;
137-
public TextView tvVersion;
138-
public TextView tvInternet;
139-
public TextView tvDisabled;
140-
141-
public Button btnRelated;
142-
public ImageButton ibSettings;
143-
public ImageButton ibLaunch;
144-
145-
public MaterialSwitch cbApply;
146-
147-
public LinearLayout llScreenWifi;
148-
public ImageView ivWifiLegend;
149-
public CheckBox cbScreenWifi;
150-
151-
public LinearLayout llScreenOther;
152-
public ImageView ivOtherLegend;
153-
public CheckBox cbScreenOther;
154-
155-
public CheckBox cbRoaming;
156-
157-
public CheckBox cbLockdown;
158-
public ImageView ivLockdownLegend;
159-
160-
public ImageButton btnClear;
161-
162-
public LinearLayout llFilter;
163-
public ImageView ivLive;
164-
public TextView tvLogging;
165-
public Button btnLogging;
166-
public ListView lvAccess;
167-
public ImageButton btnClearAccess;
168-
public CheckBox cbNotify;
169-
170-
// Custom code
171-
private final TextView tvDetails;
95+
public final ImageView ivIcon;
96+
public final TextView tvName;
97+
public final TextView tvDetails;
17298

17399
public ViewHolder(View itemView) {
174100
super(itemView);
175-
view = itemView;
176-
177-
llApplication = itemView.findViewById(R.id.llApplication);
178101
ivIcon = itemView.findViewById(R.id.ivIcon);
179-
180-
ivExpander = itemView.findViewById(R.id.ivExpander);
181102
tvName = itemView.findViewById(R.id.tvName);
182-
183-
tvHosts = itemView.findViewById(R.id.tvHosts);
184-
185-
rlLockdown = itemView.findViewById(R.id.rlLockdown);
186-
ivLockdown = itemView.findViewById(R.id.ivLockdown);
187-
188-
cbWifi = itemView.findViewById(R.id.cbWifi);
189-
ivScreenWifi = itemView.findViewById(R.id.ivScreenWifi);
190-
191-
cbOther = itemView.findViewById(R.id.cbOther);
192-
ivScreenOther = itemView.findViewById(R.id.ivScreenOther);
193-
tvRoaming = itemView.findViewById(R.id.tvRoaming);
194-
195-
tvRemarkMessaging = itemView.findViewById(R.id.tvRemarkMessaging);
196-
tvRemarkDownload = itemView.findViewById(R.id.tvRemarkDownload);
197-
198-
llConfiguration = itemView.findViewById(R.id.llConfiguration);
199-
tvUid = itemView.findViewById(R.id.tvUid);
200-
tvPackage = itemView.findViewById(R.id.tvPackage);
201-
tvVersion = itemView.findViewById(R.id.tvVersion);
202-
tvInternet = itemView.findViewById(R.id.tvInternet);
203-
tvDisabled = itemView.findViewById(R.id.tvDisabled);
204-
205-
btnRelated = itemView.findViewById(R.id.btnRelated);
206-
ibSettings = itemView.findViewById(R.id.ibSettings);
207-
ibLaunch = itemView.findViewById(R.id.ibLaunch);
208-
209-
cbApply = itemView.findViewById(R.id.cbApply);
210103
tvDetails = itemView.findViewById(R.id.app_details);
211-
212-
llScreenWifi = itemView.findViewById(R.id.llScreenWifi);
213-
ivWifiLegend = itemView.findViewById(R.id.ivWifiLegend);
214-
cbScreenWifi = itemView.findViewById(R.id.cbScreenWifi);
215-
216-
llScreenOther = itemView.findViewById(R.id.llScreenOther);
217-
ivOtherLegend = itemView.findViewById(R.id.ivOtherLegend);
218-
cbScreenOther = itemView.findViewById(R.id.cbScreenOther);
219-
220-
cbRoaming = itemView.findViewById(R.id.cbRoaming);
221-
222-
cbLockdown = itemView.findViewById(R.id.cbLockdown);
223-
ivLockdownLegend = itemView.findViewById(R.id.ivLockdownLegend);
224-
225-
btnClear = itemView.findViewById(R.id.btnClear);
226-
227-
llFilter = itemView.findViewById(R.id.llFilter);
228-
ivLive = itemView.findViewById(R.id.ivLive);
229-
tvLogging = itemView.findViewById(R.id.tvLogging);
230-
btnLogging = itemView.findViewById(R.id.btnLogging);
231-
lvAccess = itemView.findViewById(R.id.lvAccess);
232-
btnClearAccess = itemView.findViewById(R.id.btnClearAccess);
233-
cbNotify = itemView.findViewById(R.id.cbNotify);
234-
235-
final View wifiParent = (View) cbWifi.getParent();
236-
wifiParent.post(new Runnable() {
237-
public void run() {
238-
Rect rect = new Rect();
239-
cbWifi.getHitRect(rect);
240-
rect.bottom += rect.top;
241-
rect.right += rect.left;
242-
rect.top = 0;
243-
rect.left = 0;
244-
wifiParent.setTouchDelegate(new TouchDelegate(rect, cbWifi));
245-
}
246-
});
247-
248-
final View otherParent = (View) cbOther.getParent();
249-
otherParent.post(new Runnable() {
250-
public void run() {
251-
Rect rect = new Rect();
252-
cbOther.getHitRect(rect);
253-
rect.bottom += rect.top;
254-
rect.right += rect.left;
255-
rect.top = 0;
256-
rect.left = 0;
257-
otherParent.setTouchDelegate(new TouchDelegate(rect, cbOther));
258-
}
259-
});
260104
}
261105
}
262106

@@ -288,13 +132,19 @@ public AdapterRule(Context context, View anchor) {
288132

289133
TypedValue typedValue = new TypedValue();
290134
context.getTheme().resolveAttribute(android.R.attr.listPreferredItemHeight, typedValue, true);
291-
int height = TypedValue.complexToDimensionPixelSize(typedValue.data,
135+
this.iconSize = TypedValue.complexToDimensionPixelSize(typedValue.data,
292136
context.getResources().getDisplayMetrics());
293-
this.iconSize = Math.round(height * context.getResources().getDisplayMetrics().density + 0.5f);
137+
138+
this.cachedSort = PreferenceManager.getDefaultSharedPreferences(context)
139+
.getString("sort", "trackers_week");
294140

295141
setHasStableIds(true);
296142
}
297143

144+
public void updateSortPreference(String sort) {
145+
this.cachedSort = sort;
146+
}
147+
298148
public void set(List<Rule> listRule) {
299149
listAll = listRule;
300150
List<Rule> oldList = listFiltered;
@@ -395,7 +245,7 @@ public void onBindViewHolder(final ViewHolder holder, int position) {
395245
holder.ivIcon.setImageResource(android.R.drawable.sym_def_app_icon);
396246
else {
397247
Uri uri = Uri.parse("android.resource://" + rule.packageName + "/" + rule.icon);
398-
GlideApp.with(holder.itemView.getContext())
248+
GlideApp.with(context)
399249
.applyDefaultRequestOptions(glideOptions)
400250
.load(uri)
401251
.override(iconSize, iconSize)
@@ -434,10 +284,7 @@ public void onBindViewHolder(final ViewHolder holder, int position) {
434284
setGreyscale(iv, !wasBlocked);
435285
});
436286

437-
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
438-
String sort = prefs.getString("sort", "trackers_week");
439-
440-
boolean pastWeekOnly = !("trackers_all".equals(sort));
287+
boolean pastWeekOnly = !("trackers_all".equals(cachedSort));
441288
final int trackerCount = rule.getTrackerCount(pastWeekOnly);
442289
if (trackerCount > 0) {
443290
holder.tvDetails.setVisibility(View.VISIBLE);
@@ -477,11 +324,8 @@ public void onBindViewHolder(final ViewHolder holder, int position) {
477324

478325
private void setGreyscale(ImageView iv, boolean on) {
479326
if (on) {
480-
ColorMatrix matrix = new ColorMatrix();
481-
matrix.setSaturation(0); // 0 means grayscale
482-
ColorMatrixColorFilter cf = new ColorMatrixColorFilter(matrix);
483-
iv.setColorFilter(cf);
484-
iv.setImageAlpha(128); // 128 = 0.5
327+
iv.setColorFilter(GREYSCALE_FILTER);
328+
iv.setImageAlpha(128);
485329
} else {
486330
iv.setColorFilter(null);
487331
iv.setImageAlpha(255);

app/src/main/java/eu/faircode/netguard/GlideHelper.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,4 @@
2525

2626
@GlideModule
2727
public final class GlideHelper extends AppGlideModule {
28-
}
28+
}

0 commit comments

Comments
 (0)