[app] Improve scope list performance

This commit is contained in:
tehcneko 2021-02-27 15:47:52 +08:00 committed by LoveSy
parent cb5c9ea4d2
commit 76cf325321
7 changed files with 79 additions and 35 deletions

View File

@ -32,11 +32,13 @@ import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.List; import java.util.List;
import io.github.lsposed.manager.ConfigManager;
import io.github.lsposed.manager.R; import io.github.lsposed.manager.R;
public class AppHelper { public class AppHelper {
public static final String SETTINGS_CATEGORY = "de.robv.android.xposed.category.MODULE_SETTINGS"; public static final String SETTINGS_CATEGORY = "de.robv.android.xposed.category.MODULE_SETTINGS";
private static List<PackageInfo> appList;
public static Intent getSettingsIntent(String packageName, PackageManager packageManager) { public static Intent getSettingsIntent(String packageName, PackageManager packageManager) {
// taken from // taken from
@ -113,4 +115,11 @@ public class AppHelper {
return (PackageInfo a, PackageInfo b) -> displayNameComparator.compare(a.applicationInfo, b.applicationInfo); return (PackageInfo a, PackageInfo b) -> displayNameComparator.compare(a.applicationInfo, b.applicationInfo);
} }
} }
public static List<PackageInfo> getAppList(boolean force) {
if (appList == null || force) {
appList = ConfigManager.getInstalledPackagesFromAllUsers(PackageManager.GET_META_DATA, true);
}
return appList;
}
} }

View File

