provide fallback in case synchronizing around message list fails for some reason

Daniel Gultsch created

Change summary

src/main/java/eu/siacs/conversations/ui/ConversationFragment.java | 57 
1 file changed, 32 insertions(+), 25 deletions(-)

Detailed changes

src/main/java/eu/siacs/conversations/ui/ConversationFragment.java 🔗

@@ -131,7 +131,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
 	public static final String STATE_PHOTO_URI = ConversationFragment.class.getName() + ".take_photo_uri";
 	private static final String STATE_LAST_MESSAGE_UUID = "state_last_message_uuid";
 
-	final protected List<Message> messageList = new ArrayList<>();
+	private final List<Message> messageList = new ArrayList<>();
 	private final PendingItem<ActivityResult> postponedActivityResult = new PendingItem<>();
 	private final PendingItem<String> pendingConversationsUuid = new PendingItem<>();
 	private final PendingItem<Bundle> pendingExtras = new PendingItem<>();
@@ -214,31 +214,33 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
 								return;
 							}
 							runOnUiThread(() -> {
-								final int oldPosition = binding.messagesView.getFirstVisiblePosition();
-								Message message = null;
-								int childPos;
-								for (childPos = 0; childPos + oldPosition < messageList.size(); ++childPos) {
-									message = messageList.get(oldPosition + childPos);
-									if (message.getType() != Message.TYPE_STATUS) {
-										break;
+								synchronized (messageList) {
+									final int oldPosition = binding.messagesView.getFirstVisiblePosition();
+									Message message = null;
+									int childPos;
+									for (childPos = 0; childPos + oldPosition < messageList.size(); ++childPos) {
+										message = messageList.get(oldPosition + childPos);
+										if (message.getType() != Message.TYPE_STATUS) {
+											break;
+										}
 									}
+									final String uuid = message != null ? message.getUuid() : null;
+									View v = binding.messagesView.getChildAt(childPos);
+									final int pxOffset = (v == null) ? 0 : v.getTop();
+									ConversationFragment.this.conversation.populateWithMessages(ConversationFragment.this.messageList);
+									try {
+										updateStatusMessages();
+									} catch (IllegalStateException e) {
+										Log.d(Config.LOGTAG, "caught illegal state exception while updating status messages");
+									}
+									messageListAdapter.notifyDataSetChanged();
+									int pos = Math.max(getIndexOf(uuid, messageList), 0);
+									binding.messagesView.setSelectionFromTop(pos, pxOffset);
+									if (messageLoaderToast != null) {
+										messageLoaderToast.cancel();
+									}
+									conversation.messagesLoaded.set(true);
 								}
-								final String uuid = message != null ? message.getUuid() : null;
-								View v = binding.messagesView.getChildAt(childPos);
-								final int pxOffset = (v == null) ? 0 : v.getTop();
-								ConversationFragment.this.conversation.populateWithMessages(ConversationFragment.this.messageList);
-								try {
-									updateStatusMessages();
-								} catch (IllegalStateException e) {
-									Log.d(Config.LOGTAG, "caught illegal state exception while updating status messages");
-								}
-								messageListAdapter.notifyDataSetChanged();
-								int pos = Math.max(getIndexOf(uuid, messageList), 0);
-								binding.messagesView.setSelectionFromTop(pos, pxOffset);
-								if (messageLoaderToast != null) {
-									messageLoaderToast.cancel();
-								}
-								conversation.messagesLoaded.set(true);
 							});
 						}
 
@@ -1586,7 +1588,12 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
 			if (pos >= 0) {
 				Message message = null;
 				for (int i = pos; i >= 0; --i) {
-					message = (Message) binding.messagesView.getItemAtPosition(i);
+					try {
+						message = (Message) binding.messagesView.getItemAtPosition(i);
+					} catch (ArrayIndexOutOfBoundsException e) {
+						//should not happen if we synchronize properly. however if that fails we just gonna try item -1
+						continue;
+					}
 					if (message.getType() != Message.TYPE_STATUS) {
 						break;
 					}