fix rare concurrent modification in muc user search

Daniel Gultsch created

Change summary

src/main/java/eu/siacs/conversations/ui/MucUsersActivity.java | 39 +++-
1 file changed, 26 insertions(+), 13 deletions(-)

Detailed changes

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

@@ -13,8 +13,13 @@ import android.view.inputmethod.InputMethodManager;
 import android.widget.EditText;
 import android.widget.Toast;
 
+import androidx.annotation.NonNull;
 import androidx.databinding.DataBindingUtil;
 
+import com.google.common.collect.Collections2;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Ordering;
+
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Locale;
@@ -56,30 +61,38 @@ public class MucUsersActivity extends XmppActivity implements XmppConnectionServ
     private void loadAndSubmitUsers() {
         if (mConversation != null) {
             allUsers = mConversation.getMucOptions().getUsers();
-            Collections.sort(allUsers);
             submitFilteredList(mSearchEditText != null ? mSearchEditText.getText().toString() : null);
         }
     }
 
-    private void submitFilteredList(String search) {
+    private void submitFilteredList(final String search) {
         if (TextUtils.isEmpty(search)) {
-            userAdapter.submitList(allUsers);
+            userAdapter.submitList(Ordering.natural().immutableSortedCopy(allUsers));
         } else {
             final String needle = search.toLowerCase(Locale.getDefault());
-            ArrayList<MucOptions.User> filtered = new ArrayList<>();
-            for(MucOptions.User user : allUsers) {
-                final String name = user.getName();
-                final Contact contact = user.getContact();
-                if (name != null && name.toLowerCase(Locale.getDefault()).contains(needle) || contact != null && contact.getDisplayName().toLowerCase(Locale.getDefault()).contains(needle)) {
-                    filtered.add(user);
-                }
-            }
-            userAdapter.submitList(filtered);
+            userAdapter.submitList(
+                    Ordering.natural()
+                            .immutableSortedCopy(
+                                    Collections2.filter(
+                                            this.allUsers,
+                                            user -> {
+                                                final String name = user.getName();
+                                                final Contact contact = user.getContact();
+                                                return name != null
+                                                                && name.toLowerCase(
+                                                                                Locale.getDefault())
+                                                                        .contains(needle)
+                                                        || contact != null
+                                                                && contact.getDisplayName()
+                                                                        .toLowerCase(
+                                                                                Locale.getDefault())
+                                                                        .contains(needle);
+                                            })));
         }
     }
 
     @Override
-    public boolean onContextItemSelected(MenuItem item) {
+    public boolean onContextItemSelected(@NonNull MenuItem item) {
         if (!MucDetailsContextMenuHelper.onContextItemSelected(item, userAdapter.getSelectedUser(), this)) {
             return super.onContextItemSelected(item);
         }