@ -90,30 +90,32 @@ public class ScopeAdapter extends RecyclerView.Adapter<ScopeAdapter.ViewHolder>
private final SharedPreferences preferences; private final SharedPreferences preferences;
private final String modulePackageName; private final String modulePackageName;
private final String moduleName; private final String moduleName;
private final SwitchBar masterSwitch;
private final HashSet<ApplicationWithEquals> recommendedList = new HashSet<>(); private final HashSet<ApplicationWithEquals> recommendedList = new HashSet<>();
private final HashSet<ApplicationWithEquals> checkedList = new HashSet<>(); private final HashSet<ApplicationWithEquals> checkedList = new HashSet<>();
private final List<AppInfo> searchList = new ArrayList<>(); private final List<AppInfo> searchList = new ArrayList<>();
private List<AppInfo> showList = new ArrayList<>(); private final SwitchBar.OnCheckedChangeListener switchBarOnCheckedChangeListener = new SwitchBar.OnCheckedChangeListener() {
private ApplicationInfo selectedInfo; @Override
private boolean enabled = true; public boolean onCheckedChanged(SwitchBar view, boolean isChecked) {
public ScopeAdapter(AppListActivity activity, String moduleName, String modulePackageName, SwitchBar masterSwitch) {
this.activity = activity;
this.moduleName = moduleName;
this.modulePackageName = modulePackageName;
this.masterSwitch = masterSwitch;
preferences = App.getPreferences();
pm = activity.getPackageManager();
masterSwitch.setOnCheckedChangeListener((view, isChecked) -> {
if (!ModuleUtil.getInstance().setModuleEnabled(modulePackageName, isChecked)) { if (!ModuleUtil.getInstance().setModuleEnabled(modulePackageName, isChecked)) {
return false; return false;
} }
enabled = isChecked; enabled = isChecked;
notifyDataSetChanged(); notifyDataSetChanged();
return true; return true;
}); }
refresh(); };
private List<AppInfo> showList = new ArrayList<>();
private ApplicationInfo selectedInfo;
private boolean refreshing = false;
private boolean enabled = true;
public ScopeAdapter(AppListActivity activity, String moduleName, String modulePackageName) {
this.activity = activity;
this.moduleName = moduleName;
this.modulePackageName = modulePackageName;
preferences = App.getPreferences();
pm = activity.getPackageManager();
refresh(false);
} }
@NonNull @NonNull
@ -123,11 +125,8 @@ public class ScopeAdapter extends RecyclerView.Adapter<ScopeAdapter.ViewHolder>
return new ViewHolder(v); return new ViewHolder(v);
} }
private void loadApps() { private void loadApps(boolean force) {
enabled = ModuleUtil.getInstance().isModuleEnabled(modulePackageName); List<PackageInfo> appList = AppHelper.getAppList(force);
activity.runOnUiThread(() -> masterSwitch.setChecked(enabled));
List<PackageInfo> appList = ConfigManager.getInstalledPackagesFromAllUsers(PackageManager.GET_META_DATA, true);
checkedList.clear(); checkedList.clear();
recommendedList.clear(); recommendedList.clear();
searchList.clear(); searchList.clear();
@ -171,6 +170,9 @@ public class ScopeAdapter extends RecyclerView.Adapter<ScopeAdapter.ViewHolder>
ConfigManager.setModuleScope(modulePackageName, checkedList); ConfigManager.setModuleScope(modulePackageName, checkedList);
} }
showList = sortApps(searchList); showList = sortApps(searchList);
synchronized (this) {
refreshing = false;
}
activity.onDataReady(); activity.onDataReady();
} }
@ -267,6 +269,9 @@ public class ScopeAdapter extends RecyclerView.Adapter<ScopeAdapter.ViewHolder>
notifyDataSetChanged(); notifyDataSetChanged();
} }
return true; return true;
} else if (itemId == R.id.menu_refresh) {
refresh(true);
return true;
} else if (itemId == R.id.item_show_system) { } else if (itemId == R.id.item_show_system) {
item.setChecked(!item.isChecked()); item.setChecked(!item.isChecked());
preferences.edit().putBoolean("show_system_apps", item.isChecked()).apply(); preferences.edit().putBoolean("show_system_apps", item.isChecked()).apply();
@ -299,7 +304,7 @@ public class ScopeAdapter extends RecyclerView.Adapter<ScopeAdapter.ViewHolder>
} else if (!AppHelper.onOptionsItemSelected(item, preferences)) { } else if (!AppHelper.onOptionsItemSelected(item, preferences)) {
return false; return false;
} }
refresh(); refresh(false);
return true; return true;
} }
@ -481,8 +486,18 @@ public class ScopeAdapter extends RecyclerView.Adapter<ScopeAdapter.ViewHolder>
return showList.size(); return showList.size();
} }
public void refresh() { public void refresh(boolean force) {
AsyncTask.THREAD_POOL_EXECUTOR.execute(this::loadApps); synchronized (this) {
if (refreshing) {
return;
}
refreshing = true;
}
enabled = ModuleUtil.getInstance().isModuleEnabled(modulePackageName);
activity.binding.masterSwitch.setOnCheckedChangeListener(null);
activity.binding.masterSwitch.setChecked(enabled);
activity.binding.masterSwitch.setOnCheckedChangeListener(switchBarOnCheckedChangeListener);
AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> loadApps(force));
} }
protected void onCheckedChange(CompoundButton buttonView, boolean isChecked, AppInfo appInfo) { protected void onCheckedChange(CompoundButton buttonView, boolean isChecked, AppInfo appInfo) {
@ -556,7 +571,7 @@ public class ScopeAdapter extends RecyclerView.Adapter<ScopeAdapter.ViewHolder>
} }
public boolean onBackPressed() { public boolean onBackPressed() {
if (masterSwitch.isChecked() && checkedList.isEmpty()) { if (activity.binding.masterSwitch.isChecked() && checkedList.isEmpty()) {
AlertDialog.Builder builder = new AlertDialog.Builder(activity); AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle(R.string.use_recommended); builder.setTitle(R.string.use_recommended);
builder.setMessage(!recommendedList.isEmpty() ? R.string.no_scope_selected_has_recommended : R.string.no_scope_selected); builder.setMessage(!recommendedList.isEmpty() ? R.string.no_scope_selected_has_recommended : R.string.no_scope_selected);

View File

@ -23,8 +23,6 @@ package io.github.lsposed.manager.ui.activity;
import android.content.Intent; import android.content.Intent;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
@ -54,7 +52,6 @@ public class AppListActivity extends BaseActivity {
private SearchView.OnQueryTextListener searchListener; private SearchView.OnQueryTextListener searchListener;
public ActivityAppListBinding binding; public ActivityAppListBinding binding;
private final Handler handler = new Handler(Looper.getMainLooper());
public ActivityResultLauncher<String> backupLauncher; public ActivityResultLauncher<String> backupLauncher;
public ActivityResultLauncher<String[]> restoreLauncher; public ActivityResultLauncher<String[]> restoreLauncher;
@ -73,7 +70,7 @@ public class AppListActivity extends BaseActivity {
bar.setDisplayHomeAsUpEnabled(true); bar.setDisplayHomeAsUpEnabled(true);
bar.setTitle(moduleName); bar.setTitle(moduleName);
bar.setSubtitle(modulePackageName); bar.setSubtitle(modulePackageName);
scopeAdapter = new ScopeAdapter(this, moduleName, modulePackageName, binding.masterSwitch); scopeAdapter = new ScopeAdapter(this, moduleName, modulePackageName);
scopeAdapter.setHasStableIds(true); scopeAdapter.setHasStableIds(true);
binding.recyclerView.setAdapter(scopeAdapter); binding.recyclerView.setAdapter(scopeAdapter);
binding.recyclerView.setHasFixedSize(true); binding.recyclerView.setHasFixedSize(true);
@ -140,7 +137,7 @@ public class AppListActivity extends BaseActivity {
runOnUiThread(() -> { runOnUiThread(() -> {
alertDialog.dismiss(); alertDialog.dismiss();
makeSnackBar(success ? R.string.settings_restore_success : R.string.settings_restore_failed, Snackbar.LENGTH_SHORT); makeSnackBar(success ? R.string.settings_restore_success : R.string.settings_restore_failed, Snackbar.LENGTH_SHORT);
scopeAdapter.refresh(); scopeAdapter.refresh(false);
}); });
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
@ -167,9 +164,11 @@ public class AppListActivity extends BaseActivity {
} }
public void onDataReady() { public void onDataReady() {
handler.post(() -> binding.progress.setIndeterminate(false)); runOnUiThread(() -> {
String queryStr = searchView != null ? searchView.getQuery().toString() : ""; binding.progress.setIndeterminate(false);
runOnUiThread(() -> scopeAdapter.getFilter().filter(queryStr)); String queryStr = searchView != null ? searchView.getQuery().toString() : "";
scopeAdapter.getFilter().filter(queryStr);
});
} }
@Override @Override

View File

@ -85,7 +85,7 @@ public class ModulesActivity extends ListActivity implements ModuleUtil.ModuleLi
@Override @Override
protected void onResume() { protected void onResume() {
super.onResume(); super.onResume();
adapter.refresh(); adapter.refresh(true);
} }
@Override @Override
@ -105,6 +105,15 @@ public class ModulesActivity extends ListActivity implements ModuleUtil.ModuleLi
adapter.refresh(); adapter.refresh();
} }
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
int itemId = item.getItemId();
if (itemId == R.id.menu_refresh) {
adapter.refresh(true);
}
return super.onOptionsItemSelected(item);
}
@Override @Override
public boolean onContextItemSelected(@NonNull MenuItem item) { public boolean onContextItemSelected(@NonNull MenuItem item) {
ModuleUtil.InstalledModule module = ModuleUtil.getInstance().getModule(selectedPackageName); ModuleUtil.InstalledModule module = ModuleUtil.getInstance().getModule(selectedPackageName);

View File

@ -22,7 +22,6 @@ package io.github.lsposed.manager.ui.activity;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
@ -228,7 +227,7 @@ public class SettingsActivity extends BaseActivity {
new AlertDialog.Builder(requireActivity()) new AlertDialog.Builder(requireActivity())
.setCancelable(true) .setCancelable(true)
.setMessage(R.string.settings_sandhook_deprecated_warning) .setMessage(R.string.settings_sandhook_deprecated_warning)
.setPositiveButton(android.R.string.ok, (di, i) -> {}) .setPositiveButton(android.R.string.ok, null)
.show(); .show();
} }
return ConfigManager.setVariant(Integer.parseInt((String) newValue)); return ConfigManager.setVariant(Integer.parseInt((String) newValue));

View File

@ -33,6 +33,12 @@
android:icon="@drawable/ic_settings" android:icon="@drawable/ic_settings"
app:showAsAction="ifRoom" /> app:showAsAction="ifRoom" />
<item
android:id="@+id/menu_refresh"
android:title="@string/refresh"
android:icon="@drawable/ic_refresh"
app:showAsAction="ifRoom" />
<item <item
android:id="@+id/use_recommended" android:id="@+id/use_recommended"
android:title="@string/use_recommended" /> android:title="@string/use_recommended" />

View File

@ -26,4 +26,11 @@
android:id="@+id/menu_search" android:id="@+id/menu_search"
app:actionViewClass="androidx.appcompat.widget.SearchView" app:actionViewClass="androidx.appcompat.widget.SearchView"
app:showAsAction="ifRoom" /> app:showAsAction="ifRoom" />
<item
android:id="@+id/menu_refresh"
android:title="@string/refresh"
android:icon="@drawable/ic_refresh"
app:showAsAction="ifRoom" />
</menu> </menu>