-1

I want to update text in a fragment when the messages come.

In the Main Activity I do the connection with wsuri. Every message that I received the callback onTextMessage is triggered. The library I use is autoBahn.

public class MainActivity extends AppCompatActivity{

private   static  WebSocketConnection mConnection = new WebSocketConnection();  

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.intent_root_activity);

        if(savedInstanceState == null){
                frag_Home = new HomeFragment();
                fragmentManager.beginTransaction().add(R.id.fragmentContent, frag_Home, getString(R.string.TAG_HOME)).commit();
            }else{
                if(fragmentManager.findFragmentByTag(getString(R.string.TAG_HOME)) == null){
                    frag_Home = new HomeFragment();
                    fragmentManager.beginTransaction().add(R.id.fragmentContent, frag_Home, getString(R.string.TAG_HOME)).commit();
                }

        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        // Start Connection
        Connect(ipAdress);
        Log.i("ROOT ACTIVITY", "onResume");
    }


    // Function callback events
    private void Connect(String ipAddress){

    final String wsuri = "ws://" + ipAddress + ":" + port;

        try {
            // Handle Websocket Event
            mConnection.connect(wsuri, new WebSocketHandler() {

                @Override
                public void onOpen() {
                    Log.d("WIFI", "onOpen: Conneced to "+ wsuri);
                }



                @Override
                public void onTextMessage(String payload) { 
                    HomeFragment home = (HomeFragment) getSupportFragmentManager().findFragmentByTag(getString(R.string.TAG_HOME));
                    ((TextView)home.getView().findViewById(R.id.txtMsg)).setText(payload);
                }

                Override
                public void onClose(int code, String reason) {
                }
            }   
        }
    }
}   

All run fine the texts updates correctly but when I rotate my phone and when I receive a message I get an error

java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.View test.test.com.test.HomeFragment.getView()' on a null object reference 

And the texts never updates again.

1 Answers1

0

Short Answer

This can be fixed with adding android:configChanges="orientation" in the manifest of your activity but this can lead to UI bugs because you're left on your own to handle the changes of the orientation.

Long Answer

mConnection.connect(wsuri, new WebSocketHandler() {

            @Override
            public void onOpen() {
                Log.d("WIFI", "onOpen: Conneced to "+ wsuri);
            }

This inner anonymous class WebSocketHandler contains an implicit reference to the current instance of your MainActivity on the point of creation but that instance will be trashed by the Android system on orientation change. So what you're seeing after the orientation change is now a different instance than what your WebSocketHandler class points to, resulting to having null returned in your findFragmentByTag call because the HomeFragment that you're trying to request for was already cleaned up in the old instance of your MainActivity. Also this causes a memory leak because your WebSocketHandler will prevent the old instance of MainActivity to be GC'ed.

What I suggest you to do is have an entirely separate class that will handle the websocket connection and is not an inner class of the any Activity. Or you can use android:configChanges="orientation" and make sure that you handle the orientation changes properly through

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    // Checks the orientation of the screen
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        //handle the orientation change, ex change/rearrange fragments
    }
}
James Baltar
  • 231
  • 1
  • 8
  • But when rotate the device not loose the connection. It semms have the same instace because i use static. If i remove static the connection lost on rotate – Dimitris KOutsos Jun 08 '17 at 15:25
  • Yes it doesnt disconnect or gets cleaned up because it's static but the implicit reference to the MainActivity is retained on the point of creation of WebSocketHandler. So upon rotation your WebSocketHandler will not be pointing to the new MainActivity instance which is currently displayed on screeen. The MainActivity instance that your WebSocketHandler is pointing to is the old instance and is pending for cleanup but the system cant clean it up because of your WebSocketHandler pointing to it implicitly. You can add logs on onDestroy of your MainActivity and see that it is destroyed on rotate – James Baltar Jun 09 '17 at 06:41
  • ok. I Understand.. The solution which gives worked. I put the websocket handler in the non ui fragment with setRetainstance(true) on the onCreate event. Thanks a lot – Dimitris KOutsos Jun 09 '17 at 08:10