为什么我的变量设置后为空?

Why is my variable null when I've set it?

在解释之前,我将向您展示我的(简短)代码:

public class MainActivity extends AppCompatActivity 
{
    FrameLayout simpleFrameLayout;
    TabLayout tabLayout;
    SecondFragment s = new SecondFragment();
    
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        simpleFrameLayout = (FrameLayout) findViewById(R.id.simpleFrameLayout);
        tabLayout = (TabLayout) findViewById(R.id.simpleTabLayout);
// Create a new Tab named "First"
        TabLayout.Tab firstTab = tabLayout.newTab();
        firstTab.setText("First"); // set the Text for the first Tab
    
// first tab
        tabLayout.addTab(firstTab); // add  the tab at in the TabLayout
// Create a new Tab named "Second"
        TabLayout.Tab secondTab = tabLayout.newTab();
        secondTab.setText("Second"); // set the Text for the second Tab
        
        tabLayout.addTab(secondTab); // add  the tab  in the TabLayout

        Fragment fragment = null;
        fragment = new FirstFragment();
        FragmentManager fm = getSupportFragmentManager();
        FragmentTransaction ft = fm.beginTransaction();
        ft.replace(R.id.simpleFrameLayout, fragment);
        ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
        ft.commit();
        
        tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
                @Override
                public void onTabSelected(TabLayout.Tab tab) {
// get the current selected tab's position and replace the fragment accordingly
                    Fragment fragment = null;
                    switch (tab.getPosition()) {
                        case 0:
                            fragment = new FirstFragment();
                            myMenu.findItem(R.id.telefono).setVisible(false);
                            break;
                        case 1:
                            fragment = s;
                            myMenu.findItem(R.id.telefono).setVisible(true);
                            break;
                    }
                    FragmentManager fm = getSupportFragmentManager();
                    FragmentTransaction ft = fm.beginTransaction();
                    ft.replace(R.id.simpleFrameLayout, fragment);
                    ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
                    ft.commit();
                }
                @Override
                public void onTabUnselected(TabLayout.Tab tab) {

                }

                @Override
                public void onTabReselected(TabLayout.Tab tab) {

                }
            });
    }
    
    public void conectar(String nombre, String ip, int puerto) {
        //Code...
        Executor executor = Executors.newSingleThreadExecutor();
        executor.execute(new Runnable() {
                @Override
                public void run() {
                    Looper.prepare();
                    runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                try{
                                    //Code...
                                    try {
                                        //Code
                                        TabLayout.Tab tab = tabLayout.getTabAt(1);
                                        tab.select();
                                        s.roomText(param1);
                                        
                                    }
                                    catch(SocketTimeoutException ex)
                                    {

                                    }
                                }
                                catch(Exception e){
                                    StringWriter sw = new StringWriter();
                                    e.printStackTrace(new PrintWriter(sw));
                                    String stacktrace = sw.toString();
                                    // create an email intent to send to yourself
                                    final Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
                                    emailIntent.setType("plain/text");
                                    emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, new String[] { "lets.think.android@gmail.com" });
                                    emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "App Error Report");
                                    emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, stacktrace);
                                    // start the email activity - note you need to start it with a chooser
                                    startActivity(Intent.createChooser(emailIntent, "Send error report..."));
                                }
                            }
                        });
                    
                }
            });

    }
}

第二个片段:

package com.mycompany.myapp;
    
    import android.os.Bundle;
    import android.support.v4.app.Fragment;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.*;
    
    public class SecondFragment extends Fragment
    {
        EditText chat, room;
        
        public SecondFragment() {
    // Required empty public constructor
        }
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
        }
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
    // Inflate the layout for this fragment
            View view = inflater.inflate(R.layout.fragment_second, container, false);
            room = (EditText) view.findViewById(R.id.mainEditText1);
            chat = (EditText) view.findViewById(R.id.chatEditText1);
            return view;
        }
        
        public void roomText(String t){
            room.setText(t);
        }
    }

我正在尝试设置来自 MainActivity 的片段的 editText 的文本。为此,我在 SecondFragment 中编写了一个方法,该方法应该更改该 editText 的文本。并且这个方法是在MainActivity中调用的。

如果事先选择了选项卡并且实际上应该已经创建了 SecondFragment 的元素,为什么“room”对象为空?我不明白。

我已经在路上了:What is a NullPointerException, and how do I fix it?

但这对我没有帮助。

我看到很多用户无缘无故地在投票中扣分。所以我希望这个问题可以接受。

room变量在调用onCreateView()时赋值;这 应该 在你的 onTabSelected 方法中调用 ft.commit() 之后发生。

但是commit的默认行为是异步,所以:

FragmentTransaction isn't applied instantly after calling commit()

主线程不会等待,它会继续执行下一行代码,而不管 commit() 是否完成(或什至没有开始)。

因此,SecondFragment 中的 onCreateView() 在您的主线程调用之前未执行:room 当您尝试调用 setText() 时仍未初始化。

为了避免这种情况,通过调用 executePendingTransactions:

强制更新
//....
ft.replace(R.id.simpleFrameLayout, fragment);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.commit();
ft.executePendingTransactions();

文档中的一些信息:

executePendingTransactions --- After a FragmentTransaction is committed with FragmentTransaction#commit, it is scheduled to be executed asynchronously on the process's main thread. If you want to immediately execute any pending operations, you can call this function.


简历中

executePendingTransactions 提供 commit 类似 “同步”性质的东西。它将强制进程立即执行在 FragmentTransaction.

上安排的所有任务

这样,您将保证在您调用 [=27= 时 onCreateView() 已正确执行(并且 room 已初始化) ], 避免让你感到困惑的 NullPointerException.