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.
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
}
}