diff --git a/briar-android/res/layout/activity_available_forums.xml b/briar-android/res/layout/activity_available_forums.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7177fe175f97b59be6996a4e1ad6df6983f9d197
--- /dev/null
+++ b/briar-android/res/layout/activity_available_forums.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<org.briarproject.android.util.BriarRecyclerView
+	android:id="@+id/availableForumsView"
+	xmlns:android="http://schemas.android.com/apk/res/android"
+	android:layout_width="match_parent"
+	android:layout_height="match_parent"/>
diff --git a/briar-android/res/layout/list_item_available_forum.xml b/briar-android/res/layout/list_item_available_forum.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0129b9d6bfd84809d74ddedcfe219c0cd6149c02
--- /dev/null
+++ b/briar-android/res/layout/list_item_available_forum.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout
+	xmlns:android="http://schemas.android.com/apk/res/android"
+	xmlns:tools="http://schemas.android.com/tools"
+	android:layout_width="match_parent"
+	android:layout_height="wrap_content"
+	android:layout_marginLeft="@dimen/listitem_horizontal_margin"
+	android:layout_marginStart="@dimen/listitem_horizontal_margin"
+	android:paddingTop="@dimen/listitem_horizontal_margin"
+	android:background="?attr/selectableItemBackground">
+
+	<TextView
+		android:id="@+id/forumNameView"
+		android:layout_width="wrap_content"
+		android:layout_height="wrap_content"
+		android:maxLines="2"
+		android:textColor="@android:color/primary_text_light"
+		android:textSize="@dimen/text_size_medium"
+		tools:text="This is a name of a forum that is available"/>
+
+	<TextView
+		android:id="@+id/sharedByView"
+		android:layout_width="wrap_content"
+		android:layout_height="wrap_content"
+		android:layout_alignParentLeft="true"
+		android:layout_alignParentStart="true"
+		android:layout_below="@+id/forumNameView"
+		android:layout_marginBottom="-8dp"
+		android:paddingTop="@dimen/margin_medium"
+		android:textColor="@android:color/secondary_text_light"
+		android:textSize="@dimen/text_size_small"
+		tools:text="Shared by Megalox"/>
+
+	<Button
+		android:id="@+id/acceptButton"
+		style="@style/BriarButtonFlat.Positive"
+		android:layout_width="wrap_content"
+		android:layout_height="wrap_content"
+		android:text="@string/dialog_button_accept"
+		android:layout_below="@+id/sharedByView"
+		android:layout_alignParentRight="true"
+		android:layout_alignParentEnd="true"/>
+
+	<Button
+		android:id="@+id/declineButton"
+		style="@style/BriarButtonFlat.Negative"
+		android:layout_width="wrap_content"
+		android:layout_height="wrap_content"
+		android:text="@string/dialog_button_decline"
+		android:layout_below="@+id/sharedByView"
+		android:layout_toLeftOf="@+id/acceptButton"
+		android:layout_toStartOf="@+id/acceptButton"/>
+
+	<View style="@style/Divider.ForumList"
+	      android:layout_below="@+id/acceptButton"
+	      android:layout_alignParentLeft="true"
+	      android:layout_alignParentStart="true"/>
+
+</RelativeLayout>
+
diff --git a/briar-android/res/values/strings.xml b/briar-android/res/values/strings.xml
index e5d21dec3eef771234840b9167a10436bda80f47..e0daa614ee482e2e339368664b921378b7bd76c0 100644
--- a/briar-android/res/values/strings.xml
+++ b/briar-android/res/values/strings.xml
@@ -102,6 +102,7 @@
 	<string name="forum_post_hint">Type forum post</string>
 	<string name="available_forums_title">Available Forums</string>
 	<string name="forum_joined_toast">Joined Forum</string>
+	<string name="forum_declined_toast">Forum Invitation Declined</string>
 	<string name="shared_by_format">Shared by %s</string>
 	<string name="no_contacts_prompt">You don\'t have any contacts. Add a contact now?</string>
 	<string name="add_button">Add</string>
