RecyclerView дублирует items,больше чем необходимо. В первый раз когда перехожу на экран все нормально, если выйти и вернуться происходит,дублирование

я пишу приложение чат на языке Java, используя FireBase и у меня возникла проблемма. Проблемма заключается в том, что когда я повторно после возврата в Activity_Main перехожу на экран контактов, контакты дублируются в RecyclerView, каждый раз это модет быть разное колличество. При чем передаваемые в адаптер данные верны.

К сожалению, я не смог самостоятельно найти и исправить причину.

Заранее благодарю Вас за помощь.

Заранее извиняюсь, если что-то не очень доходчиво изложил, я мнгновенно готов ответить на Ваши вопросы и уточнить.

Структура базы данных: Структура базы данных

UsersПользователь

введите сюда описание изображения

введите сюда описание изображения

введите сюда описание изображения

На телефоне это выглядит так:

введите сюда описание изображения и вот так: введите сюда описание изображения

public class MainActivity extends AppCompatActivity {


private Toolbar toolbar;
private FloatingActionButton createChatBtn;
private FirebaseUser currentUser;
private FirebaseAuth mAuth;
private DatabaseReference rootRef;// ссылка для доступа к базе данных
private RecyclerView recyclerView;
private TextView batteryLevel;
private BroadCastBattery broadCastBattery;
private int READ_CONTACTS_PERMISSION = 1;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mAuth = FirebaseAuth.getInstance();
    currentUser = mAuth.getCurrentUser();
    rootRef = FirebaseDatabase.getInstance().getReference();
    createChatBtn = findViewById(R.id.fab_bt);
    toolbar = findViewById(R.id.toolBar);
    batteryLevel = findViewById(R.id.battery_level);
    broadCastBattery = new BroadCastBattery();
    setSupportActionBar(toolbar);
    recyclerView = findViewById(R.id.incoming_message_recyclerview);
    MainActivityAdapter mainActivityAdapter = new MainActivityAdapter(new ArrayList<>());
    LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
    recyclerView.setHasFixedSize(true);
    recyclerView.setLayoutManager(linearLayoutManager);
    recyclerView.setAdapter(mainActivityAdapter);
    onStart();
    onResume();
    onPause();
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_GRANTED) {
    new Thread(() -> {
        try {
           readContacts();
        } catch (Exception exception) {
            runOnUiThread(() -> Toast.makeText(MainActivity.this, exception.toString(), Toast.LENGTH_SHORT).show());
        }
    }).start();
    }else{
        requestReadContactsPermission();
    }


    createChatBtn.setOnClickListener(v -> {

        Intent contactIntent = new Intent(MainActivity.this, ContactsActivity.class);
        startActivity(contactIntent);
    });
    REF_DATABASE_MESSAGES_ROOT.child(currentUser.getUid()).addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot snapshot) {
            for (DataSnapshot child1 : snapshot.getChildren()) {
                for (DataSnapshot child2 : child1.getChildren()) {

                    if (child2.getKey().equals("LastMessage")) {
                        getMessageFromDB(child1.getKey(), "LastMessage").addOnSuccessListener(message -> {

                            if (message.getSenderId().equals(currentUser.getUid())) {
                                getUserFromDB(message.getReceiverId()).addOnSuccessListener(user -> {
                                    mainActivityAdapter.addIncomingMessage(new IncomingMessage(user.getUsername(), message.getText(), user.getImageURL(), user.getId()));
                                });
                            } else {
                                getUserFromDB(message.getSenderId()).addOnSuccessListener(user -> {
                                    mainActivityAdapter.addIncomingMessage(new IncomingMessage(user.getUsername(), message.getText(), user.getImageURL(), user.getId()));
                                });
                            }
                        });
                    }
                }
            }
        }


        @Override
        public void onCancelled(@NonNull DatabaseError error) {

        }
    });
}


protected void onStart() {
    super.onStart();
    if (currentUser == null) {
        Intent welcomeIntent = new Intent(this, WelcomeActivity.class);
        startActivity(welcomeIntent);
    } else {

    }
}

