diff --git a/briar-android/src/main/java/org/briarproject/briar/android/controller/DbControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/controller/DbControllerImpl.java
index eaeb7a06ec1c15fbc58e42a2d27c03bb8124eda8..6ae01b8a53ad11cac4857179ccf52f41c9b577b2 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/controller/DbControllerImpl.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/controller/DbControllerImpl.java
@@ -17,7 +17,7 @@ public class DbControllerImpl implements DbController {
 	private static final Logger LOG =
 			Logger.getLogger(DbControllerImpl.class.getName());
 
-	private final Executor dbExecutor;
+	protected final Executor dbExecutor;
 	private final LifecycleManager lifecycleManager;
 
 	@Inject
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/forum/ForumControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/forum/ForumControllerImpl.java
index 4c52f6154c90103da580c4206ffc2dd3b4a882fb..8d97e7810063d4a4d20209a469220b5a2b7e8f47 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/forum/ForumControllerImpl.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/forum/ForumControllerImpl.java
@@ -17,6 +17,7 @@ import org.briarproject.briar.android.controller.handler.ResultExceptionHandler;
 import org.briarproject.briar.android.forum.ForumController.ForumListener;
 import org.briarproject.briar.android.threaded.ThreadListControllerImpl;
 import org.briarproject.briar.api.android.AndroidNotificationManager;
+import org.briarproject.briar.api.client.MessageTracker;
 import org.briarproject.briar.api.client.MessageTracker.GroupCount;
 import org.briarproject.briar.api.forum.Forum;
 import org.briarproject.briar.api.forum.ForumInvitationResponse;
@@ -55,10 +56,10 @@ class ForumControllerImpl extends
 			LifecycleManager lifecycleManager, IdentityManager identityManager,
 			@CryptoExecutor Executor cryptoExecutor,
 			ForumManager forumManager, ForumSharingManager forumSharingManager,
-			EventBus eventBus, Clock clock,
+			EventBus eventBus, Clock clock, MessageTracker messageTracker,
 			AndroidNotificationManager notificationManager) {
 		super(dbExecutor, lifecycleManager, identityManager, cryptoExecutor,
-				eventBus, clock, notificationManager);
+				eventBus, clock, notificationManager, messageTracker);
 		this.forumManager = forumManager;
 		this.forumSharingManager = forumSharingManager;
 	}
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupControllerImpl.java
index 0c75305591d4220540a76c85683760b273b31d76..db6029e57c002ad2f8365ee7cc915670b4e7c386 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupControllerImpl.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupControllerImpl.java
@@ -17,6 +17,7 @@ import org.briarproject.briar.android.controller.handler.ResultExceptionHandler;
 import org.briarproject.briar.android.privategroup.conversation.GroupController.GroupListener;
 import org.briarproject.briar.android.threaded.ThreadListControllerImpl;
 import org.briarproject.briar.api.android.AndroidNotificationManager;
+import org.briarproject.briar.api.client.MessageTracker;
 import org.briarproject.briar.api.client.MessageTracker.GroupCount;
 import org.briarproject.briar.api.privategroup.GroupMember;
 import org.briarproject.briar.api.privategroup.GroupMessage;
@@ -60,9 +61,10 @@ class GroupControllerImpl extends
 			@CryptoExecutor Executor cryptoExecutor,
 			PrivateGroupManager privateGroupManager,
 			GroupMessageFactory groupMessageFactory, EventBus eventBus,
-			Clock clock, AndroidNotificationManager notificationManager) {
+			MessageTracker messageTracker, Clock clock,
+			AndroidNotificationManager notificationManager) {
 		super(dbExecutor, lifecycleManager, identityManager, cryptoExecutor,
-				eventBus, clock, notificationManager);
+				eventBus, clock, notificationManager, messageTracker);
 		this.privateGroupManager = privateGroupManager;
 		this.groupMessageFactory = groupMessageFactory;
 	}
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemAdapter.java b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemAdapter.java
index 0a36ac80ec301f1f1a56e900726267f9b40e1751..99a4a3335afcef45a27a536231ce5658caca3c15 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemAdapter.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemAdapter.java
@@ -66,17 +66,7 @@ public class ThreadItemAdapter<I extends ThreadItem>
 		revision++;
 	}
 
