【问题标题】:Why is my variable null when I've set it?为什么我的变量设置为空?
【发布时间】:2020-12-14 22:50:54
【问题描述】:

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

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 的元素,为什么“房间”对象为空?我不明白。

我已经这样做了:What is a NullPointerException, and how do I fix it?

但这对我没有帮助。

我看到许多用户无缘无故地投票减分。所以我希望这个问题是可以接受的。

【问题讨论】:

  • @aran 好吧,标题很弱,不具体。不确定它是否值得投反对票,但这肯定是一个糟糕的问题。
  • 重命名,所以它不是锤子。
  • 请在贴代码墙之前描述问题。

标签: java android nullpointerexception


【解决方案1】:

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

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

FragmentTransaction isn't applied instantly after calling commit()

主线程不会等待,它只会继续执行下一行代码,无论 commit() 是否完成(甚至没有开始)。

因此,来自 SecondFragmentonCreateView() 在您的主线程调用之前并未执行:当您尝试调用 @ 时,room 仍未初始化987654332@就可以了。

为了避免这种情况,通过调用 executePendingTransactions 强制更新:

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

来自文档的一些信息:

executePendingTransactions --- 使用 FragmentTransaction#commit 提交 FragmentTransaction 后,它会被调度执行 在进程的主线程上异步。如果你想 立即执行任何挂起的操作,你可以调用它 功能。


在简历中

executePendingTransactions 提供commit 类似于“同步”性质的东西。它将强制进程立即执行在FragmentTransaction 上安排的所有任务。

这样,您将保证在您调用s.roomText()onCreateView() 已正确执行(并且room 已初始化),避免了NullPointerException 这让你很困惑。

【讨论】:

  • 使用回调不是更好吗?
  • 我不明白你的意思。回调只是可以同步/异步执行的代码片段。这里的问题在于同步。另外,当你只需要调用一个方法来实现相同的行为时,我并没有真正理解实现同步回调的意义。
  • 回调的全部意义在于它发生在其他事情发生之后,在这种情况下是提交完成。
  • 回调实际上会在提交之后被调用。紧随其后:关键是提交是异步的,因此在调用回调时它可能尚未完成甚至启动。这是在 commit() 行之后立即出现的。您会遇到与 OP 相同的问题。
  • @aran 谢谢你的解释。我认为类似的事情正在朝着那个方向发展......但我想我永远不会发现它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-12-23
  • 1970-01-01
  • 2013-12-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多