I'm working on a chat app. The ChatFragment has a chatList that get data from Firebase realtime database and add one by one item using childEventListener (onChildAdded).

When orientation change or user leave the fragment, I want to keep the chatList that were received, remove the listener and then re-attach listener when user go back to chat fragment or when orientation change completed.

The problem is, when activity/fragment was re-created, the childEventListener was lost, so I have to re-create new listener. But then the chatList was duplicated because the onChildAdded was called and add all item again.

I tried

FirebaseDatabase.getInstance().setPersistenceEnabled(true);

But it didn't work, it still called onChildAdded. And then, every query using singleValueEventListener will not work properly because it requests to the cached data, not the real time database.

I think of comparing the chatList's item with the item was received in onChildAdded, if it exists, just skip it. But it's quite waste time, and not what I want to do: keep the current data, no need to reload from firebase DB, and also keep listener for new item.

Or can I save all the listener and get it back somehow, I don't know.

Here is some code of my activity and fragment

In the HomeActivity, the code to save fragment to bundle

@Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        if (chatListFragment.isAdded())
            getSupportFragmentManager().putFragment(outState, ChatListFragment.TAG, chatListFragment);
    }

Then I get it back in onCreate(). In here all fragment's fields were lost: chatList, listener...

if(getSupportFragmentManager().getFragment(savedInstanceState, ChatListFragment.TAG) != null) {
                chatListFragment = getSupportFragmentManager().getFragment(savedInstanceState, ChatListFragment.TAG);
            }

In the ChatFragment, I save the chat list in bundle

@Override
    public void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putParcelableArrayList(KEY_CHAT_LIST, chatList);
        outState.putInt(KEY_CURRENT_POSITION, currentItemPosition);
        //TODO: save data
    }

And I get it back in onActivityCreated()

@Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        if(savedInstanceState != null) {
            chatList = savedInstanceState.getParcelableArrayList(KEY_CHAT_LIST);
            currentItemPosition = savedInstanceState.getInt(KEY_CURRENT_POSITION);
            chatListAdapter.setChatList(chatList);
            chatListAdapter.notifyDataSetChanged();

            //the method below gets data from firebase DB by creating a 
            //childEventListener, that mean it gets all the chat item again 
            //but if I don't call it, I can't listen to onChildAdded :((

            //presenter.loadChatList(chatList);
        } else {
            chatList.clear();
            chatListAdapter.setChatList(chatList);
            chatListAdapter.notifyDataSetChanged();

            presenter.loadChatList(chatList);
        }
    }

So, in short, I want to keep both data and all the firebase listeners for new item/changed item when re-start/re-create activity/fragment, and not using setPersistenceEnabled(true).

Sorry for my bad English. Thank you so much.

1 Answers

0
Loren Rogers On

Not knowing WHY the activity(and fragment) are recreated, Saving the instance state in the fragment is the correct thing to do. However, you should retrieve the data in Fragment.onCreate (savedInstanceState). THis is the first method called and a good place to set up non-graphical data