From 2fa5e4679f7638774614fb780774e1049b1c11a6 Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Sun, 25 Dec 2016 15:11:59 +0800 Subject: [PATCH] CallbackHandler to manage asyncs --- .../com/topjohnwu/magisk/MainActivity.java | 2 - .../com/topjohnwu/magisk/ModulesFragment.java | 35 ++++---- .../com/topjohnwu/magisk/ReposFragment.java | 36 ++++---- .../com/topjohnwu/magisk/SplashActivity.java | 13 +-- .../com/topjohnwu/magisk/StatusFragment.java | 85 +++++++------------ .../com/topjohnwu/magisk/utils/Async.java | 43 ++++------ .../magisk/utils/CallbackHandler.java | 43 ++++++++++ .../magisk/utils/SafetyNetHelper.java | 4 +- 8 files changed, 129 insertions(+), 132 deletions(-) create mode 100644 app/src/main/java/com/topjohnwu/magisk/utils/CallbackHandler.java diff --git a/app/src/main/java/com/topjohnwu/magisk/MainActivity.java b/app/src/main/java/com/topjohnwu/magisk/MainActivity.java index cde89a1bd..218c64766 100644 --- a/app/src/main/java/com/topjohnwu/magisk/MainActivity.java +++ b/app/src/main/java/com/topjohnwu/magisk/MainActivity.java @@ -12,7 +12,6 @@ import android.preference.PreferenceManager; import android.support.annotation.IdRes; import android.support.annotation.NonNull; import android.support.design.widget.NavigationView; -import android.support.design.widget.Snackbar; import android.support.v4.app.ActivityCompat; import android.support.v4.view.GravityCompat; import android.support.v4.widget.DrawerLayout; @@ -24,7 +23,6 @@ import android.view.MenuItem; import android.view.View; import com.topjohnwu.magisk.utils.Logger; -import com.topjohnwu.magisk.utils.Shell; import butterknife.BindView; import butterknife.ButterKnife; diff --git a/app/src/main/java/com/topjohnwu/magisk/ModulesFragment.java b/app/src/main/java/com/topjohnwu/magisk/ModulesFragment.java index cd390892f..6eb40323e 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ModulesFragment.java +++ b/app/src/main/java/com/topjohnwu/magisk/ModulesFragment.java @@ -19,6 +19,7 @@ import com.github.clans.fab.FloatingActionButton; import com.topjohnwu.magisk.adapters.ModulesAdapter; import com.topjohnwu.magisk.module.Module; import com.topjohnwu.magisk.utils.Async; +import com.topjohnwu.magisk.utils.CallbackHandler; import com.topjohnwu.magisk.utils.Logger; import com.topjohnwu.magisk.utils.ModuleHelper; @@ -28,7 +29,10 @@ import java.util.List; import butterknife.BindView; import butterknife.ButterKnife; -public class ModulesFragment extends Fragment { +public class ModulesFragment extends Fragment implements CallbackHandler.EventListener { + + public static final CallbackHandler.Event moduleLoadDone = new CallbackHandler.Event(); + private static final int FETCH_ZIP_CODE = 2; @BindView(R.id.swipeRefreshLayout) SwipeRefreshLayout mSwipeRefreshLayout; @@ -36,10 +40,8 @@ public class ModulesFragment extends Fragment { @BindView(R.id.empty_rv) TextView emptyTv; @BindView(R.id.fab) FloatingActionButton fabio; - private SharedPreferences prefs; private List listModules = new ArrayList<>(); private View mView; - private SharedPreferences.OnSharedPreferenceChangeListener listener; @Nullable @Override @@ -53,30 +55,24 @@ public class ModulesFragment extends Fragment { startActivityForResult(intent, FETCH_ZIP_CODE); }); - prefs = PreferenceManager.getDefaultSharedPreferences(getActivity()); - mSwipeRefreshLayout.setOnRefreshListener(() -> { recyclerView.setVisibility(View.GONE); - prefs.edit().putBoolean("module_done", false).apply(); - new Async.LoadModules(prefs).exec(); + new Async.LoadModules().exec(); }); - if (prefs.getBoolean("module_done", false)) { + if (moduleLoadDone.isTriggered) { updateUI(); } - listener = (pref, s) -> { - if (s.equals("module_done")) { - if (pref.getBoolean(s, false)) { - Logger.dev("ModulesFragment: UI refresh triggered"); - updateUI(); - } - } - }; - return mView; } + @Override + public void onTrigger(CallbackHandler.Event event) { + Logger.dev("ModulesFragment: UI refresh triggered"); + updateUI(); + } + @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == FETCH_ZIP_CODE && resultCode == Activity.RESULT_OK && data != null) { @@ -91,14 +87,14 @@ public class ModulesFragment extends Fragment { public void onResume() { super.onResume(); mView = this.getView(); - prefs.registerOnSharedPreferenceChangeListener(listener); + CallbackHandler.register(moduleLoadDone, this); getActivity().setTitle(R.string.modules); } @Override public void onDestroy() { super.onDestroy(); - prefs.unregisterOnSharedPreferenceChangeListener(listener); + CallbackHandler.unRegister(moduleLoadDone, this); } private void updateUI() { @@ -113,5 +109,4 @@ public class ModulesFragment extends Fragment { } mSwipeRefreshLayout.setRefreshing(false); } - } diff --git a/app/src/main/java/com/topjohnwu/magisk/ReposFragment.java b/app/src/main/java/com/topjohnwu/magisk/ReposFragment.java index cc1513f43..e3cc45314 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ReposFragment.java +++ b/app/src/main/java/com/topjohnwu/magisk/ReposFragment.java @@ -20,6 +20,7 @@ import com.topjohnwu.magisk.adapters.ReposAdapter; import com.topjohnwu.magisk.adapters.SimpleSectionedRecyclerViewAdapter; import com.topjohnwu.magisk.module.Repo; import com.topjohnwu.magisk.utils.Async; +import com.topjohnwu.magisk.utils.CallbackHandler; import com.topjohnwu.magisk.utils.Logger; import com.topjohnwu.magisk.utils.ModuleHelper; @@ -29,7 +30,9 @@ import java.util.List; import butterknife.BindView; import butterknife.ButterKnife; -public class ReposFragment extends Fragment { +public class ReposFragment extends Fragment implements CallbackHandler.EventListener { + + public static final CallbackHandler.Event repoLoadDone = new CallbackHandler.Event(); @BindView(R.id.recyclerView) RecyclerView recyclerView; @BindView(R.id.empty_rv) TextView emptyTv; @@ -44,8 +47,6 @@ public class ReposFragment extends Fragment { private SimpleSectionedRecyclerViewAdapter mSectionedAdapter; - private SharedPreferences.OnSharedPreferenceChangeListener listener; - private SharedPreferences prefs; private SearchView.OnQueryTextListener searchListener; @Nullable @@ -57,35 +58,23 @@ public class ReposFragment extends Fragment { ButterKnife.bind(this, view); mSectionedAdapter = new - SimpleSectionedRecyclerViewAdapter(getActivity(), R.layout.section, R.id.section_text, new ReposAdapter(fUpdateRepos, fInstalledRepos, fOthersRepos)); + SimpleSectionedRecyclerViewAdapter(getActivity(), R.layout.section, + R.id.section_text, new ReposAdapter(fUpdateRepos, fInstalledRepos, fOthersRepos)); recyclerView.setAdapter(mSectionedAdapter); mSwipeRefreshLayout.setRefreshing(true); - prefs = PreferenceManager.getDefaultSharedPreferences(getActivity()); - mSwipeRefreshLayout.setOnRefreshListener(() -> { recyclerView.setVisibility(View.GONE); - prefs.edit().putBoolean("repo_done", false).apply(); new Async.LoadRepos(getActivity()).exec(); }); - if (prefs.getBoolean("repo_done", false)) { + if (repoLoadDone.isTriggered) { reloadRepos(); updateUI(); } - listener = (pref, s) -> { - if (s.equals("repo_done")) { - if (pref.getBoolean(s, false)) { - Logger.dev("ReposFragment: UI refresh triggered"); - reloadRepos(); - updateUI(); - } - } - }; - searchListener = new SearchView.OnQueryTextListener() { @Override public boolean onQueryTextSubmit(String query) { @@ -102,6 +91,13 @@ public class ReposFragment extends Fragment { return view; } + @Override + public void onTrigger(CallbackHandler.Event event) { + Logger.dev("ReposFragment: UI refresh triggered"); + reloadRepos(); + updateUI(); + } + @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { inflater.inflate(R.menu.menu_repo, menu); @@ -113,14 +109,14 @@ public class ReposFragment extends Fragment { public void onResume() { super.onResume(); setHasOptionsMenu(true); - prefs.registerOnSharedPreferenceChangeListener(listener); + CallbackHandler.register(repoLoadDone, this); getActivity().setTitle(R.string.downloads); } @Override public void onDestroy() { super.onDestroy(); - prefs.unregisterOnSharedPreferenceChangeListener(listener); + CallbackHandler.unRegister(repoLoadDone, this); } private void reloadRepos() { diff --git a/app/src/main/java/com/topjohnwu/magisk/SplashActivity.java b/app/src/main/java/com/topjohnwu/magisk/SplashActivity.java index 3367b1da5..649585600 100644 --- a/app/src/main/java/com/topjohnwu/magisk/SplashActivity.java +++ b/app/src/main/java/com/topjohnwu/magisk/SplashActivity.java @@ -12,13 +12,11 @@ import com.topjohnwu.magisk.utils.Utils; public class SplashActivity extends AppCompatActivity { - private SharedPreferences prefs; - @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - prefs = PreferenceManager.getDefaultSharedPreferences(getApplication()); + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getApplication()); if (prefs.getString("theme", "").equals("Dark")) { setTheme(R.style.AppTheme_dh); } @@ -28,17 +26,14 @@ public class SplashActivity extends AppCompatActivity { // Initialize prefs prefs.edit() - .putBoolean("module_done", false) - .putBoolean("repo_done", false) - .putBoolean("update_check_done", false) .putBoolean("magiskhide", Utils.itemExist(false, "/magisk/.core/magiskhide/enable")) .putBoolean("busybox", Utils.commandExists("busybox")) .putBoolean("hosts", Utils.itemExist(false, "/magisk/.core/hosts")) .apply(); - new Async.CheckUpdates(prefs).exec(); - - new Async.LoadModules(prefs) { + new Async.CheckUpdates().exec(); + Async.checkSafetyNet(getApplicationContext()); + new Async.LoadModules() { @Override protected void onPostExecute(Void v) { super.onPostExecute(v); diff --git a/app/src/main/java/com/topjohnwu/magisk/StatusFragment.java b/app/src/main/java/com/topjohnwu/magisk/StatusFragment.java index 7f43ca8e6..b87f3c8e8 100644 --- a/app/src/main/java/com/topjohnwu/magisk/StatusFragment.java +++ b/app/src/main/java/com/topjohnwu/magisk/StatusFragment.java @@ -2,14 +2,10 @@ package com.topjohnwu.magisk; import android.app.Fragment; import android.app.FragmentTransaction; -import android.content.Intent; import android.content.SharedPreferences; -import android.net.Uri; -import android.os.Build; import android.os.Bundle; import android.preference.PreferenceManager; import android.support.annotation.Nullable; -import android.support.v4.content.FileProvider; import android.support.v4.widget.SwipeRefreshLayout; import android.support.v7.app.AlertDialog; import android.view.LayoutInflater; @@ -19,28 +15,25 @@ import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.TextView; -import com.topjohnwu.magisk.receivers.DownloadReceiver; import com.topjohnwu.magisk.utils.Async; +import com.topjohnwu.magisk.utils.CallbackHandler; import com.topjohnwu.magisk.utils.Logger; -import com.topjohnwu.magisk.utils.SafetyNetHelper; import com.topjohnwu.magisk.utils.Shell; -import com.topjohnwu.magisk.utils.Utils; -import com.topjohnwu.magisk.utils.ZipUtils; -import java.io.File; import java.util.List; import butterknife.BindColor; import butterknife.BindView; import butterknife.ButterKnife; -public class StatusFragment extends Fragment { +public class StatusFragment extends Fragment implements CallbackHandler.EventListener { - public static int remoteAppVersionCode = -1; public static double magiskVersion, remoteMagiskVersion = -1; - public static String magiskVersionString, magiskLink, magiskChangelog, appLink, appChangelog, remoteAppVersion; + public static String magiskVersionString, magiskLink, magiskChangelog; + public static int SNCheckResult = -1; - private static int lastSNCheckResult = -1; + public static final CallbackHandler.Event updateCheckDone = new CallbackHandler.Event(); + public static final CallbackHandler.Event safetyNetDone = new CallbackHandler.Event(); @BindView(R.id.swipeRefreshLayout) SwipeRefreshLayout mSwipeRefreshLayout; @@ -69,16 +62,13 @@ public class StatusFragment extends Fragment { private AlertDialog.Builder builder; - private SharedPreferences prefs; - private SharedPreferences.OnSharedPreferenceChangeListener listener; - @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View v = inflater.inflate(R.layout.status_fragment, container, false); ButterKnife.bind(this, v); - prefs = PreferenceManager.getDefaultSharedPreferences(getActivity()); + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity()); String theme = prefs.getString("theme", ""); if (theme.equals("Dark")) { @@ -88,34 +78,26 @@ public class StatusFragment extends Fragment { } mSwipeRefreshLayout.setOnRefreshListener(() -> { - prefs.edit().putBoolean("update_check_done", false).apply(); - magiskStatusContainer.setBackgroundColor(trans); magiskStatusIcon.setImageResource(0); magiskUpdateText.setText(R.string.checking_for_updates); magiskCheckUpdatesProgress.setVisibility(View.VISIBLE); - new Async.CheckUpdates(prefs).exec(); - checkSafetyNet(); + safetyNetProgress.setVisibility(View.VISIBLE); + safetyNetContainer.setBackgroundColor(trans); + safetyNetIcon.setImageResource(0); + safetyNetStatusText.setText(R.string.checking_safetyNet_status); + + updateUI(); + new Async.CheckUpdates().exec(); + Async.checkSafetyNet(getActivity()); }); - listener = (pref, s) -> { - if (s.equals("update_check_done")) { - if (pref.getBoolean(s, false)) { - Logger.dev("StatusFragment: UI refresh triggered"); - updateUI(); - updateCheckUI(); - } - } - }; - updateUI(); - if (prefs.getBoolean("update_check_done", false)) { + if (updateCheckDone.isTriggered) { updateCheckUI(); } - if (lastSNCheckResult == -1) { - checkSafetyNet(); - } else { + if (safetyNetDone.isTriggered) { updateSafetyNetUI(); } @@ -139,17 +121,30 @@ public class StatusFragment extends Fragment { return v; } + @Override + public void onTrigger(CallbackHandler.Event event) { + if (event == updateCheckDone) { + Logger.dev("StatusFragment: Update Check UI refresh triggered"); + updateCheckUI(); + } else if (event == safetyNetDone) { + Logger.dev("StatusFragment: SafetyNet UI refresh triggered"); + updateSafetyNetUI(); + } + } + @Override public void onResume() { super.onResume(); - prefs.registerOnSharedPreferenceChangeListener(listener); + CallbackHandler.register(updateCheckDone, this); + CallbackHandler.register(safetyNetDone, this); getActivity().setTitle(R.string.status); } @Override public void onDestroy() { super.onDestroy(); - prefs.unregisterOnSharedPreferenceChangeListener(listener); + CallbackHandler.unRegister(updateCheckDone, this); + CallbackHandler.unRegister(safetyNetDone, this); } private void updateUI() { @@ -227,7 +222,7 @@ public class StatusFragment extends Fragment { private void updateSafetyNetUI() { int image, color; safetyNetProgress.setVisibility(View.GONE); - switch (lastSNCheckResult) { + switch (SNCheckResult) { case -1: color = colorNeutral; image = R.drawable.ic_help; @@ -249,19 +244,5 @@ public class StatusFragment extends Fragment { safetyNetStatusText.setTextColor(color); safetyNetIcon.setImageResource(image); } - - private void checkSafetyNet() { - safetyNetProgress.setVisibility(View.VISIBLE); - safetyNetContainer.setBackgroundColor(trans); - safetyNetIcon.setImageResource(0); - safetyNetStatusText.setText(R.string.checking_safetyNet_status); - new SafetyNetHelper(getActivity()) { - @Override - public void handleResults(int i) { - lastSNCheckResult = i; - updateSafetyNetUI(); - } - }.requestTest(); - } } 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 63593f5e1..f9db42a73 100644 --- a/app/src/main/java/com/topjohnwu/magisk/utils/Async.java +++ b/app/src/main/java/com/topjohnwu/magisk/utils/Async.java @@ -12,7 +12,9 @@ import android.support.v7.app.AlertDialog; import android.util.Log; import android.widget.Toast; +import com.topjohnwu.magisk.ModulesFragment; import com.topjohnwu.magisk.R; +import com.topjohnwu.magisk.ReposFragment; import com.topjohnwu.magisk.StatusFragment; import org.json.JSONException; @@ -48,12 +50,6 @@ public class Async { public static class CheckUpdates extends NormalTask { - private SharedPreferences mPrefs; - - public CheckUpdates(SharedPreferences prefs) { - mPrefs = prefs; - } - @Override protected Void doInBackground(Void... voids) { String jsonStr = WebRequest.makeWebServiceCall(UPDATE_JSON, WebRequest.GET); @@ -61,37 +57,33 @@ public class Async { JSONObject json = new JSONObject(jsonStr); JSONObject magisk = json.getJSONObject("magisk"); - JSONObject app = json.getJSONObject("app"); StatusFragment.remoteMagiskVersion = magisk.getDouble("versionCode"); StatusFragment.magiskLink = magisk.getString("link"); StatusFragment.magiskChangelog = magisk.getString("changelog"); - StatusFragment.remoteAppVersion = app.getString("version"); - StatusFragment.remoteAppVersionCode = app.getInt("versionCode"); - StatusFragment.appLink = app.getString("link"); - StatusFragment.appChangelog = app.getString("changelog"); - - } catch (JSONException ignored) { - Logger.dev("JSON error!"); - } + } catch (JSONException ignored) {} return null; } @Override protected void onPostExecute(Void v) { - mPrefs.edit().putBoolean("update_check_done", true).apply(); + CallbackHandler.triggerCallback(StatusFragment.updateCheckDone); } } + public static void checkSafetyNet(Context context) { + new SafetyNetHelper(context) { + @Override + public void handleResults(int i) { + StatusFragment.SNCheckResult = i; + CallbackHandler.triggerCallback(StatusFragment.safetyNetDone); + } + }.requestTest(); + } + public static class LoadModules extends RootTask { - private SharedPreferences mPrefs; - - public LoadModules(SharedPreferences prefs) { - mPrefs = prefs; - } - @Override protected Void doInBackground(Void... voids) { ModuleHelper.createModuleMap(); @@ -100,7 +92,7 @@ public class Async { @Override protected void onPostExecute(Void v) { - mPrefs.edit().putBoolean("module_done", true).apply(); + CallbackHandler.triggerCallback(ModulesFragment.moduleLoadDone); } } @@ -120,8 +112,7 @@ public class Async { @Override protected void onPostExecute(Void v) { - PreferenceManager.getDefaultSharedPreferences(mContext).edit() - .putBoolean("repo_done", true).apply(); + CallbackHandler.triggerCallback(ReposFragment.repoLoadDone); } } @@ -266,7 +257,7 @@ public class Async { protected void done() { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext); prefs.edit().putBoolean("module_done", false).putBoolean("update_check_done", true).apply(); - new LoadModules(prefs).exec(); + new LoadModules().exec(); AlertDialog.Builder builder; String theme = prefs.getString("theme", ""); diff --git a/app/src/main/java/com/topjohnwu/magisk/utils/CallbackHandler.java b/app/src/main/java/com/topjohnwu/magisk/utils/CallbackHandler.java new file mode 100644 index 000000000..58244bd7c --- /dev/null +++ b/app/src/main/java/com/topjohnwu/magisk/utils/CallbackHandler.java @@ -0,0 +1,43 @@ +package com.topjohnwu.magisk.utils; + +import java.util.HashMap; +import java.util.HashSet; + +public class CallbackHandler { + + private static HashMap> listeners = new HashMap<>(); + + public static void register(Event event, EventListener listener) { + HashSet list = listeners.get(event); + if (list == null) { + list = new HashSet<>(); + listeners.put(event, list); + } + list.add(listener); + } + + public static void unRegister(Event event, EventListener listener) { + HashSet list = listeners.get(event); + if (list != null) { + list.remove(listener); + } + } + + public static void triggerCallback(Event event) { + event.isTriggered = true; + HashSet list = listeners.get(event); + if (list != null) { + for (EventListener listener : list) { + listener.onTrigger(event); + } + } + } + + public static class Event { + public boolean isTriggered = false; + } + + public interface EventListener { + void onTrigger(Event event); + } +} diff --git a/app/src/main/java/com/topjohnwu/magisk/utils/SafetyNetHelper.java b/app/src/main/java/com/topjohnwu/magisk/utils/SafetyNetHelper.java index f2213750b..33a087981 100644 --- a/app/src/main/java/com/topjohnwu/magisk/utils/SafetyNetHelper.java +++ b/app/src/main/java/com/topjohnwu/magisk/utils/SafetyNetHelper.java @@ -20,11 +20,9 @@ public abstract class SafetyNetHelper implements GoogleApiClient.OnConnectionFailedListener, GoogleApiClient.ConnectionCallbacks { private GoogleApiClient mGoogleApiClient; - protected Context mContext; public SafetyNetHelper(Context context) { - mContext = context; - mGoogleApiClient = new GoogleApiClient.Builder(mContext) + mGoogleApiClient = new GoogleApiClient.Builder(context) .addApi(SafetyNet.API) .addConnectionCallbacks(this) .addOnConnectionFailedListener(this)