diff --git a/briar-android/src/org/briarproject/android/contact/BaseContactListAdapter.java b/briar-android/src/org/briarproject/android/contact/BaseContactListAdapter.java
index 590c7a2d747c8c5936786a717d83d1d64ae13b78..908afe48307fa1bd9ed3ce80baac447a9be1fe2a 100644
--- a/briar-android/src/org/briarproject/android/contact/BaseContactListAdapter.java
+++ b/briar-android/src/org/briarproject/android/contact/BaseContactListAdapter.java
@@ -21,14 +21,14 @@ import static android.support.v7.util.SortedList.INVALID_POSITION;
 public abstract class BaseContactListAdapter<VH extends BaseContactListAdapter.BaseContactHolder>
 		extends RecyclerView.Adapter<VH> {
 
-	protected SortedList<ContactListItem> contacts;
+	protected final SortedList<ContactListItem> contacts;
 	protected final OnItemClickListener listener;
 	protected Context ctx;
 
 	public BaseContactListAdapter(Context context, OnItemClickListener listener) {
 		this.ctx = context;
 		this.listener = listener;
-		this.contacts = new SortedList<ContactListItem>(ContactListItem.class,
+		this.contacts = new SortedList<>(ContactListItem.class,
 				new SortedListCallBacks());
 	}
 
diff --git a/briar-android/src/org/briarproject/android/forum/AvailableForumsActivity.java b/briar-android/src/org/briarproject/android/forum/AvailableForumsActivity.java
index f685e0d0670c8e169aff0a2e89de7b9b37d6db97..dd7a722e7518cdbf206f410a65b8e8e40f278c95 100644
--- a/briar-android/src/org/briarproject/android/forum/AvailableForumsActivity.java
+++ b/briar-android/src/org/briarproject/android/forum/AvailableForumsActivity.java
@@ -1,34 +1,30 @@
 package org.briarproject.android.forum;
 
 import android.os.Bundle;
-import android.view.View;
-import android.widget.AdapterView;
-import android.widget.AdapterView.OnItemClickListener;
-import android.widget.ListView;
+import android.support.v7.widget.LinearLayoutManager;
 import android.widget.Toast;
 
 import org.briarproject.R;
 import org.briarproject.android.AndroidComponent;
 import org.briarproject.android.BriarActivity;
-import org.briarproject.android.util.ListLoadingProgressBar;
+import org.briarproject.android.util.BriarRecyclerView;
 import org.briarproject.api.contact.Contact;
-import org.briarproject.api.contact.ContactId;
 import org.briarproject.api.db.DbException;
 import org.briarproject.api.db.NoSuchGroupException;
 import org.briarproject.api.event.ContactRemovedEvent;
 import org.briarproject.api.event.Event;
 import org.briarproject.api.event.EventBus;
 import org.briarproject.api.event.EventListener;
+import org.briarproject.api.event.ForumInvitationReceivedEvent;
 import org.briarproject.api.event.GroupAddedEvent;
 import org.briarproject.api.event.GroupRemovedEvent;
-import org.briarproject.api.event.MessageValidatedEvent;
 import org.briarproject.api.forum.Forum;
 import org.briarproject.api.forum.ForumManager;
 import org.briarproject.api.forum.ForumSharingManager;
-import org.briarproject.api.sync.ClientId;
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.List;
 import java.util.logging.Logger;
 
 import javax.inject.Inject;
@@ -36,16 +32,15 @@ import javax.inject.Inject;
 import static android.widget.Toast.LENGTH_SHORT;
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
-import static org.briarproject.android.util.CommonLayoutParams.MATCH_MATCH;
+import static org.briarproject.android.forum.AvailableForumsAdapter.AvailableForumClickListener;
 
 public class AvailableForumsActivity extends BriarActivity
-implements EventListener, OnItemClickListener {
+		implements EventListener, AvailableForumClickListener {
 
 	private static final Logger LOG =
 			Logger.getLogger(AvailableForumsActivity.class.getName());
 
-	private AvailableForumsAdapter adapter = null;
-	private ListView list = null;
+	private AvailableForumsAdapter adapter;
 
 	// Fields that are accessed from background threads must be volatile
 	@Inject protected volatile ForumManager forumManager;
@@ -56,15 +51,13 @@ implements EventListener, OnItemClickListener {
 	public void onCreate(Bundle state) {
 		super.onCreate(state);
 
-		adapter = new AvailableForumsAdapter(this);
-		list = new ListView(this);
-		list.setLayoutParams(MATCH_MATCH);
-		list.setAdapter(adapter);
-		list.setOnItemClickListener(this);
+		setContentView(R.layout.activity_available_forums);
 
-		// Show a progress bar while the list is loading
-		ListLoadingProgressBar loading = new ListLoadingProgressBar(this);
-		setContentView(loading);
+		adapter = new AvailableForumsAdapter(this, this);
+		BriarRecyclerView list =
+				(BriarRecyclerView) findViewById(R.id.availableForumsView);
+		list.setLayoutManager(new LinearLayoutManager(this));
+		list.setAdapter(adapter);
 	}
 
 	@Override
@@ -113,11 +106,12 @@ implements EventListener, OnItemClickListener {
 					LOG.info("No forums available, finishing");
 					finish();
 				} else {
-					setContentView(list);
 					adapter.clear();
+					List<AvailableForumsItem> list =
+							new ArrayList<>(available.size());
 					for (ForumContacts f : available)
-						adapter.add(new AvailableForumsItem(f));
-					adapter.sort(AvailableForumsItemComparator.INSTANCE);
+						list.add(new AvailableForumsItem(f));
+					adapter.addAll(list);
 				}
 			}
 		});
@@ -145,37 +139,33 @@ implements EventListener, OnItemClickListener {
 				LOG.info("Forum removed, reloading");
 				loadForums();
 			}
-		} else if (e instanceof MessageValidatedEvent) {
-			MessageValidatedEvent m = (MessageValidatedEvent) e;
-			ClientId c = m.getClientId();
-			if (m.isValid() && !m.isLocal()
-					&& c.equals(forumSharingManager.getClientId())) {
-				LOG.info("Available forums updated, reloading");
-				loadForums();
-			}
+		} else if (e instanceof ForumInvitationReceivedEvent) {
+			LOG.info("Available forums updated, reloading");
+			loadForums();
 		}
 	}
 
