0

I have a chat app, which opens a Websocket to a server. The app has 2 modules -

  1. chat sdk: which handles the connection plus back and forth messaging.
  2. ui: which handles adapters and views

The chat UI is on a fragment hosted by an activity.

Everything worked fine but when i decided to use persistence on device rotation, i have problems. When i rotate the device, the websocket reconnects (which is normal),the activity is recreated so is the fragment too.

After device rotation and some debugging, i saw that my messageList is properly filled with any added items (ie message texts) but not the UI. When i type a text from the EditText and press send, the item is properly displayed in the UI, BUT when i receive response from server the UI is not updated even if the message is added to the messageList.

I read in similar posts that the RecyclerView adapter is updating the old fragment after the rotation. Is this the case? And if this is the case, why when i send a message from the EditText it is properly displayed but not when from the onMessage of my WebSocket?

I tried "android:configChanges="screenSize|orientation|screenLayout" w/o any results. I override the onConfigurationChanged and force the adapter to update the views, with no result

@Override
public void onConfigurationChanged(@NonNull Configuration newConfig) {

    super.onConfigurationChanged(newConfig);

    if(messagesAdapter!=null){
        messagesAdapter.notifyDataSetChanged();
    }
}

I save the fragment to restore it in my activity

public class MessageActivity extends AppCompatActivity {
private MessageFragment fragment;

@Override
protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_message);


    if (savedInstanceState == null) {
        fragment = MessageFragment.newInstance();

        getSupportFragmentManager().beginTransaction()
                .replace(R.id.container, fragment)
                .commitNow();
    }else{
        fragment = (MessageFragment) getSupportFragmentManager().getFragment(savedInstanceState, "messageFragment");
    }

}

@Override
public void onBackPressed() {

    finishAffinity();
}


@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);

    //Save the fragment's instance
    getSupportFragmentManager().putFragment(outState, "messageFragment", fragment);
}}

And i also save and retrieve my messageList

 @Override
public void onSaveInstanceState(@NonNull Bundle outState) {

    super.onSaveInstanceState(outState);
    //saving the state of the chat
    outState.putParcelableArrayList("messages", messageArrayList);
    try {
        Log.d(TAG, "messagelist in save instance " + messageArrayList.size());
    }catch (NullPointerException e){
        e.printStackTrace();
    }
    outState.putString("dialogId", messageArrayList.get(0).getDialogId());
}

onMessage from websocket

@Override
public void onMessage(ArrayList<Message> data) {

    if (!messageArrayList.isEmpty() && messageArrayList.get(messageArrayList.size() - 1).getServerMessageType() == Constants.TYPE_TYPING_ON) {
        messageArrayList.remove(messageArrayList.size() - 1);
    }
    this.messageArrayList.addAll(data);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && isFragmentAttached) {

        mActivity.runOnUiThread(new Runnable() {
            @Override
            public void run() {

                if (omiliaClient != null) {
                    updateUi(messageArrayList, omiliaClient.user2);

                }
            }
        });
    }
}
iliasPs
  • 15
  • 8
  • Since you mentioned that your UI is updated/restored after the screen rotation. I need to understand the code snippet where you receive the new data from the callback you've attached to the Api/websocket. Are you correctly updating the same instance of the dataset i.e. `messageArrayList` ? – sud007 Jan 14 '20 at 11:55
  • added the snippet for you to see. But after debugging i saw that the messages are properly added to the list – iliasPs Jan 14 '20 at 11:59
  • Does this answer your question? [Recyclerview not populating with data after orientation change](https://stackoverflow.com/questions/36083044/recyclerview-not-populating-with-data-after-orientation-change) – sud007 Jan 14 '20 at 11:59
  • @sud007 The selected answer on the thread you sent me was not the case, but the second answer was. But Venky below answered earlier. Thanks a lot. – iliasPs Jan 14 '20 at 12:17

1 Answers1

1

Call setRetainInstance(true) in either of onCreate(), onCreateView() or onActivityCreated() methods.

sud007
  • 5,824
  • 4
  • 56
  • 63
Ankit Tale
  • 1,924
  • 4
  • 17
  • 30
  • When i rotate, the views are restored perfectly and as expected. The problem starts when i start receiving messages after the rotation. – iliasPs Jan 14 '20 at 11:48
  • This a bad behaviour. It can be a workaround but not suggested as you would never know that your `RecyclerView` is unnecessarily refreshing the whole adpater. `notifyDataSetChanged` is a heavyweight operation, caution should be exercised for adapters with big/unknown data set size. Personally fixed a huge issue in production app due to this simple iceberg-esque issue. – sud007 Jan 14 '20 at 11:49
  • @iliasPs But the way you are storing fragment instance is really wrong. – Ankit Tale Jan 14 '20 at 11:52
  • Please elaborate ? – iliasPs Jan 14 '20 at 11:53
  • Agree with @Venky this is not how you store the instance of a Fragment. – sud007 Jan 14 '20 at 11:58
  • @iliasPs I think the storing and restoring of fragment is main culprit in updating User Interface – Ankit Tale Jan 14 '20 at 11:59
  • @Venky i was having the same thoughts. But i didn't find a solution – iliasPs Jan 14 '20 at 12:01
  • @iliasPs Have you tried setRetainInstance(true) in onCreate, onCreateView() or onActivityCreated(). – Ankit Tale Jan 14 '20 at 12:04
  • https://developer.android.com/reference/android/app/Fragment#setRetainInstance(boolean) – Ankit Tale Jan 14 '20 at 12:04
  • @Venky, edit your answer with the setRetainInstance(true) and i ll accept it. Thanks a lot – iliasPs Jan 14 '20 at 12:09