diff --git a/briar-android/src/main/java/org/briarproject/briar/android/controller/handler/NewUiResultHandler.java b/briar-android/src/main/java/org/briarproject/briar/android/controller/handler/NewUiResultHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..46d85295c0660a7c3135364c4579e7df5e477b83
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/controller/handler/NewUiResultHandler.java
@@ -0,0 +1,60 @@
+package org.briarproject.briar.android.controller.handler;
+
+import android.os.Binder;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.support.annotation.UiThread;
+
+public abstract class NewUiResultHandler<R> implements ResultHandler<R> {
+
+	private static final int MESSAGE_POST_RESULT = 1;
+	private static UiThreadHandler uiHandler;
+
+	// Ui thread handler singleton, used for all result handlers
+	private static Handler getHandler() {
+		synchronized (NewUiResultHandler.class) {
+			if (uiHandler == null) {
+				uiHandler = new UiThreadHandler();
+			}
+			return uiHandler;
+		}
+	}
+
+	private static class UiThreadHandler extends Handler {
+
+		UiThreadHandler() {
+			super(Looper.getMainLooper());
+		}
+
+		@SuppressWarnings("unchecked")
+		@Override
+		public void handleMessage(Message msg) {
+			if (msg.what == MESSAGE_POST_RESULT) {
+				ResultHandlerResult<?> mhr = (ResultHandlerResult<?>) msg.obj;
+				mhr.resultHandler.onResultUi(mhr.result);
+			}
+		}
+	}
+
+	private static class ResultHandlerResult<R> {
+		final NewUiResultHandler resultHandler;
+		final R result;
+
+		ResultHandlerResult(NewUiResultHandler resultHandler, R result) {
+			this.resultHandler = resultHandler;
+			this.result = result;
+		}
+	}
+
+	@Override
+	public void onResult(R result) {
+		Binder.flushPendingCommands();
+		Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
+				new ResultHandlerResult<>(this, result));
+		message.sendToTarget();
+	}
+
+	@UiThread
+	public abstract void onResultUi(R result);
+}
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/login/PasswordActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/login/PasswordActivity.java
index 3606f077f1428d0199c7f434417d4b65a7d31f32..3f7e933c78c326f877117432390af45bf2256164 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/login/PasswordActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/login/PasswordActivity.java
@@ -3,7 +3,6 @@ package org.briarproject.briar.android.login;
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.os.Bundle;
-import android.support.annotation.NonNull;
 import android.support.design.widget.TextInputLayout;
 import android.support.v7.app.AlertDialog;
 import android.text.Editable;
@@ -19,7 +18,7 @@ import android.widget.TextView.OnEditorActionListener;
 import org.briarproject.briar.R;
 import org.briarproject.briar.android.activity.ActivityComponent;
 import org.briarproject.briar.android.activity.BaseActivity;
-import org.briarproject.briar.android.controller.handler.UiResultHandler;
+import org.briarproject.briar.android.controller.handler.NewUiResultHandler;
 import org.briarproject.briar.android.util.UiUtils;
 
 import javax.inject.Inject;
@@ -39,6 +38,8 @@ public class PasswordActivity extends BaseActivity {
 	private TextInputLayout input;
 	private EditText password;
 
+	private PasswordResult passwordResult;
+
 	@Override
 	public void onCreate(Bundle state) {
 		super.onCreate(state);
@@ -78,6 +79,16 @@ public class PasswordActivity extends BaseActivity {
 			public void afterTextChanged(Editable s) {
 			}
 		});
+
+		this.passwordResult =
+				(PasswordResult) getLastCustomNonConfigurationInstance();
+		if (passwordResult != null)
+			passwordResult.setActivity(this);
+	}
+
+	@Override
+	public Object onRetainCustomNonConfigurationInstance() {
+		return passwordResult;
 	}
 
 	@Override
@@ -123,24 +134,21 @@ public class PasswordActivity extends BaseActivity {
 	}
 
 	private void validatePassword() {
+		initProgressUiState();
+
+		passwordResult = new PasswordResult(this);
+		passwordController.validatePassword(password.getText().toString(),
+				passwordResult);
+	}
+
+	public void initProgressUiState() {
 		hideSoftKeyboard(password);
 		signInButton.setVisibility(INVISIBLE);
 		progress.setVisibility(VISIBLE);
-		passwordController.validatePassword(password.getText().toString(),
-				new UiResultHandler<Boolean>(this) {
-					@Override
-					public void onResultUi(@NonNull Boolean result) {
-						if (result) {
-							setResult(RESULT_OK);
-							finish();
-						} else {
-							tryAgain();
-						}
-					}
-				});
 	}
 
 	private void tryAgain() {
+		passwordResult = null;
 		UiUtils.setError(input, getString(R.string.try_again), true);
 		signInButton.setVisibility(VISIBLE);
 		progress.setVisibility(INVISIBLE);
@@ -149,4 +157,29 @@ public class PasswordActivity extends BaseActivity {
 		// show the keyboard again
 		showSoftKeyboard(password);
 	}
+
+	private static class PasswordResult extends
+			NewUiResultHandler<Boolean> {
+
+		private PasswordActivity activity;
+
+		PasswordResult(PasswordActivity activity) {
+			setActivity(activity);
+		}
+
+		void setActivity(PasswordActivity activity) {
+			this.activity = activity;
+			activity.initProgressUiState();
+		}
+
+		@Override
+		public void onResultUi(Boolean result) {
+			if (result) {
+				activity.setResult(RESULT_OK);
+				activity.finish();
+			} else {
+				activity.tryAgain();
+			}
+		}
+	}
 }