From 28407d2e9492f78fed4ead3d94e77c7feb7bbb4d Mon Sep 17 00:00:00 2001 From: Felix Ableitner Date: Mon, 31 Oct 2016 03:59:26 +0900 Subject: [PATCH] Use generic listeners for RestApi callbacks --- .../fragments/DeviceFragment.java | 30 +---- .../fragments/DrawerFragment.java | 16 +-- .../fragments/SettingsFragment.java | 9 +- .../syncthingandroid/syncthing/RestApi.java | 120 ++++++------------ .../views/DevicesAdapter.java | 6 +- .../views/FoldersAdapter.java | 6 +- 6 files changed, 58 insertions(+), 129 deletions(-) diff --git a/src/main/java/com/nutomic/syncthingandroid/fragments/DeviceFragment.java b/src/main/java/com/nutomic/syncthingandroid/fragments/DeviceFragment.java index b4211328..bd1dbf81 100644 --- a/src/main/java/com/nutomic/syncthingandroid/fragments/DeviceFragment.java +++ b/src/main/java/com/nutomic/syncthingandroid/fragments/DeviceFragment.java @@ -49,10 +49,7 @@ import static com.nutomic.syncthingandroid.util.Compression.METADATA; /** * Shows device details and allows changing them. */ -public class DeviceFragment extends Fragment implements - SyncthingActivity.OnServiceConnectedListener, RestApi.OnReceiveConnectionsListener, - SyncthingService.OnApiChangeListener, RestApi.OnDeviceIdNormalizedListener, - View.OnClickListener { +public class DeviceFragment extends Fragment implements View.OnClickListener { public static final String EXTRA_DEVICE_ID = "com.nutomic.syncthingandroid.fragments.DeviceFragment.DEVICE_ID"; @@ -155,7 +152,7 @@ public class DeviceFragment extends Fragment implements SettingsActivity activity = (SettingsActivity) getActivity(); mIsCreateMode = activity.getIsCreate(); - activity.registerOnServiceConnectedListener(this); + activity.registerOnServiceConnectedListener(this::onServiceConnected); activity.setTitle(mIsCreateMode ? R.string.add_device : R.string.edit_device); setHasOptionsMenu(true); @@ -173,7 +170,7 @@ public class DeviceFragment extends Fragment implements public void onDestroy() { super.onDestroy(); if (mSyncthingService != null) { - mSyncthingService.unregisterOnApiChangeListener(this); + mSyncthingService.unregisterOnApiChangeListener(this::onApiChange); } } @@ -235,10 +232,9 @@ public class DeviceFragment extends Fragment implements mAddressesView.removeTextChangedListener(mAddressesTextWatcher); } - @Override public void onServiceConnected() { mSyncthingService = ((SyncthingActivity) getActivity()).getService(); - mSyncthingService.registerOnApiChangeListener(this); + mSyncthingService.registerOnApiChangeListener(this::onApiChange); } /** @@ -247,7 +243,6 @@ public class DeviceFragment extends Fragment implements * NOTE: This is only called once on startup, should be called more often to properly display * version/address changes. */ - @Override public void onReceiveConnections(Map connections) { boolean viewsExist = mSyncthingVersionView != null && mCurrentAddressView != null; if (viewsExist && connections.containsKey(mDevice.deviceID)) { @@ -258,7 +253,6 @@ public class DeviceFragment extends Fragment implements } } - @Override public void onApiChange(SyncthingService.State currentState) { if (currentState != ACTIVE) { getActivity().finish(); @@ -282,7 +276,7 @@ public class DeviceFragment extends Fragment implements } } - mSyncthingService.getApi().getConnections(this); + mSyncthingService.getApi().getConnections(this::onReceiveConnections); updateViewsAndSetListeners(); } @@ -324,7 +318,8 @@ public class DeviceFragment extends Fragment implements .show(); return true; } - mSyncthingService.getApi().addDevice(mDevice, this); + mSyncthingService.getApi().addDevice(mDevice, error -> + Toast.makeText(getActivity(), error, Toast.LENGTH_LONG).show()); getActivity().finish(); return true; case R.id.share_device_id: @@ -358,17 +353,6 @@ public class DeviceFragment extends Fragment implements } } - /** - * Callback for {@link RestApi#editDevice}. - * Displays an error toast if error message present. - */ - @Override - public void onDeviceIdNormalized(String normalizedId, String error) { - if (error != null) { - Toast.makeText(getActivity(), error, Toast.LENGTH_LONG).show(); - } - } - private void initDevice() { mDevice = new Device(); mDevice.name = ""; diff --git a/src/main/java/com/nutomic/syncthingandroid/fragments/DrawerFragment.java b/src/main/java/com/nutomic/syncthingandroid/fragments/DrawerFragment.java index 8b60942f..80edafe1 100644 --- a/src/main/java/com/nutomic/syncthingandroid/fragments/DrawerFragment.java +++ b/src/main/java/com/nutomic/syncthingandroid/fragments/DrawerFragment.java @@ -31,10 +31,7 @@ import java.util.TimerTask; /** * Displays information about the local device. */ -public class DrawerFragment extends Fragment implements RestApi.OnReceiveSystemInfoListener, - RestApi.OnReceiveConnectionsListener, - RestApi.OnReceiveSystemVersionListener, - View.OnClickListener { +public class DrawerFragment extends Fragment implements View.OnClickListener { private TextView mDeviceId; private TextView mCpuUsage; @@ -139,9 +136,9 @@ public class DrawerFragment extends Fragment implements RestApi.OnReceiveSystemI private void updateGui() { if (mActivity.getApi() == null || getActivity() == null || getActivity().isFinishing()) return; - mActivity.getApi().getSystemInfo(this); - mActivity.getApi().getSystemVersion(this); - mActivity.getApi().getConnections(this); + mActivity.getApi().getSystemInfo(this::onReceiveSystemInfo); + mActivity.getApi().getSystemVersion(this::onReceiveSystemVersion); + mActivity.getApi().getConnections(this::onReceiveConnections); } /** @@ -156,7 +153,6 @@ public class DrawerFragment extends Fragment implements RestApi.OnReceiveSystemI /** * Populates views with status received via {@link RestApi#getSystemInfo}. */ - @Override public void onReceiveSystemInfo(SystemInfo info) { if (getActivity() == null) return; @@ -181,7 +177,6 @@ public class DrawerFragment extends Fragment implements RestApi.OnReceiveSystemI /** * Populates views with status received via {@link RestApi#getSystemInfo}. */ - @Override public void onReceiveSystemVersion(SystemVersion info) { if (getActivity() == null) return; @@ -192,8 +187,7 @@ public class DrawerFragment extends Fragment implements RestApi.OnReceiveSystemI /** * Populates views with status received via {@link RestApi#getConnections}. */ - @Override - public void onReceiveConnections(Map connections) { + private void onReceiveConnections(Map connections) { Connection c = connections.get(RestApi.TOTAL_STATS); mDownload.setText(Util.readableTransferRate(mActivity, c.inBits)); mUpload.setText(Util.readableTransferRate(mActivity, c.outBits)); diff --git a/src/main/java/com/nutomic/syncthingandroid/fragments/SettingsFragment.java b/src/main/java/com/nutomic/syncthingandroid/fragments/SettingsFragment.java index dfdd5fa4..0997ae70 100644 --- a/src/main/java/com/nutomic/syncthingandroid/fragments/SettingsFragment.java +++ b/src/main/java/com/nutomic/syncthingandroid/fragments/SettingsFragment.java @@ -8,7 +8,6 @@ import android.os.Bundle; import android.preference.CheckBoxPreference; import android.preference.EditTextPreference; import android.preference.Preference; -import android.preference.PreferenceCategory; import android.preference.PreferenceFragment; import android.preference.PreferenceScreen; import android.util.Log; @@ -232,7 +231,7 @@ public class SettingsFragment extends PreferenceFragment } public boolean onRequireRestart(Preference preference, Object o) { - mSyncthingService.getApi().requireRestart(getActivity()); + mSyncthingService.getApi().showRestartDialog(getActivity()); return true; } @@ -262,7 +261,7 @@ public class SettingsFragment extends PreferenceFragment break; case KEY_STTRACE: if (((String) o).matches("[0-9a-z, ]*")) - mSyncthingService.getApi().requireRestart(getActivity()); + mSyncthingService.getApi().showRestartDialog(getActivity()); else { Toast.makeText(getActivity(), R.string.toast_invalid_sttrace, Toast.LENGTH_SHORT) .show(); @@ -284,7 +283,7 @@ public class SettingsFragment extends PreferenceFragment new TestRootTask().execute(); } else { new Thread(new ChownFilesRunnable()).start(); - mSyncthingService.getApi().requireRestart(getActivity()); + mSyncthingService.getApi().showRestartDialog(getActivity()); } return true; case KEY_EXPORT_CONFIG: @@ -350,7 +349,7 @@ public class SettingsFragment extends PreferenceFragment @Override protected void onPostExecute(Boolean haveRoot) { if (haveRoot) { - mSyncthingService.getApi().requireRestart(getActivity()); + mSyncthingService.getApi().showRestartDialog(getActivity()); mUseRoot.setChecked(true); } else { Toast.makeText(getActivity(), R.string.toast_root_denied, Toast.LENGTH_SHORT) diff --git a/src/main/java/com/nutomic/syncthingandroid/syncthing/RestApi.java b/src/main/java/com/nutomic/syncthingandroid/syncthing/RestApi.java index 74fc31ae..e3e73d98 100644 --- a/src/main/java/com/nutomic/syncthingandroid/syncthing/RestApi.java +++ b/src/main/java/com/nutomic/syncthingandroid/syncthing/RestApi.java @@ -29,6 +29,7 @@ import com.nutomic.syncthingandroid.model.Options; import com.nutomic.syncthingandroid.model.SystemInfo; import com.nutomic.syncthingandroid.model.SystemVersion; import com.nutomic.syncthingandroid.util.FolderObserver; +import com.nutomic.syncthingandroid.util.Util; import org.json.JSONArray; import org.json.JSONException; @@ -60,6 +61,14 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener, void onConfigChanged(); } + public interface OnResultListener1 { + public void onResult(T t); + } + + public interface OnResultListener2 { + public void onResult(T t, R r); + } + private final Context mContext; private final URL mUrl; private final String mApiKey; @@ -82,8 +91,8 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener, private long mPreviousConnectionTime = 0; /** - * Stores the latest result of {@link #getModel(String, OnReceiveModelListener)} for each folder, - * for calculating device percentage in {@link #getConnections(OnReceiveConnectionsListener)}. + * Stores the latest result of {@link #getModel} for each folder, for calculating device + * percentage in {@link #getConnections}. */ private final HashMap mCachedModelInfo = new HashMap<>(); @@ -172,7 +181,7 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener, * Either shows a restart dialog, or only updates the config, depending on * {@link #mRestartPostponed}. */ - public void requireRestart(Activity activity) { + public void showRestartDialog(Activity activity) { if (mRestartPostponed) { sendConfig(); } else { @@ -181,13 +190,16 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener, mOnConfigChangedListener.onConfigChanged(); } + /** + * Sends current config to Syncthing. + */ private void sendConfig() { new PostTask(mUrl, PostTask.URI_CONFIG, mHttpsCertPath, mApiKey, null) .execute(new Gson().toJson(mConfig)); } /** - * Immediately restarts Syncthing, without confirmation. + * Sends current config and restarts Syncthing. */ public void restart() { new PostTask(mUrl, PostTask.URI_CONFIG, mHttpsCertPath, mApiKey, result -> { @@ -263,16 +275,11 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener, } } - public void addDevice(Device device, OnDeviceIdNormalizedListener listener) { - normalizeDeviceId(device.deviceID, ((normalizedId, error) -> { - if (error == null) { + public void addDevice(Device device, OnResultListener1 errorListener) { + normalizeDeviceId(device.deviceID, normalizedId -> { mConfig.devices.add(device); sendConfig(); - } - else { - listener.onDeviceIdNormalized(normalizedId, error); - } - })); + }, errorListener); } public void addFolder(Folder folder) { @@ -294,21 +301,7 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener, public void editSettings(Config.Gui newGui, Options newOptions, Activity activity) { mConfig.gui = newGui; mConfig.options = newOptions; - requireRestart(activity); - } - - /** - * Result listener for {@link #getSystemInfo(OnReceiveSystemInfoListener)}. - */ - public interface OnReceiveSystemInfoListener { - public void onReceiveSystemInfo(SystemInfo info); - } - - /** - * Result listener for {@link #getSystemVersion(OnReceiveSystemVersionListener)}. - */ - public interface OnReceiveSystemVersionListener { - void onReceiveSystemVersion(SystemVersion version); + showRestartDialog(activity); } /** @@ -316,9 +309,9 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener, * * @param listener Callback invoked when the result is received. */ - public void getSystemInfo(final OnReceiveSystemInfoListener listener) { + public void getSystemInfo(OnResultListener1 listener) { new GetTask(mUrl, GetTask.URI_SYSTEM, mHttpsCertPath, mApiKey, result -> { - listener.onReceiveSystemInfo(new Gson().fromJson(result, SystemInfo.class)); + listener.onResult(new Gson().fromJson(result, SystemInfo.class)); }).execute(); } @@ -327,10 +320,10 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener, * * @param listener Callback invoked when the result is received. */ - public void getSystemVersion(final OnReceiveSystemVersionListener listener) { + public void getSystemVersion(OnResultListener1 listener) { new GetTask(mUrl, GetTask.URI_VERSION, mHttpsCertPath, mApiKey, result -> { SystemVersion systemVersion = new Gson().fromJson(result, SystemVersion.class); - listener.onReceiveSystemVersion(systemVersion); + listener.onResult(systemVersion); }).execute(); } @@ -341,31 +334,19 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener, return deepCopy(mConfig.folders, new TypeToken>(){}.getType()); } - /** - * Listener for {@link #getConnections}. - */ - public interface OnReceiveConnectionsListener { - - /** - * @param connections Map from Device id to {@link Connection}. - *

- * NOTE: The parameter connections is cached internally. Do not modify it or - * any of its contents. - */ - public void onReceiveConnections(Map connections); - } - /** * Returns connection info for the local device and all connected devices. *

* Use the key {@link #TOTAL_STATS} to get connection info for the local device. + * + * The result is cached internally. Do not modify it or any of its contents. */ - public void getConnections(final OnReceiveConnectionsListener listener) { + public void getConnections(final OnResultListener1> listener) { new GetTask(mUrl, GetTask.URI_CONNECTIONS, mHttpsCertPath, mApiKey, result -> { Long now = System.currentTimeMillis(); Long timeElapsed = (now - mPreviousConnectionTime) / 1000; if (timeElapsed < 1) { - listener.onReceiveConnections(mPreviousConnections); + listener.onResult(mPreviousConnections); return; } @@ -407,7 +388,7 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener, } mPreviousConnections = connections; - listener.onReceiveConnections(mPreviousConnections); + listener.onResult(mPreviousConnections); } catch (JSONException e) { Log.w(TAG, "Failed to parse connections", e); } @@ -449,13 +430,6 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener, : 100; } - /** - * Listener for {@link #getModel}. - */ - public interface OnReceiveModelListener { - public void onReceiveModel(String folderId, Model model); - } - /** * Listener for {@link #getEvents}. */ @@ -472,14 +446,15 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener, */ void onDone(long lastId); } + /** * Returns status information about the folder with the given id. */ - public void getModel(final String folderId, final OnReceiveModelListener listener) { + public void getModel(final String folderId, final OnResultListener2 listener) { new GetTask(mUrl, GetTask.URI_MODEL, mHttpsCertPath, mApiKey, result -> { Model m = new Gson().fromJson(result, Model.class); mCachedModelInfo.put(folderId, m); - listener.onReceiveModel(folderId, m); + listener.onResult(folderId, m); }).execute("folder", folderId); } @@ -508,31 +483,19 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener, "since", String.valueOf(sinceId), "limit", String.valueOf(limit)); } - /** - * Result listener for {@link #normalizeDeviceId(String, OnDeviceIdNormalizedListener)}. - */ - public interface OnDeviceIdNormalizedListener { - /** - * On any call, exactly one parameter will be null. - * - * @param normalizedId The normalized device ID, or null on error. - * @param error An error message, or null on success. - */ - public void onDeviceIdNormalized(String normalizedId, String error); - } - /** * Normalizes a given device ID. */ - public void normalizeDeviceId(final String id, final OnDeviceIdNormalizedListener listener) { + public void normalizeDeviceId(String id, OnResultListener1 listener, + OnResultListener1 errorListener) { new GetTask(mUrl, GetTask.URI_DEVICEID, mHttpsCertPath, mApiKey, result -> { JsonObject json = new JsonParser().parse(result).getAsJsonObject(); JsonElement normalizedId = json.get("id"); JsonElement error = json.get("error"); if (normalizedId != null) - listener.onDeviceIdNormalized(normalizedId.getAsString(), null); + listener.onResult(normalizedId.getAsString()); if (error != null) - listener.onDeviceIdNormalized(null, error.getAsString()); + errorListener.onResult(error.getAsString()); }).execute("id", id); } @@ -557,21 +520,14 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener, throw new RuntimeException(); } - /** - * Callback for {@link #getUsageReport}. - */ - public interface OnReceiveUsageReportListener { - public void onReceiveUsageReport(String report); - } - /** * Returns prettyfied usage report. */ - public void getUsageReport(final OnReceiveUsageReportListener listener) { + public void getUsageReport(final OnResultListener1 listener) { new GetTask(mUrl, GetTask.URI_REPORT, mHttpsCertPath, mApiKey, result -> { JsonElement json = new JsonParser().parse(result); Gson gson = new GsonBuilder().setPrettyPrinting().create(); - listener.onReceiveUsageReport(gson.toJson(json)); + listener.onResult(gson.toJson(json)); }).execute(); } diff --git a/src/main/java/com/nutomic/syncthingandroid/views/DevicesAdapter.java b/src/main/java/com/nutomic/syncthingandroid/views/DevicesAdapter.java index 267373f7..bde589b8 100644 --- a/src/main/java/com/nutomic/syncthingandroid/views/DevicesAdapter.java +++ b/src/main/java/com/nutomic/syncthingandroid/views/DevicesAdapter.java @@ -22,8 +22,7 @@ import java.util.Map; /** * Generates item views for device items. */ -public class DevicesAdapter extends ArrayAdapter - implements RestApi.OnReceiveConnectionsListener { +public class DevicesAdapter extends ArrayAdapter { private Map mConnections = new HashMap<>(); @@ -78,11 +77,10 @@ public class DevicesAdapter extends ArrayAdapter */ public void updateConnections(RestApi api) { for (int i = 0; i < getCount(); i++) { - api.getConnections(this); + api.getConnections(this::onReceiveConnections); } } - @Override public void onReceiveConnections(Map connections) { mConnections = connections; notifyDataSetChanged(); diff --git a/src/main/java/com/nutomic/syncthingandroid/views/FoldersAdapter.java b/src/main/java/com/nutomic/syncthingandroid/views/FoldersAdapter.java index 981b4a21..61c5cd19 100644 --- a/src/main/java/com/nutomic/syncthingandroid/views/FoldersAdapter.java +++ b/src/main/java/com/nutomic/syncthingandroid/views/FoldersAdapter.java @@ -25,8 +25,7 @@ import static android.view.View.VISIBLE; /** * Generates item views for folder items. */ -public class FoldersAdapter extends ArrayAdapter - implements RestApi.OnReceiveModelListener { +public class FoldersAdapter extends ArrayAdapter { private final HashMap mModels = new HashMap<>(); private final LayoutInflater mInflater; @@ -100,11 +99,10 @@ public class FoldersAdapter extends ArrayAdapter */ public void updateModel(RestApi api) { for (int i = 0; i < getCount(); i++) { - api.getModel(getItem(i).id, this); + api.getModel(getItem(i).id, this::onReceiveModel); } } - @Override public void onReceiveModel(String folderId, Model model) { mModels.put(folderId, model); notifyDataSetChanged();