Android 触发 OnTextMessage 时,getview() 上的片段返回 null

Android fragment reutn null on getview() when OnTextMessage is triggered

我想在收到消息时更新片段中的文本。

主要Activity我用wsuri做连接。我收到回调 onTextMessage 的每条消息都会被触发。我使用的图书馆是 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) {
                }
            }   
        }
    }
}   

所有 运行 很好,文本更新正确,但是当我旋转我的 phone 并且当我收到一条消息时,我收到一条错误消息

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

而且文本再也不会更新了。

简答

这可以通过在 activity 的清单中添加 android:configChanges="orientation" 来解决,但这可能会导致 UI 错误,因为您需要自己处理更改方向。

长答案

mConnection.connect(wsuri, new WebSocketHandler() {

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

这个内部匿名 class WebSocketHandler 在创建时包含对 MainActivity 当前实例的隐式引用,但该实例将被 Android 方向改变系统。所以你在方向改变后看到的是一个不同于你的 WebSocketHandler class 指向的实例,导致在你的 findFragmentByTag 调用中返回 null 因为 HomeFragment 您尝试请求的内容已在您的 MainActivity 的旧实例中清理干净。这也会导致内存泄漏,因为您的 WebSocketHandler 会阻止 MainActivity 的旧实例被 GC 处理。

我建议你做的是有一个完全独立的 class 来处理 websocket 连接,而不是任何 Activity 的内部 class。或者您可以使用 android:configChanges="orientation" 并确保通过

正确处理方向更改
@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
    }
}