Devin S
Devin S

Reputation: 155

Multiple Realtime database calls through the onResume() Fragment lifecycle method

I'm trying to create an app which involves a userstatus field. There is userStatus and customUserStatus. If the customUserStatus is not null, then the userStatus will be set to the customUserStatus value, else it will be set to "Online". This all occurs within the onResume() fragment method.

The issue that I am having is that the code for the onResume() is called multiple times...even when the fragment is not open at all.

As you can see, the onResume code is executed multiple times, setting the user status more than once.

(Chat Fragment exit)
    2021-02-10 11:59:34.828 22682-22682/com.user.myapp W/status: The chat fragment is no longer visible and the onStop has been called. Setting userStatus to offline

(ChatFragment opened)
    2021-02-10 11:59:34.866 22682-22682/com.user.myapp W/status: setting the user status to custom user status... At the Gym
    2021-02-10 11:59:34.868 22682-22682/com.user.myapp W/status: setting the user status to custom user status... At the Gym

(App exit - you can see that onResume() called multiple times...)
    2021-02-10 11:59:46.201 22682-22682/com.user.myapp W/status: Setting user status to offline in the MainActivity
    2021-02-10 11:59:46.260 22682-22682/com.user.myapp W/status: setting the user status to custom user status... At the Gym
    2021-02-10 11:59:46.262 22682-22682/com.user.myapp W/status: setting the user status to custom user status... At the Gym
    2021-02-10 11:59:46.263 22682-22682/com.user.myapp W/status: setting the user status to custom user status... At the Gym

My onResume method:

  1. Get the user object from the database
  2. Check if the user has set a custom status
  3. If not, then set their status to the default -> "online"
  4. Else, set their status to the customStatus

I am using the onResume as a way to check if the current fragment has been opened, and if so, then it will set the user's status. I want it to only be executed once.

    @Override
    public void onResume() {
        super.onResume();
        //Log.w("status", "The chat fragment is now visible and the onResume has been called. Setting userStatus to online");

    String userId = FirebaseAuth.getInstance().getCurrentUser().getUid();
    DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Users").child(userId);
    reference.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot snapshot) {
            User user = snapshot.getValue(User.class);
            if(user.getCustomuserstatus() != null){
                if(user.getUserstatus() != user.getCustomuserstatus()){
                    setUserStatus(user.getCustomuserstatus());
                    Log.w("status", "setting the user status to custom user status... " + user.getCustomuserstatus());
                }
            } else {
                Toast.makeText(getActivity(), user.getCustomuserstatus(), Toast.LENGTH_SHORT).show();
                setUserStatus("online");
                Log.w("status", "setting the user status to online from the onresume");
            }
        }

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

        }
    });

Upvotes: 0

Views: 69

Answers (1)

Frank van Puffelen
Frank van Puffelen

Reputation: 599601

You have no control over how often Android calls onResume. So your options are:

  1. Track whether your code in onResume has already run with a more global/static flag, and only execute it when it hasn't run before.
  2. Remove the listener in onPause, so that next time onResume runs you're attaching the first listener again.

I prefer the second approach, as it leads to cleaner code and has less chance of leaving database listeners lingering for activities/fragments that the user is not looking at anymore.

Upvotes: 1

Related Questions