为什么我的变量设置后为空?
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
.
在解释之前,我将向您展示我的(简短)代码:
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
.