-	public void onItemClick(AdapterView<?> parent, View view, int position,
-			long id) {
-		AvailableForumsItem item = adapter.getItem(position);
-		Collection<ContactId> shared = new ArrayList<>();
-		for (Contact c : item.getContacts()) shared.add(c.getId());
-		subscribe(item.getForum(), shared);
-		String joined = getString(R.string.forum_joined_toast);
-		Toast.makeText(this, joined, LENGTH_SHORT).show();
+	public void onItemClick(AvailableForumsItem item, boolean accept) {
+		respondToInvitation(item.getForum(), accept);
+
+		// show toast
+		int res = R.string.forum_declined_toast;
+		if (accept) res = R.string.forum_joined_toast;
+		Toast.makeText(this, res, LENGTH_SHORT).show();
 	}
 
-	private void subscribe(final Forum f, final Collection<ContactId> shared) {
+	private void respondToInvitation(final Forum f, final boolean accept) {
 		runOnDbThread(new Runnable() {
 			public void run() {
 				try {
-					forumManager.addForum(f);
+					forumSharingManager.respondToInvitation(f, accept);
 				} catch (DbException e) {
 					if (LOG.isLoggable(WARNING))
 						LOG.log(WARNING, e.toString(), e);
 				}
+				loadForums();
 			}
 		});
 	}
+
 }
diff --git a/briar-android/src/org/briarproject/android/forum/AvailableForumsAdapter.java b/briar-android/src/org/briarproject/android/forum/AvailableForumsAdapter.java
index e5969e3bea3b795970c4fc82daef77734ed2de17..0cd0e818123de7c70ef8c405786a1599d99a51c9 100644
--- a/briar-android/src/org/briarproject/android/forum/AvailableForumsAdapter.java
+++ b/briar-android/src/org/briarproject/android/forum/AvailableForumsAdapter.java
@@ -1,57 +1,160 @@
 package org.briarproject.android.forum;
 
 import android.content.Context;
+import android.support.v7.util.SortedList;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
-import android.widget.LinearLayout;
+import android.widget.Button;
 import android.widget.TextView;
 
 import org.briarproject.R;
-import org.briarproject.android.util.LayoutUtils;
 import org.briarproject.api.contact.Contact;
 import org.briarproject.util.StringUtils;
 
 import java.util.ArrayList;
 import java.util.Collection;
 
-import static android.text.TextUtils.TruncateAt.END;
-import static android.widget.LinearLayout.VERTICAL;
+class AvailableForumsAdapter extends
+		RecyclerView.Adapter<AvailableForumsAdapter.AvailableForumViewHolder> {
 
-class AvailableForumsAdapter extends ArrayAdapter<AvailableForumsItem> {
+	private final Context ctx;
+	private final AvailableForumClickListener listener;
+	private final SortedList<AvailableForumsItem> forums =
+			new SortedList<>(AvailableForumsItem.class,
+					new SortedListCallBacks());
 
-	private final int pad;
+	AvailableForumsAdapter(Context ctx,
+			AvailableForumClickListener listener) {
 
-	AvailableForumsAdapter(Context ctx) {
-		super(ctx, android.R.layout.simple_expandable_list_item_1,
-				new ArrayList<AvailableForumsItem>());
-		pad = LayoutUtils.getPadding(ctx);
+		this.ctx = ctx;
+		this.listener = listener;
 	}
 
 	@Override
-	public View getView(int position, View convertView, ViewGroup parent) {
-		AvailableForumsItem item = getItem(position);
-		Context ctx = getContext();
-
-		LinearLayout layout = new LinearLayout(ctx);
-		layout.setOrientation(VERTICAL);
-
-		TextView name = new TextView(ctx);
-		name.setTextSize(18);
-		name.setSingleLine();
-		name.setEllipsize(END);
-		name.setPadding(pad, pad, pad, pad);
-		name.setText(item.getForum().getName());
-		layout.addView(name);
-
-		TextView status = new TextView(ctx);
-		status.setPadding(pad, 0, pad, pad);
-		Collection<String> names = new ArrayList<String>();
+	public AvailableForumViewHolder onCreateViewHolder(ViewGroup parent,
+			int viewType) {
+
+		View v = LayoutInflater.from(ctx)
+				.inflate(R.layout.list_item_available_forum, parent,  false);
+		return new AvailableForumViewHolder(v);
+	}
+
+	@Override
+	public void onBindViewHolder(AvailableForumViewHolder ui, int position) {
+		final AvailableForumsItem item = getItem(position);
+
+		ui.name.setText(item.getForum().getName());
+
+		Collection<String> names = new ArrayList<>();
 		for (Contact c : item.getContacts()) names.add(c.getAuthor().getName());
-		String format = ctx.getString(R.string.shared_by_format);
-		status.setText(String.format(format, StringUtils.join(names, ", ")));
-		layout.addView(status);
+		ui.sharedBy.setText(ctx.getString(R.string.shared_by_format,
+				StringUtils.join(names, ", ")));
+
+		ui.accept.setOnClickListener(new View.OnClickListener() {
+			@Override
+			public void onClick(View v) {
+				listener.onItemClick(item, true);
+			}
+		});
+		ui.decline.setOnClickListener(new View.OnClickListener() {
+			@Override
+			public void onClick(View v) {
+				listener.onItemClick(item, false);
+			}
+		});
+	}
+
+	@Override
+	public int getItemCount() {
+		return forums.size();
+	}
 
-		return layout;
+	public AvailableForumsItem getItem(int position) {
+		return forums.get(position);
 	}
+
+	public void add(AvailableForumsItem item) {
+		forums.add(item);
+	}
+
+	public void addAll(Collection<AvailableForumsItem> list) {
+		forums.addAll(list);
+	}
+
+	public void clear() {
+		forums.clear();
+	}
+
+	protected static class AvailableForumViewHolder
+			extends RecyclerView.ViewHolder {
+
+		public final ViewGroup layout;
+		public final TextView name;
+		public final TextView sharedBy;
+		public final Button accept;
+		public final Button decline;
+
+		public AvailableForumViewHolder(View v) {
+			super(v);
+
+			layout = (ViewGroup) v;
+			name = (TextView) v.findViewById(R.id.forumNameView);
+			sharedBy = (TextView) v.findViewById(R.id.sharedByView);
+			accept = (Button) v.findViewById(R.id.acceptButton);
+			decline = (Button) v.findViewById(R.id.declineButton);
+		}
+	}
+
+	private class SortedListCallBacks
+			extends SortedList.Callback<AvailableForumsItem> {
+
+		@Override
+		public int compare(AvailableForumsItem o1,
+				AvailableForumsItem o2) {
+			return String.CASE_INSENSITIVE_ORDER
+					.compare(o1.getForum().getName(),
+							o2.getForum().getName());
+		}
+
+		@Override
+		public void onInserted(int position, int count) {
+			notifyItemRangeInserted(position, count);
+		}
+
+		@Override
+		public void onRemoved(int position, int count) {
+			notifyItemRangeRemoved(position, count);
+		}
+
+		@Override
+		public void onMoved(int fromPosition, int toPosition) {
+			notifyItemMoved(fromPosition, toPosition);
+		}
+
+		@Override
+		public void onChanged(int position, int count) {
+			notifyItemRangeChanged(position, count);
+		}
+
+		@Override
+		public boolean areContentsTheSame(AvailableForumsItem oldItem,
+				AvailableForumsItem newItem) {
+			return oldItem.getForum().equals(newItem.getForum()) &&
+					oldItem.getContacts().equals(newItem.getContacts());
+		}
+
+		@Override
+		public boolean areItemsTheSame(AvailableForumsItem oldItem,
+				AvailableForumsItem newItem) {
+			return oldItem.getForum().equals(newItem.getForum());
+		}
+	}
+
+
+	interface AvailableForumClickListener {
+		void onItemClick(AvailableForumsItem item, boolean accept);
+	}
+
 }
diff --git a/briar-android/src/org/briarproject/android/forum/AvailableForumsItemComparator.java b/briar-android/src/org/briarproject/android/forum/AvailableForumsItemComparator.java
deleted file mode 100644
index c9098edb00538c785a876f99238690c7165b33e0..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/forum/AvailableForumsItemComparator.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package org.briarproject.android.forum;
-
-import java.util.Comparator;
-
-class AvailableForumsItemComparator implements Comparator<AvailableForumsItem> {
-
-	static final AvailableForumsItemComparator INSTANCE =
-			new AvailableForumsItemComparator();
-
-	public int compare(AvailableForumsItem a, AvailableForumsItem b) {
-		if (a == b) return 0;
-		String aName = a.getForum().getName();
-		String bName = b.getForum().getName();
-		return String.CASE_INSENSITIVE_ORDER.compare(aName, bName);
-	}
-}