protected void onResume() {
    super.onResume();
    AppStates.updateState(AppStates.ONLINE, rootRef, currentUser);
    registerReceiver(broadCastBattery, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
}

protected void onPause() {
    super.onPause();
    AppStates.updateState(AppStates.OFFLINE, rootRef, currentUser);
    unregisterReceiver(broadCastBattery);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    super.onCreateOptionsMenu(menu);
    getMenuInflater().inflate(R.menu.options_menu, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
    super.onOptionsItemSelected(item);
    if (item.getItemId() == R.id.menu_settings) {
        Intent settingsIntent = new Intent(this, SettingsActivity.class);
        startActivity(settingsIntent);
    }

    if (item.getItemId() == R.id.menu_logout) {

        Dialog logout_dialog = new Dialog(this);
        logout_dialog.setContentView(R.layout.logout_dialog);
        logout_dialog.show();
        Button yes_bt = logout_dialog.findViewById(R.id.yes_bt);
        Button no_bt = logout_dialog.findViewById(R.id.no_bt);
        yes_bt.setOnClickListener(v -> {
            mAuth.signOut();
            Intent loginIntent = new Intent(MainActivity.this, LoginActivity.class);
            startActivity(loginIntent);
            logout_dialog.cancel();
        });
        no_bt.setOnClickListener(v -> logout_dialog.cancel());

    }
    return true;
}


public void contactMatchCheck(List<Contact> contacts) {
    rootRef.child("Phones").get().addOnSuccessListener(dataSnapshot -> {

        for (DataSnapshot child : dataSnapshot.getChildren()) {
            for (Contact contact : contacts) {
                if (contact.getPhoneNumber().equals(child.getKey())) {
                    rootRef.child("Phone_contacts").child(currentUser.getUid()).child(child.getKey()).setValue(child.getValue().toString());

                }
            }
        }


    });
}


@SuppressLint("Range")
public void readContacts() {
    ArrayList<Contact> contacts = new ArrayList<>();
    getUserFromDB(currentUser.getUid()).addOnSuccessListener(user -> {
        ContentResolver cr = getContentResolver();
        Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI, null,
                null, null, null);
        if (cur.getCount() > 0) {
            while (cur.moveToNext()) {
                String id = cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID));
                String name = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
                Log.i("Names", name);
                if (Integer.parseInt(cur.getString(cur.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) {
                    // Query phone here. Covered next
                    Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = " + id, null, null);
                    while (phones.moveToNext()) {
                        String phone = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)).replaceAll("[\\s,-]", "");

                        if (phone.charAt(0) == '0') {
                            Contact contact = new Contact(name, user.getCountryCode() + phone.replaceFirst("0", ""));
                            contacts.add(contact);
                        } else {
                            Contact contact = new Contact(name, phone);
                            contacts.add(contact);
                        }
                    }
                    phones.close();
                }
            }
        }
        cur.close();
        contactMatchCheck(contacts);
    });
}

private class BroadCastBattery extends BroadcastReceiver {


    @Override

    public void onReceive(Context context, Intent intent) {

        int battery = intent.getIntExtra("level", 0);

        batteryLevel.setText("Battery level: " + String.valueOf(battery) + "%");
        REF_DATABASE_BATTERY.child(currentUser.getUid()).setValue(new Battery(currentUser.getUid(), String.valueOf(battery) + "%")).addOnCompleteListener(new OnCompleteListener<Void>() {
            @Override
            public void onComplete(@NonNull Task<Void> task) {
                if (task.isSuccessful()) {

                } else {
                    String exception = Objects.requireNonNull(task.getException()).toString();
                    Toast.makeText(MainActivity.this, "An error has occurred:" + exception, Toast.LENGTH_SHORT).show();
                }
            }
        });
    }

}
private void requestReadContactsPermission() {
    //checks if we need to explain to user why this permission is needed for
    if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_CONTACTS)) {
        new AlertDialog.Builder(this).setTitle("Permission needed").setMessage("This permission is needed to read your phone contacts.").setPositiveButton("ok", (dialog, which) -> ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_CONTACTS}, READ_CONTACTS_PERMISSION)).setNegativeButton("cancel", (dialog, which) -> startActivity(new Intent(this,WelcomeActivity.class))).create().show();
    } else {
        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_CONTACTS}, READ_CONTACTS_PERMISSION);
    }
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == READ_CONTACTS_PERMISSION) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            readContacts();
        }
    }
}
public Task<User> getUserFromDB(String uid) {
    return REF_DATABASE_USERS_ROOT.child(uid).get().continueWith(task -> task.getResult().getValue(User.class));
}

public Task<Message> getMessageFromDB(String uid, String mid) {
    return REF_DATABASE_MESSAGES_ROOT.child(currentUser.getUid()).child(uid).child(mid).get().continueWith(task -> task.getResult().getValue(Message.class));
}

}

Метод readContacts считывает все контакты с телефона. Метод contactMatchCheck проверяет, совпадают ли номера телефонов полученные в методе readContacts с номерами зарегистрированных пользователей в узле Phones и если да, то записывает их в узел с сurrentId в узле Phone_contacts.

Экран контактов

