[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.List;
import io.github.lsposed.manager.ConfigManager;
import io.github.lsposed.manager.R;
public class AppHelper {
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) {
// taken from
@ -113,4 +115,11 @@ public class AppHelper {
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 String modulePackageName;
private final String moduleName;
private final SwitchBar masterSwitch;
private final HashSet<ApplicationWithEquals> recommendedList = new HashSet<>();
private final HashSet<ApplicationWithEquals> checkedList = new HashSet<>();
private final List<AppInfo> searchList = new ArrayList<>();
private List<AppInfo> showList = new ArrayList<>();
private ApplicationInfo selectedInfo;
private boolean enabled = true;
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) -> {
private final SwitchBar.OnCheckedChangeListener switchBarOnCheckedChangeListener = new SwitchBar.OnCheckedChangeListener() {
@Override
public boolean onCheckedChanged(SwitchBar view, boolean isChecked) {
if (!ModuleUtil.getInstance().setModuleEnabled(modulePackageName, isChecked)) {
return false;
}
enabled = isChecked;
notifyDataSetChanged();
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
@ -123,11 +125,8 @@ public class ScopeAdapter extends RecyclerView.Adapter<ScopeAdapter.ViewHolder>
return new ViewHolder(v);
}
private void loadApps() {
enabled = ModuleUtil.getInstance().isModuleEnabled(modulePackageName);
activity.runOnUiThread(() -> masterSwitch.setChecked(enabled));
List<PackageInfo> appList = ConfigManager.getInstalledPackagesFromAllUsers(PackageManager.GET_META_DATA, true);
private void loadApps(boolean force) {
List<PackageInfo> appList = AppHelper.getAppList(force);
checkedList.clear();
recommendedList.clear();
searchList.clear();
@ -171,6 +170,9 @@ public class ScopeAdapter extends RecyclerView.Adapter<ScopeAdapter.ViewHolder>
ConfigManager.setModuleScope(modulePackageName, checkedList);
}
showList = sortApps(searchList);
synchronized (this) {
refreshing = false;
}
activity.onDataReady();
}
@ -267,6 +269,9 @@ public class ScopeAdapter extends RecyclerView.Adapter<ScopeAdapter.ViewHolder>
notifyDataSetChanged();
}
return true;
} else if (itemId == R.id.menu_refresh) {
refresh(true);
return true;
} else if (itemId == R.id.item_show_system) {
item.setChecked(!item.isChecked());
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)) {
return false;
}
refresh();
refresh(false);
return true;
}
@ -481,8 +486,18 @@ public class ScopeAdapter extends RecyclerView.Adapter<ScopeAdapter.ViewHolder>
return showList.size();
}
public void refresh() {
AsyncTask.THREAD_POOL_EXECUTOR.execute(this::loadApps);
public void refresh(boolean force) {
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) {
@ -556,7 +571,7 @@ public class ScopeAdapter extends RecyclerView.Adapter<ScopeAdapter.ViewHolder>
}
public boolean onBackPressed() {
if (masterSwitch.isChecked() && checkedList.isEmpty()) {
if (activity.binding.masterSwitch.isChecked() && checkedList.isEmpty()) {
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle(R.string.use_recommended);
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.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.Menu;
import android.view.MenuItem;
@ -54,7 +52,6 @@ public class AppListActivity extends BaseActivity {
private SearchView.OnQueryTextListener searchListener;
public ActivityAppListBinding binding;
private final Handler handler = new Handler(Looper.getMainLooper());
public ActivityResultLauncher<String> backupLauncher;
public ActivityResultLauncher<String[]> restoreLauncher;
@ -73,7 +70,7 @@ public class AppListActivity extends BaseActivity {
bar.setDisplayHomeAsUpEnabled(true);
bar.setTitle(moduleName);
bar.setSubtitle(modulePackageName);
scopeAdapter = new ScopeAdapter(this, moduleName, modulePackageName, binding.masterSwitch);
scopeAdapter = new ScopeAdapter(this, moduleName, modulePackageName);
scopeAdapter.setHasStableIds(true);
binding.recyclerView.setAdapter(scopeAdapter);
binding.recyclerView.setHasFixedSize(true);
@ -140,7 +137,7 @@ public class AppListActivity extends BaseActivity {
runOnUiThread(() -> {
alertDialog.dismiss();
makeSnackBar(success ? R.string.settings_restore_success : R.string.settings_restore_failed, Snackbar.LENGTH_SHORT);
scopeAdapter.refresh();
scopeAdapter.refresh(false);
});
} catch (Exception e) {
e.printStackTrace();
@ -167,9 +164,11 @@ public class AppListActivity extends BaseActivity {
}
public void onDataReady() {
handler.post(() -> binding.progress.setIndeterminate(false));
String queryStr = searchView != null ? searchView.getQuery().toString() : "";
runOnUiThread(() -> scopeAdapter.getFilter().filter(queryStr));
runOnUiThread(() -> {
binding.progress.setIndeterminate(false);
String queryStr = searchView != null ? searchView.getQuery().toString() : "";
scopeAdapter.getFilter().filter(queryStr);
});
}
@Override

View File

@ -85,7 +85,7 @@ public class ModulesActivity extends ListActivity implements ModuleUtil.ModuleLi
@Override
protected void onResume() {
super.onResume();
adapter.refresh();
adapter.refresh(true);
}
@Override
@ -105,6 +105,15 @@ public class ModulesActivity extends ListActivity implements ModuleUtil.ModuleLi
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
public boolean onContextItemSelected(@NonNull MenuItem item) {
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.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
@ -228,7 +227,7 @@ public class SettingsActivity extends BaseActivity {
new AlertDialog.Builder(requireActivity())
.setCancelable(true)
.setMessage(R.string.settings_sandhook_deprecated_warning)
.setPositiveButton(android.R.string.ok, (di, i) -> {})
.setPositiveButton(android.R.string.ok, null)
.show();
}
return ConfigManager.setVariant(Integer.parseInt((String) newValue));

View File

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

View File

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