-	// Useful when the adapter has not calculated the dimension yet
-	void postSetItemWithIdVisible(@Nullable final MessageId messageId) {
-		new Handler().post(new Runnable() {
-			@Override
-			public void run() {
-				setItemWithIdVisible(messageId);
-			}
-		});
-	}
-
-	void setItemWithIdVisible(@Nullable MessageId messageId) {
+	void setItemWithIdVisible(MessageId messageId) {
 		if (messageId != null) {
 			int pos = 0;
 			for (I item : items) {
@@ -169,7 +159,7 @@ public class ThreadItemAdapter<I extends ThreadItem>
 	/**
 	 * Returns the position of the first unread item below the current viewport
 	 */
-	public int getVisibleUnreadPosBottom() {
+	int getVisibleUnreadPosBottom() {
 		final int positionBottom = layoutManager.findLastVisibleItemPosition();
 		if (positionBottom == NO_POSITION) return NO_POSITION;
 		for (int i = positionBottom + 1; i < items.size(); i++) {
@@ -181,7 +171,7 @@ public class ThreadItemAdapter<I extends ThreadItem>
 	/**
 	 * Returns the position of the first unread item above the current viewport
 	 */
-	public int getVisibleUnreadPosTop() {
+	int getVisibleUnreadPosTop() {
 		final int positionTop = layoutManager.findFirstVisibleItemPosition();
 		int position = NO_POSITION;
 		for (int i = 0; i < items.size(); i++) {
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemList.java b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemList.java
index 53d6ed633a89704ed9351b6f6b5527128833e4ee..d4f067c2f72ecba9706a26d0dc95df3ce034864b 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemList.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemList.java
@@ -9,7 +9,7 @@ import javax.annotation.Nullable;
 public interface ThreadItemList<I extends ThreadItem> extends List<I> {
 
 	@Nullable
-	MessageId getBottomVisibleItemId();
+	MessageId getFirstVisibleItemId();
 
 	void setBottomVisibleItemId(@Nullable MessageId bottomVisibleItemId);
 }
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemListImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemListImpl.java
index 880d297391fc5d6936266fa65a3b58e5499ad4e1..f6fb80e68246d2f55b7630bb648072feaa415874 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemListImpl.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadItemListImpl.java
@@ -12,7 +12,7 @@ public class ThreadItemListImpl<I extends ThreadItem> extends ArrayList<I>
 	private MessageId bottomVisibleItemId;
 
 	@Override
-	public MessageId getBottomVisibleItemId() {
+	public MessageId getFirstVisibleItemId() {
 		return bottomVisibleItemId;
 	}
 
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListActivity.java
index 68cec97a2789860c3929939c17b6024747d8487a..b62f35c772dce2206c6c91f04de8bbae7614e20b 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListActivity.java
@@ -149,11 +149,12 @@ public abstract class ThreadListActivity<G extends NamedGroup, A extends ThreadI
 
 	@Override
 	@Nullable
-	public MessageId getLastVisibleMessageId() {
+	public MessageId getFirstVisibleMessageId() {
 		if (layoutManager != null && adapter != null) {
 			int position =
-					layoutManager.findLastCompletelyVisibleItemPosition();
-			return adapter.getItemAt(position).getId();
+					layoutManager.findFirstVisibleItemPosition();
+			I i = adapter.getItemAt(position);
+			return i == null ? null : adapter.getItemAt(position).getId();
 		}
 		return null;
 	}
@@ -190,10 +191,7 @@ public abstract class ThreadListActivity<G extends NamedGroup, A extends ThreadI
 							if (items.isEmpty()) {
 								list.showData();
 							} else {
-								adapter.setItems(items);
-								adapter.postSetItemWithIdVisible(
-										items.getBottomVisibleItemId());
-								list.showData();
+								initList(items);
 								updateTextInput(replyId);
 							}
 						} else {
@@ -209,6 +207,15 @@ public abstract class ThreadListActivity<G extends NamedGroup, A extends ThreadI
 				});
 	}
 
+	private void initList(final ThreadItemList<I> items) {
+		adapter.setItems(items);
+		MessageId messageId = items.getFirstVisibleItemId();
+		if (messageId != null)
+			adapter.setItemWithIdVisible(messageId);
+		updateUnreadCount();
+		list.showData();
+	}
+
 	protected void loadSharingContacts() {
 		getController().loadSharingContacts(
 				new UiResultExceptionHandler<Collection<ContactId>, DbException>(
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListController.java b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListController.java
index 45aa69a0ac6a819ae2d56ba6015cae293fa2abd8..d39c8b453a6c1c5852d9c56663edd1d7ca0fe4fa 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListController.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListController.java
@@ -56,7 +56,7 @@ public interface ThreadListController<G extends NamedGroup, I extends ThreadItem
 	interface ThreadListDataSource extends DestroyableContext {
 
 		@UiThread @Nullable
-		MessageId getLastVisibleMessageId();
+		MessageId getFirstVisibleMessageId();
 	}
 
 }
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListControllerImpl.java
index c61b354583269ff34cf44222a0cdfe6769fe6eac..add7a977668cb62d24c3909f407c7134530d1d43 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListControllerImpl.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListControllerImpl.java
@@ -34,8 +34,6 @@ import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.Executor;
 import java.util.logging.Logger;
 
-import javax.inject.Inject;
-
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
 
@@ -56,20 +54,21 @@ public abstract class ThreadListControllerImpl<G extends NamedGroup, I extends T
 	protected final AndroidNotificationManager notificationManager;
 	protected final Executor cryptoExecutor;
 	protected final Clock clock;
+	private final MessageTracker messageTracker;
 	protected volatile L listener;
-	@Inject
-	MessageTracker messageTracker;
 
 	protected ThreadListControllerImpl(@DatabaseExecutor Executor dbExecutor,
 			LifecycleManager lifecycleManager, IdentityManager identityManager,
 			@CryptoExecutor Executor cryptoExecutor, EventBus eventBus,
-			Clock clock, AndroidNotificationManager notificationManager) {
+			Clock clock, AndroidNotificationManager notificationManager,
+			MessageTracker messageTracker) {
 		super(dbExecutor, lifecycleManager);
 		this.identityManager = identityManager;
 		this.cryptoExecutor = cryptoExecutor;
 		this.notificationManager = notificationManager;
 		this.clock = clock;
 		this.eventBus = eventBus;
+		this.messageTracker = messageTracker;
 	}
 
 	@Override
@@ -100,14 +99,19 @@ public abstract class ThreadListControllerImpl<G extends NamedGroup, I extends T
 
 	@Override
 	public void onActivityDestroy() {
-		try {
-			messageTracker
-					.storeMessageId(groupId,
-							listener.getLastVisibleMessageId());
-		} catch (DbException e) {
-			if (LOG.isLoggable(WARNING))
-				LOG.log(WARNING, e.toString(), e);
-		}
+		dbExecutor.execute(new Runnable() {
+			@Override
+			public void run() {
+				try {
+					messageTracker
+							.storeMessageId(groupId,
+									listener.getFirstVisibleMessageId());
+				} catch (DbException e) {
+					if (LOG.isLoggable(WARNING))
+						LOG.log(WARNING, e.toString(), e);
+				}
+			}
+		});
 	}
 
 	@CallSuper
@@ -304,19 +308,16 @@ public abstract class ThreadListControllerImpl<G extends NamedGroup, I extends T
 	@DatabaseExecutor
 	protected abstract void deleteNamedGroup(G groupItem) throws DbException;
 
-	private ThreadItemList<I> buildItems(Collection<H> headers) {
+	private ThreadItemList<I> buildItems(Collection<H> headers)
+			throws DbException {
 		ThreadItemList<I> items = new ThreadItemListImpl<>();
 		for (H h : headers) {
 			items.add(buildItem(h, bodyCache.get(h.getId())));
 		}
-		try {
-			MessageId msgId = messageTracker.loadStoredMessageId(groupId);
-			if (LOG.isLoggable(INFO))
-				LOG.info("Loaded last top visible message id " + msgId);
-			items.setBottomVisibleItemId(msgId);
-		} catch (DbException e) {
-			e.printStackTrace();
-		}
+		MessageId msgId = messageTracker.loadStoredMessageId(groupId);
+		if (LOG.isLoggable(INFO))
+			LOG.info("Loaded last top visible message id " + msgId);
+		items.setBottomVisibleItemId(msgId);
 		return items;
 	}
 
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/view/UnreadMessageButton.java b/briar-android/src/main/java/org/briarproject/briar/android/view/UnreadMessageButton.java
index e7f4fa92f5387377a72ea82ba02f7b0d1b3ae9bf..4a5360043e21128e68b15c276db786f1d7c01d14 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/view/UnreadMessageButton.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/view/UnreadMessageButton.java
@@ -36,8 +36,7 @@ public class UnreadMessageButton extends FrameLayout {
 
 		LayoutInflater inflater = (LayoutInflater) context
 				.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-		inflater
-				.inflate(R.layout.unread_message_button, this, true);
+		inflater.inflate(R.layout.unread_message_button, this, true);
 
 		fab = (FloatingActionButton) findViewById(R.id.fab);
 		unread = (TextView) findViewById(R.id.unreadCountView);
@@ -64,15 +63,11 @@ public class UnreadMessageButton extends FrameLayout {
 
 	public void setUnreadCount(int count) {
 		if (count == 0) {
-			fab.setVisibility(GONE);
-//			fab.hide();
-			unread.setVisibility(GONE);
+			setVisibility(INVISIBLE);
 		} else {
 			// FIXME: Use animations when upgrading to support library 24.2.0
 			//        https://code.google.com/p/android/issues/detail?id=216469
-			fab.setVisibility(VISIBLE);
-//			if (!fab.isShown()) fab.show();
-			unread.setVisibility(VISIBLE);
+			setVisibility(VISIBLE);
 			unread.setText(String.valueOf(count));
 		}
 	}
diff --git a/briar-core/src/test/java/org/briarproject/briar/client/MessageTrackerTest.java b/briar-core/src/test/java/org/briarproject/briar/client/MessageTrackerTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..6f841703fe67468ff4fe8c8847ee2f2bb7a1d330
--- /dev/null
+++ b/briar-core/src/test/java/org/briarproject/briar/client/MessageTrackerTest.java
@@ -0,0 +1,57 @@
+package org.briarproject.briar.client;
+
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.data.BdfEntry;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.test.TestUtils;
+import org.briarproject.briar.api.client.MessageTracker;
+import org.briarproject.briar.test.BriarTestCase;
+import org.jmock.Expectations;
+import org.jmock.Mockery;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Test;
+
+import static org.briarproject.briar.client.MessageTrackerConstants.GROUP_KEY_STORED_MESSAGE_ID;
+
+public class MessageTrackerTest extends BriarTestCase {
+
+	protected final Mockery context = new Mockery();
+	protected final GroupId groupId = new GroupId(TestUtils.getRandomId());
+	protected final ClientHelper clientHelper =
+			context.mock(ClientHelper.class);
+	private final DatabaseComponent db = context.mock(DatabaseComponent.class);
+	private final MessageId messageId = new MessageId(TestUtils.getRandomId());
+	private final MessageTracker messageTracker =
+			new MessageTrackerImpl(db, clientHelper);
+	private final BdfDictionary dictionary = BdfDictionary.of(
+			new BdfEntry(GROUP_KEY_STORED_MESSAGE_ID, messageId)
+	);
+
+	@Test
+	public void testMessageStore() throws Exception {
+		context.checking(new Expectations() {{
+			oneOf(clientHelper).mergeGroupMetadata(groupId, dictionary);
+		}});
+		messageTracker.storeMessageId(groupId, messageId);
+	}
+
+	@Test
+	public void testMessageLoad() throws Exception {
+		context.checking(new Expectations() {{
+			oneOf(clientHelper).getGroupMetadataAsDictionary(groupId);
+			will(returnValue(dictionary));
+		}});
+		MessageId loadedId = messageTracker.loadStoredMessageId(groupId);
+		Assert.assertNotNull(loadedId);
+		Assert.assertTrue(messageId.equals(loadedId));
+	}
+
+	@After
+	public void checkExpectations() {
+		context.assertIsSatisfied();
+	}
+}
diff --git a/briar-core/src/test/java/org/briarproject/briar/forum/ForumManagerTest.java b/briar-core/src/test/java/org/briarproject/briar/forum/ForumManagerTest.java
index 09805ce44b1cb4d07cc45796ed5b830abab7e7a7..30567fdf225431c37ef54d27fc1908c2d2e7c9e1 100644
--- a/briar-core/src/test/java/org/briarproject/briar/forum/ForumManagerTest.java
+++ b/briar-core/src/test/java/org/briarproject/briar/forum/ForumManagerTest.java
@@ -1,10 +1,7 @@
 package org.briarproject.briar.forum;
 
-import org.briarproject.bramble.api.db.DbException;
 import org.briarproject.bramble.api.sync.GroupId;
-import org.briarproject.bramble.api.sync.MessageId;
 import org.briarproject.bramble.test.TestDatabaseModule;
-import org.briarproject.bramble.test.TestUtils;
 import org.briarproject.briar.api.forum.Forum;
 import org.briarproject.briar.api.forum.ForumManager;
 import org.briarproject.briar.api.forum.ForumPost;
@@ -13,7 +10,6 @@ import org.briarproject.briar.api.forum.ForumSharingManager;
 import org.briarproject.briar.test.BriarIntegrationTest;
 import org.briarproject.briar.test.BriarIntegrationTestComponent;
 import org.briarproject.briar.test.DaggerBriarIntegrationTestComponent;
-import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -227,18 +223,4 @@ public class ForumManagerTest
 		assertEquals(1, forumManager1.getPostHeaders(g1).size());
 	}
 
-	@Test
-	public void testMessageStoreAndLoad() {
-		MessageId msgId = new MessageId(TestUtils.getRandomId());
-		MessageId loadedId = null;
-		try {
-			messageTracker0.storeMessageId(groupId0, msgId);
-			loadedId = messageTracker0.loadStoredMessageId(groupId0);
-		} catch (DbException e) {
-			e.printStackTrace();
-		}
-		Assert.assertNotNull(loadedId);
-		Assert.assertTrue(msgId.equals(loadedId));
-	}
-
 }