public class ContactsActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private ImageButton backBt;
private Toolbar toolbar;
private FirebaseAuth mAuth;
private DatabaseReference rootRef;
private FirebaseUser currentUser;
private TextView batteryLevel;
private BroadCastBattery broadCastBattery;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_contacts);
    backBt = findViewById(R.id.back_bt);
    toolbar = findViewById(R.id.toolBar);
    setSupportActionBar(toolbar);
    mAuth = FirebaseAuth.getInstance();
    currentUser = mAuth.getCurrentUser();
    rootRef = FirebaseDatabase.getInstance().getReference();
    batteryLevel = findViewById(R.id.battery_level);
    broadCastBattery = new BroadCastBattery();
    recyclerView = findViewById(R.id.recyclerView);
    UserAdapter userAdapter = new UserAdapter(new ArrayList<>());
    LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
    recyclerView.setHasFixedSize(true);
    recyclerView.setLayoutManager(linearLayoutManager);
    recyclerView.setAdapter(userAdapter);
    onResume();
    onPause();
    onStop();

    backBt.setOnClickListener(v -> {

        Intent mainIntent = new Intent(ContactsActivity.this, MainActivity.class);
        startActivity(mainIntent);
    });
    REF_DATABASE_USERS_ROOT.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot snapshot) {
            rootRef.child("Phone_contacts").child(currentUser.getUid()).get().addOnSuccessListener(dataSnapshot -> {
                for (DataSnapshot phoneContact : dataSnapshot.getChildren()) {
                    getUserFromDB(phoneContact.getValue(String.class)).addOnSuccessListener(user -> userAdapter.addUser(user));
                }
                runOnUiThread(() -> toolbar.setSubtitle(userAdapter.getItemCount() + " contacts"));

            });

        }
        @Override
        public void onCancelled(@NonNull DatabaseError error) {

        }
    });
}

protected void onResume() {
    super.onResume();
    AppStates.updateState(AppStates.ONLINE, rootRef, currentUser);
    registerReceiver(broadCastBattery, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
}

protected void onPause() {
    super.onPause();
    AppStates.updateState(AppStates.OFFLINE, rootRef, currentUser);

}

protected void onStop() {
    super.onStop();
    unregisterReceiver(broadCastBattery);
}


private class BroadCastBattery extends BroadcastReceiver {


    @Override

    public void onReceive(Context context, Intent intent) {

        int battery = intent.getIntExtra("level", 0);

        batteryLevel.setText("Battery level: " + String.valueOf(battery) + "%");
        REF_DATABASE_BATTERY.child(currentUser.getUid()).setValue(new Battery(currentUser.getUid(), String.valueOf(battery) + "%")).addOnCompleteListener(new OnCompleteListener<Void>() {
            @Override
            public void onComplete(@NonNull Task<Void> task) {
                if (task.isSuccessful()) {

                } else {
                    String exception = Objects.requireNonNull(task.getException()).toString();
                    Toast.makeText(ContactsActivity.this, "An error has occurred:" + exception, Toast.LENGTH_SHORT).show();
                }
            }
        });
    }

}

public Task<User> getUserFromDB(String uid) {
    return REF_DATABASE_USERS_ROOT.child(uid).get().continueWith(task -> task.getResult().getValue(User.class));
}

}

В классе ContactActivity в onCreate я повесил слушателя на узел Users, при изменении данных у пользователя,я обновляю контакты отображенные на экране, доставая их из узла Phone_contacts.

Адаптер:

public class UserAdapter extends RecyclerView.Adapter<UserAdapter.ViewHolder> {//отвечает за добавление данных в RecyclerView
private List<User> mUsers;

//constructor
public UserAdapter(List<User> mUsers) {
    this.mUsers = mUsers;
}

public List<User> getMUsers() {
    return mUsers;
}

@NonNull
@Override
public UserAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.user_item, parent, false);
    return new ViewHolder(view);
}

@Override
//get and set data
public void onBindViewHolder(@NonNull UserAdapter.ViewHolder holder, int position) {
    User user = mUsers.get(position);
    holder.username.setText(user.getUsername());
    if (user.getState().equals("online") || user.getState().equals("typing")) {
        holder.state.setImageResource(R.color.green);
    } else {
        holder.state.setImageResource(R.color.transparent);
    }
    if (user.getImageURL() == null) {
        holder.profile_image.setImageResource(R.drawable.profile);
    } else {
        Picasso.get().load(user.getImageURL()).into(holder.profile_image);
    }
    holder.currentUserId = user.getId();
}

@Override
public int getItemCount() {
    return mUsers.size();
}

public void addUser(User user) {
    mUsers.add(user);
    notifyItemInserted(mUsers.size() - 1);
}

@Override
public long getItemId(int position) {
    return position;
}


/* public void addAllUsers(ArrayList<User> users){
         mUsers.addAll(users);
         notifyAll();
     }*/
@SuppressLint("NotifyDataSetChanged")
public void deleteAllUsers() {
    mUsers.clear();
    notifyDataSetChanged();
}

public void clear() {
    int size = mUsers.size();
    mUsers.clear();
    notifyItemRangeRemoved(0, size);
}


static class ViewHolder extends RecyclerView.ViewHolder { //отвечает за элемент списка
    public final TextView username;
    public final ImageView profile_image;
    public final CircleImageView state;
    public String currentUserId;


    public ViewHolder(View itemView) {
        super(itemView);
        //init views
        profile_image = itemView.findViewById(R.id.profile_image);
        username = itemView.findViewById(R.id.tvItemUsername);
        state = itemView.findViewById(R.id.state);


        //handle item click
        itemView.setOnClickListener(v -> {
            Intent singleChatIntent = new Intent(itemView.getContext(), SingleChatActivity.class);
            singleChatIntent.putExtra("ContactID", currentUserId);
            itemView.getContext().startActivity(singleChatIntent);
        });
    }
}

}


Ответы (0 шт):