Avoid race conditions when updating the UI from events.

This commit is contained in:
akwizgran
2016-10-17 10:54:00 +01:00
parent 50a70f7649
commit 2140a290e4
14 changed files with 239 additions and 93 deletions

View File

@@ -24,13 +24,15 @@ public abstract class ThreadItemAdapter<I extends ThreadItem>
private final NestedTreeList<I> items = new NestedTreeList<>();
private final Map<I, ValueAnimator> animatingItems = new HashMap<>();
private final ThreadItemListener<I> listener;
private final LinearLayoutManager layoutManager;
// highlight not dependant on time
private I replyItem;
// temporary highlight
private I addedItem;
private final ThreadItemListener<I> listener;
private final LinearLayoutManager layoutManager;
private volatile int revision = 0;
public ThreadItemAdapter(ThreadItemListener<I> listener,
LinearLayoutManager layoutManager) {
@@ -290,6 +292,29 @@ public abstract class ThreadItemAdapter<I extends ThreadItem>
animatingItems.remove(item);
}
/**
* Returns the adapter's revision counter. This method should be called on
* any thread before starting an asynchronous load that could overwrite
* other changes to the adapter, and called again on the UI thread before
* applying the changes from the asynchronous load. If the revision has
* changed between the two calls, the asynchronous load should be restarted
* without applying its changes. Otherwise {@link #incrementRevision()}
* should be called before applying the changes.
*/
public int getRevision() {
return revision;
}
/**
* Increments the adapter's revision counter. This method should be called
* on the UI thread before applying any changes to the adapter that could
* be overwritten by an asynchronous load.
*/
@UiThread
public void incrementRevision() {
revision++;
}
protected interface ThreadItemListener<I> {
void onItemVisible(I item);

View File

@@ -29,6 +29,7 @@ import org.briarproject.api.sync.MessageId;
import org.briarproject.util.StringUtils;
import java.util.Collection;
import java.util.logging.Logger;
import static android.support.design.widget.Snackbar.make;
import static android.view.View.GONE;
@@ -42,6 +43,9 @@ public abstract class ThreadListActivity<G extends NamedGroup, I extends ThreadI
protected static final String KEY_INPUT_VISIBILITY = "inputVisibility";
protected static final String KEY_REPLY_ID = "replyId";
private static final Logger LOG =
Logger.getLogger(ThreadListActivity.class.getName());
protected A adapter;
protected BriarRecyclerView list;
protected TextInputView textInput;
@@ -106,18 +110,24 @@ public abstract class ThreadListActivity<G extends NamedGroup, I extends ThreadI
protected abstract void onNamedGroupLoaded(G groupItem);
private void loadItems() {
final int revision = adapter.getRevision();
getController().loadItems(
new UiResultExceptionHandler<Collection<I>, DbException>(
this) {
new UiResultExceptionHandler<Collection<I>, DbException>(this) {
@Override
public void onResultUi(Collection<I> items) {
if (items.isEmpty()) {
list.showData();
if (revision == adapter.getRevision()) {
adapter.incrementRevision();
if (items.isEmpty()) {
list.showData();
} else {
adapter.setItems(items);
list.showData();
if (replyId != null)
adapter.setReplyItemById(replyId);
}
} else {
adapter.setItems(items);
list.showData();
if (replyId != null)
adapter.setReplyItemById(replyId);
LOG.info("Concurrent update, reloading");
loadItems();
}
}
@@ -271,6 +281,7 @@ public abstract class ThreadListActivity<G extends NamedGroup, I extends ThreadI
}
protected void addItem(final I item, boolean isLocal) {
adapter.incrementRevision();
adapter.add(item);
if (isLocal && adapter.isVisible(item)) {
displaySnackbarShort(getItemPostedString());