From 2a7061957733b57a547433c26159f6aa5edbc06e Mon Sep 17 00:00:00 2001 From: tonymanou Date: Sun, 8 Jan 2017 14:41:19 +0100 Subject: [PATCH] Improve magisk hide app list's adapter, better thread safety --- .../topjohnwu/magisk/MagiskHideFragment.java | 42 +++---------- .../magisk/adapters/ApplicationAdapter.java | 62 ++++++++++++++++--- .../com/topjohnwu/magisk/utils/Async.java | 34 ++++++---- .../magisk/utils/CallbackHandler.java | 12 ++++ .../com/topjohnwu/magisk/utils/Utils.java | 5 ++ 5 files changed, 100 insertions(+), 55 deletions(-) diff --git a/app/src/main/java/com/topjohnwu/magisk/MagiskHideFragment.java b/app/src/main/java/com/topjohnwu/magisk/MagiskHideFragment.java index 1e686f931..041c239b4 100644 --- a/app/src/main/java/com/topjohnwu/magisk/MagiskHideFragment.java +++ b/app/src/main/java/com/topjohnwu/magisk/MagiskHideFragment.java @@ -1,7 +1,6 @@ package com.topjohnwu.magisk; import android.app.Fragment; -import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.os.Bundle; import android.support.annotation.Nullable; @@ -20,7 +19,6 @@ import com.topjohnwu.magisk.utils.Async; import com.topjohnwu.magisk.utils.CallbackHandler; import com.topjohnwu.magisk.utils.Logger; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -32,10 +30,8 @@ public class MagiskHideFragment extends Fragment implements CallbackHandler.Even @BindView(R.id.swipeRefreshLayout) SwipeRefreshLayout mSwipeRefreshLayout; @BindView(R.id.recyclerView) RecyclerView recyclerView; - public static List listApps, fListApps = new ArrayList<>(); - public static List hideList = new ArrayList<>(); // Don't show in list... - public static final List blacklist = Arrays.asList( + public static final List BLACKLIST = Arrays.asList( "android", "com.topjohnwu.magisk", "com.google.android.gms", @@ -46,7 +42,7 @@ public class MagiskHideFragment extends Fragment implements CallbackHandler.Even private PackageManager packageManager; private View mView; - private ApplicationAdapter appAdapter = new ApplicationAdapter(fListApps, hideList); + private ApplicationAdapter appAdapter = new ApplicationAdapter(); private SearchView.OnQueryTextListener searchListener; @@ -69,13 +65,13 @@ public class MagiskHideFragment extends Fragment implements CallbackHandler.Even searchListener = new SearchView.OnQueryTextListener() { @Override public boolean onQueryTextSubmit(String query) { - new FilterApps().exec(query); + appAdapter.filter(query); return false; } @Override public boolean onQueryTextChange(String newText) { - new FilterApps().exec(newText); + appAdapter.filter(newText); return false; } }; @@ -111,33 +107,9 @@ public class MagiskHideFragment extends Fragment implements CallbackHandler.Even @Override public void onTrigger(CallbackHandler.Event event) { Logger.dev("MagiskHideFragment: UI refresh"); - updateUI(); - } - - private class FilterApps extends Async.NormalTask { - @Override - protected Void doInBackground(String... strings) { - String newText = strings[0]; - fListApps.clear(); - for (ApplicationInfo info : listApps) { - if (info.loadLabel(packageManager).toString().toLowerCase().contains(newText.toLowerCase()) - || info.packageName.toLowerCase().contains(newText.toLowerCase())) { - fListApps.add(info); - } - } - return null; - } - - @Override - protected void onPostExecute(Void v) { - appAdapter.notifyDataSetChanged(); - } - } - - private void updateUI() { - appAdapter.notifyDataSetChanged(); + Async.LoadApps.Result result = (Async.LoadApps.Result) event.getResult(); + appAdapter.setLists(result.listApps, result.hideList); recyclerView.setVisibility(View.VISIBLE); mSwipeRefreshLayout.setRefreshing(false); } - -} \ No newline at end of file +} diff --git a/app/src/main/java/com/topjohnwu/magisk/adapters/ApplicationAdapter.java b/app/src/main/java/com/topjohnwu/magisk/adapters/ApplicationAdapter.java index 841e1a50d..c47709fad 100644 --- a/app/src/main/java/com/topjohnwu/magisk/adapters/ApplicationAdapter.java +++ b/app/src/main/java/com/topjohnwu/magisk/adapters/ApplicationAdapter.java @@ -10,12 +10,16 @@ import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.widget.CheckBox; +import android.widget.Filter; import android.widget.ImageView; import android.widget.TextView; import com.topjohnwu.magisk.R; import com.topjohnwu.magisk.utils.Async; +import com.topjohnwu.magisk.utils.Utils; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; import butterknife.BindView; @@ -23,16 +27,21 @@ import butterknife.ButterKnife; public class ApplicationAdapter extends RecyclerView.Adapter { - private List mList; + private List mOriginalList, mList; private List mHideList; private Context context; private PackageManager packageManager; + private ApplicationFilter filter; + public ApplicationAdapter() { + mOriginalList = mList = Collections.emptyList(); + mHideList = Collections.emptyList(); + } - - public ApplicationAdapter(List list, List hideList) { - mList = list; - mHideList = hideList; + public void setLists(List listApps, List hideList) { + mOriginalList = mList = Collections.unmodifiableList(listApps); + mHideList = new ArrayList<>(hideList); + notifyDataSetChanged(); } @Override @@ -78,7 +87,14 @@ public class ApplicationAdapter extends RecyclerView.Adapter filteredApps; + if (constraint == null || constraint.length() == 0) { + filteredApps = mOriginalList; + } else { + filteredApps = new ArrayList<>(); + String filter = constraint.toString().toLowerCase(); + for (ApplicationInfo info : mOriginalList) { + if (Utils.lowercaseContains(info.loadLabel(packageManager), filter) + || Utils.lowercaseContains(info.packageName, filter)) { + filteredApps.add(info); + } + } + } + + FilterResults results = new FilterResults(); + results.values = filteredApps; + results.count = filteredApps.size(); + return results; + } + + @SuppressWarnings("unchecked") + @Override + protected void publishResults(CharSequence constraint, FilterResults results) { + mList = (List) results.values; + notifyDataSetChanged(); + } + } +} diff --git a/app/src/main/java/com/topjohnwu/magisk/utils/Async.java b/app/src/main/java/com/topjohnwu/magisk/utils/Async.java index dbb0c2f90..5d7041e15 100644 --- a/app/src/main/java/com/topjohnwu/magisk/utils/Async.java +++ b/app/src/main/java/com/topjohnwu/magisk/utils/Async.java @@ -117,7 +117,7 @@ public class Async { } } - public static class LoadApps extends RootTask { + public static class LoadApps extends RootTask { private PackageManager pm; @@ -126,25 +126,33 @@ public class Async { } @Override - protected Void doInBackground(Void... voids) { - MagiskHideFragment.hideList.clear(); - MagiskHideFragment.fListApps.clear(); - MagiskHideFragment.listApps = pm.getInstalledApplications(PackageManager.GET_META_DATA); - for (Iterator i = MagiskHideFragment.listApps.iterator(); i.hasNext(); ) { + protected Result doInBackground(Void... voids) { + List listApps = pm.getInstalledApplications(PackageManager.GET_META_DATA); + for (Iterator i = listApps.iterator(); i.hasNext(); ) { ApplicationInfo info = i.next(); - if (MagiskHideFragment.blacklist.contains(info.packageName) || !info.enabled) + if (MagiskHideFragment.BLACKLIST.contains(info.packageName) || !info.enabled) i.remove(); } - Collections.sort(MagiskHideFragment.listApps, (a, b) -> a.loadLabel(pm).toString().toLowerCase() + Collections.sort(listApps, (a, b) -> a.loadLabel(pm).toString().toLowerCase() .compareTo(b.loadLabel(pm).toString().toLowerCase())); - MagiskHideFragment.hideList.addAll(Shell.su(Async.MAGISK_HIDE_PATH + "list")); - MagiskHideFragment.fListApps.addAll(MagiskHideFragment.listApps); - return null; + List hideList = Shell.su(Async.MAGISK_HIDE_PATH + "list"); + return new Result(listApps, hideList); } @Override - protected void onPostExecute(Void aVoid) { - MagiskHideFragment.packageLoadDone.trigger(); + protected void onPostExecute(Result result) { + MagiskHideFragment.packageLoadDone.trigger(result); + } + + public static class Result { + + public final List listApps; + public final List hideList; + + Result(List listApps, List hideList) { + this.listApps = listApps; + this.hideList = hideList; + } } } diff --git a/app/src/main/java/com/topjohnwu/magisk/utils/CallbackHandler.java b/app/src/main/java/com/topjohnwu/magisk/utils/CallbackHandler.java index 454146a11..6d70ede25 100644 --- a/app/src/main/java/com/topjohnwu/magisk/utils/CallbackHandler.java +++ b/app/src/main/java/com/topjohnwu/magisk/utils/CallbackHandler.java @@ -33,11 +33,23 @@ public class CallbackHandler { } public static class Event { + public boolean isTriggered = false; + private Object result; + public void trigger() { + trigger(null); + } + + public void trigger(Object result) { + this.result = result; isTriggered = true; triggerCallback(this); } + + public Object getResult() { + return result; + } } public interface EventListener { diff --git a/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java b/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java index 5118ae54e..eafe1df4a 100644 --- a/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java +++ b/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java @@ -9,6 +9,7 @@ import android.content.pm.PackageManager; import android.net.Uri; import android.os.Environment; import android.support.v4.app.ActivityCompat; +import android.text.TextUtils; import android.util.Base64; import android.widget.Toast; @@ -144,6 +145,10 @@ public class Utils { } } + public static boolean lowercaseContains(CharSequence string, CharSequence nonNullLowercaseSearch) { + return !TextUtils.isEmpty(string) && string.toString().toLowerCase().contains(nonNullLowercaseSearch); + } + public static class ByteArrayInOutStream extends ByteArrayOutputStream { public ByteArrayInputStream getInputStream() { ByteArrayInputStream in = new ByteArrayInputStream(buf, 0, count);