mirror of
https://github.com/syncthing/syncthing-android.git
synced 2024-11-26 22:31:16 +00:00
Do not use WeakReference for listeners (fixes #328).
This makes sure listeners are not invoked after being destroyed. Also call onApiChange() on GUI thread.
This commit is contained in:
parent
7ddee2f953
commit
e821d2e468
6 changed files with 68 additions and 30 deletions
|
@ -109,6 +109,12 @@ public class FolderPickerActivity extends SyncthingActivity
|
|||
getService().registerOnApiChangeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
getService().unregisterOnApiChangeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
if (mListView.getAdapter() == mRootsAdapter)
|
||||
|
|
|
@ -44,8 +44,6 @@ public class MainActivity extends SyncthingActivity
|
|||
|
||||
private AlertDialog mDisabledDialog;
|
||||
|
||||
private boolean mIsDestroyed = false;
|
||||
|
||||
/**
|
||||
* Causes population of folder and device lists, unlocks info drawer.
|
||||
*/
|
||||
|
@ -55,7 +53,7 @@ public class MainActivity extends SyncthingActivity
|
|||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (currentState != SyncthingService.State.ACTIVE && !isFinishing() && !mIsDestroyed) {
|
||||
if (currentState != SyncthingService.State.ACTIVE && !isFinishing()) {
|
||||
if (currentState == SyncthingService.State.DISABLED) {
|
||||
if (mLoadingDialog != null) {
|
||||
mLoadingDialog.dismiss();
|
||||
|
@ -215,7 +213,9 @@ public class MainActivity extends SyncthingActivity
|
|||
if (mLoadingDialog != null) {
|
||||
mLoadingDialog.dismiss();
|
||||
}
|
||||
mIsDestroyed = true;
|
||||
getService().unregisterOnApiChangeListener(this);
|
||||
getService().unregisterOnApiChangeListener(mFolderFragment);
|
||||
getService().unregisterOnApiChangeListener(mDevicesFragment);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -124,18 +124,22 @@ public class DeviceSettingsFragment extends PreferenceFragment implements
|
|||
mSyncthingService.registerOnApiChangeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
mSyncthingService.unregisterOnApiChangeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApiChange(SyncthingService.State currentState) {
|
||||
if (getActivity() == null || getActivity().isFinishing()) {
|
||||
if (currentState != SyncthingService.State.ACTIVE) {
|
||||
getActivity().finish();
|
||||
return;
|
||||
}
|
||||
else if (currentState != SyncthingService.State.ACTIVE) {
|
||||
getActivity().finish();
|
||||
}
|
||||
|
||||
if (mIsCreate) {
|
||||
if (mIsCreate)
|
||||
getActivity().setTitle(R.string.add_device);
|
||||
} else {
|
||||
else {
|
||||
RestApi.Device device = null;
|
||||
getActivity().setTitle(R.string.edit_device);
|
||||
List<RestApi.Device> devices = mSyncthingService.getApi().getDevices(false);
|
||||
|
|
|
@ -121,10 +121,7 @@ public class FolderSettingsFragment extends PreferenceFragment
|
|||
|
||||
@Override
|
||||
public void onApiChange(SyncthingService.State currentState) {
|
||||
if (getActivity() == null || getActivity().isFinishing()) {
|
||||
return;
|
||||
}
|
||||
else if (currentState != SyncthingService.State.ACTIVE) {
|
||||
if (currentState != SyncthingService.State.ACTIVE) {
|
||||
getActivity().finish();
|
||||
return;
|
||||
}
|
||||
|
@ -185,6 +182,12 @@ public class FolderSettingsFragment extends PreferenceFragment
|
|||
mSyncthingService.registerOnApiChangeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
mSyncthingService.unregisterOnApiChangeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
|
|
|
@ -160,6 +160,12 @@ public class SettingsFragment extends PreferenceFragment
|
|||
mSyncthingService.registerOnApiChangeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
mSyncthingService.unregisterOnApiChangeListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles ActionBar back selected.
|
||||
*/
|
||||
|
|
|
@ -14,6 +14,7 @@ import android.content.SharedPreferences;
|
|||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.os.Environment;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
|
@ -31,7 +32,6 @@ import java.io.File;
|
|||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.HashSet;
|
||||
|
@ -92,6 +92,8 @@ public class SyncthingService extends Service {
|
|||
|
||||
private final SyncthingServiceBinder mBinder = new SyncthingServiceBinder(this);
|
||||
|
||||
private Handler mMainHandler;
|
||||
|
||||
/**
|
||||
* Callback for when the Syncthing web interface becomes first available after service start.
|
||||
*/
|
||||
|
@ -106,7 +108,7 @@ public class SyncthingService extends Service {
|
|||
public void onApiChange(State currentState);
|
||||
}
|
||||
|
||||
private final HashSet<WeakReference<OnApiChangeListener>> mOnApiChangeListeners =
|
||||
private final HashSet<OnApiChangeListener> mOnApiChangeListeners =
|
||||
new HashSet<>();
|
||||
|
||||
/**
|
||||
|
@ -139,10 +141,10 @@ public class SyncthingService extends Service {
|
|||
*/
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
// Just catch the empty intent and return.
|
||||
if (intent == null) {
|
||||
}
|
||||
else if (ACTION_RESTART.equals(intent.getAction()) && mCurrentState == State.ACTIVE) {
|
||||
if (intent == null)
|
||||
return START_STICKY;
|
||||
|
||||
if (ACTION_RESTART.equals(intent.getAction()) && mCurrentState == State.ACTIVE) {
|
||||
mApi.shutdown();
|
||||
mCurrentState = State.INIT;
|
||||
updateState();
|
||||
|
@ -253,6 +255,7 @@ public class SyncthingService extends Service {
|
|||
.putString("gui_password", sb.toString()).commit();
|
||||
}
|
||||
|
||||
mMainHandler = new Handler();
|
||||
mDeviceStateHolder = new DeviceStateHolder(SyncthingService.this);
|
||||
registerReceiver(mDeviceStateHolder, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
|
||||
new StartupTask().execute();
|
||||
|
@ -347,13 +350,24 @@ public class SyncthingService extends Service {
|
|||
* Register a listener for the syncthing API state changing.
|
||||
*
|
||||
* The listener is called immediately with the current state, and again whenever the state
|
||||
* changes.
|
||||
* changes. The call is always from the GUI thread.
|
||||
*
|
||||
* @see {@link #unregisterOnApiChangeListener}
|
||||
*/
|
||||
public void registerOnApiChangeListener(OnApiChangeListener listener) {
|
||||
// Make sure we don't send an invalid state or syncthing might show a "disabled" message
|
||||
// when it's just starting up.
|
||||
listener.onApiChange(mCurrentState);
|
||||
mOnApiChangeListeners.add(new WeakReference<>(listener));
|
||||
mOnApiChangeListeners.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters a previously registered listener.
|
||||
*
|
||||
* @see {@link #registerOnApiChangeListener}
|
||||
*/
|
||||
public void unregisterOnApiChangeListener(OnApiChangeListener listener) {
|
||||
mOnApiChangeListeners.remove(listener);
|
||||
}
|
||||
|
||||
private class PollWebGuiAvailableTaskImpl extends PollWebGuiAvailableTask {
|
||||
|
@ -382,15 +396,20 @@ public class SyncthingService extends Service {
|
|||
* Must only be called from SyncthingService or {@link RestApi}.
|
||||
*/
|
||||
private void onApiChange() {
|
||||
for (Iterator<WeakReference<OnApiChangeListener>> i = mOnApiChangeListeners.iterator();
|
||||
i.hasNext(); ) {
|
||||
WeakReference<OnApiChangeListener> listener = i.next();
|
||||
if (listener.get() != null) {
|
||||
listener.get().onApiChange(mCurrentState);
|
||||
} else {
|
||||
i.remove();
|
||||
mMainHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (Iterator<OnApiChangeListener> i = mOnApiChangeListeners.iterator();
|
||||
i.hasNext(); ) {
|
||||
OnApiChangeListener listener = i.next();
|
||||
if (listener != null) {
|
||||
listener.onApiChange(mCurrentState);
|
||||
} else {
|
||||
i.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue