diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/AddContactActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/AddContactActivity.java index 6b6068b7f..b04358016 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/AddContactActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/AddContactActivity.java @@ -49,8 +49,8 @@ public class AddContactActivity extends BriarActivity implements viewModel = ViewModelProviders.of(this, viewModelFactory) .get(AddContactViewModel.class); - viewModel.getRemoteLinkEntered().observe(this, entered -> { - if (entered != null && entered) { + viewModel.getRemoteLinkEntered().observeEvent(this, entered -> { + if (entered) { NicknameFragment f = new NicknameFragment(); showNextFragment(f); } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/AddContactViewModel.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/AddContactViewModel.java index 19e566101..729201cfd 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/AddContactViewModel.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/AddContactViewModel.java @@ -12,6 +12,8 @@ import org.briarproject.bramble.api.contact.ContactManager; import org.briarproject.bramble.api.db.DatabaseExecutor; import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; +import org.briarproject.briar.android.viewmodel.LiveEvent; +import org.briarproject.briar.android.viewmodel.MutableLiveEvent; import java.util.concurrent.Executor; import java.util.logging.Logger; @@ -35,8 +37,8 @@ public class AddContactViewModel extends AndroidViewModel { private final MutableLiveData handshakeLink = new MutableLiveData<>(); - private final MutableLiveData remoteLinkEntered = - new MutableLiveData<>(); + private final MutableLiveEvent remoteLinkEntered = + new MutableLiveEvent<>(); private final MutableLiveData addContactResult = new MutableLiveData<>(); @Nullable @@ -81,14 +83,13 @@ public class AddContactViewModel extends AndroidViewModel { return link != null && LINK_REGEX.matcher(link).find(); } - LiveData getRemoteLinkEntered() { + LiveEvent getRemoteLinkEntered() { return remoteLinkEntered; } void onRemoteLinkEntered() { if (remoteHandshakeLink == null) throw new IllegalStateException(); - remoteLinkEntered.setValue(true); - remoteLinkEntered.postValue(false); // reset, so we can navigate back + remoteLinkEntered.setEvent(true); } void addContact(String nickname) { diff --git a/briar-android/src/main/java/org/briarproject/briar/android/viewmodel/LiveEvent.java b/briar-android/src/main/java/org/briarproject/briar/android/viewmodel/LiveEvent.java new file mode 100644 index 000000000..24aa38cc0 --- /dev/null +++ b/briar-android/src/main/java/org/briarproject/briar/android/viewmodel/LiveEvent.java @@ -0,0 +1,61 @@ +package org.briarproject.briar.android.viewmodel; + +import android.arch.lifecycle.LifecycleOwner; +import android.arch.lifecycle.LiveData; +import android.arch.lifecycle.Observer; +import android.support.annotation.Nullable; + +import org.briarproject.bramble.api.nullsafety.NotNullByDefault; + +import javax.annotation.concurrent.Immutable; + +@NotNullByDefault +public class LiveEvent extends LiveData> { + + public void observeEvent(LifecycleOwner owner, + LiveEventHandler handler) { + LiveEventObserver observer = new LiveEventObserver<>(handler); + super.observe(owner, observer); + } + + public static class ConsumableEvent { + private final T content; + private boolean consumed = false; + + public ConsumableEvent(T content) { + this.content = content; + } + + @Nullable + public T getContentIfNotConsumed() { + if (consumed) return null; + else { + consumed = true; + return content; + } + } + } + + @Immutable + public static class LiveEventObserver + implements Observer> { + private final LiveEventHandler handler; + + public LiveEventObserver(LiveEventHandler handler) { + this.handler = handler; + } + + @Override + public void onChanged(@Nullable ConsumableEvent consumableEvent) { + if (consumableEvent != null) { + T content = consumableEvent.getContentIfNotConsumed(); + if (content != null) handler.onEventUnconsumedContent(content); + } + } + + } + + public interface LiveEventHandler { + void onEventUnconsumedContent(T t); + } +} diff --git a/briar-android/src/main/java/org/briarproject/briar/android/viewmodel/MutableLiveEvent.java b/briar-android/src/main/java/org/briarproject/briar/android/viewmodel/MutableLiveEvent.java new file mode 100644 index 000000000..dac33ecfc --- /dev/null +++ b/briar-android/src/main/java/org/briarproject/briar/android/viewmodel/MutableLiveEvent.java @@ -0,0 +1,15 @@ +package org.briarproject.briar.android.viewmodel; + +import org.briarproject.bramble.api.nullsafety.NotNullByDefault; + +@NotNullByDefault +public class MutableLiveEvent extends LiveEvent { + + public void postEvent(T value) { + super.postValue(new ConsumableEvent<>(value)); + } + + public void setEvent(T value) { + super.setValue(new ConsumableEvent<>(value)); + } +}