片段问题中的 NullPointerException
Posted
技术标签:
【中文标题】片段问题中的 NullPointerException【英文标题】:NullPointerException in a fragment problem 【发布时间】:2019-05-01 19:57:29 【问题描述】:在过去的几个小时里,我一直在努力寻找问题的答案,但在尝试了不同的方法后,我无法解决我的问题。
我想要的是使用一个 Edittext 和一个对该 edittext 执行某些操作的按钮。这是我在 fragment_main.xml 中的代码:
<android.support.design.widget.TextInputLayout
android:id="@+id/text_input_email"
android:layout_
android:layout_
app:errorEnabled="true">
<android.support.design.widget.TextInputEditText
android:id="@+id/email_input"
android:layout_
android:layout_
android:hint="Email"
android:inputType="textEmailAddress"/>
</android.support.design.widget.TextInputLayout>
<Button
android:id="@+id/send_email_button"
android:layout_
android:layout_
android:text="Send"/>
还有我在 MainFragment.java 中的代码:
import ...
public class MainFragment extends Fragment
private TextInputLayout textInputEmail;
public MainFragment()
// Required empty public constructor
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
View view = inflater.inflate(R.layout.fragment_main, container, false);
textInputEmail = (TextInputLayout) view.findViewById(R.id.text_input_email);
Button send_button = (Button) view.findViewById(R.id.send_email_button);
send_button.setOnClickListener(view -> buttonSend(view));
return view;
private boolean validateEmail()
String emailInput = textInputEmail.getEditText().getText().toString().trim();
if (emailInput.isEmpty())
textInputEmail.setError("Field can't be empty!");
return false;
else
textInputEmail.setError(null);
return true;
public void buttonSend(View v)
if (!validateEmail() )
return;
/*do something*/
为此,我的任何一个代码都没有出现任何错误,因此我并不真正了解问题所在。我在 MainActivity.java 中收到的警告是“'getText' 可能会在 validateEmail() 方法中的 .getText() 部分产生'java.lang.NullPointerException'”。
希望我解释得很好。感谢任何试图提供帮助的人!
编辑:我相信我解释得不够清楚。我忘了说当我按下发送按钮时,我的应用程序会立即崩溃。这就是我要解决的问题。
编辑 2:这是我认为的“堆栈跟踪”。
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.luka.straingeremailapp, PID: 2728
java.lang.IllegalStateException: Could not find method buttonSend(View) in a parent or ancestor Context for android:onClick attribute defined on view class android.support.v7.widget.AppCompatButton
at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.resolveMethod(AppCompatViewInflater.java:424)
at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:381)
at android.view.View.performClick(View.java:6291)
at android.view.View$PerformClick.run(View.java:24931)
at android.os.Handler.handleCallback(Handler.java:808)
at android.os.Handler.dispatchMessage(Handler.java:101)
at android.os.Looper.loop(Looper.java:166)
at android.app.ActivityThread.main(ActivityThread.java:7425)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:245)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:921)
【问题讨论】:
能否提供应用崩溃时打印的堆栈跟踪信息? 我已经准备好这样做了,你能告诉我具体怎么做吗? @pantank14 粘贴应用崩溃后出现在 android studio 的 logcat 中的日志 我相信我已经将它添加到上面的主要问题中。 【参考方案1】:对于崩溃:
这是因为android:onClick
属性仅在方法在Activity
上声明时有效,在Fragment
上无效。我建议永远不要使用 android:onClick
属性。
相反,将onCreateView
中的Button
解析为TextInputLayout
,并手动调用button.setOnClickListener(view -> buttonSend(view));
来分配点击监听器。
对于警告:
这是因为TextInputLayout
将其getEditText()
方法声明为@Nullable
(这意味着它不保证在调用它时会得到一个非空值)。
原因是TextInputLayout
在膨胀后分配了它的内部EditText
(您在XML 布局中声明的TextInputEditText
)。
如果您没有将 TextInputEditText
包含为 TextInputLayout
的子项,则 getEditText()
将返回 null。在您的情况下,您可以保证除非您更改该布局,否则您将获得正确的值,因此您可以做的是做出该断言以避免警告:
EditText editText = Objects.requireNonNull(textInputEmail.getEditText());
String emailInput = editText.getText().toString().trim();
【讨论】:
我已将“editText”行添加到 MainFragment.java 中。有警告说:“调用需要 API 级别 19(当前最小值为 16):java.util.Objects#requireNonNull”。运行应用程序时,一切似乎又正常了,但是当我单击发送按钮时,应用程序又崩溃了。 好吧,如果你是 minSdkVersion 16,你只需要在你的项目中定义你自己的。如果您仍然看到问题,则需要提供崩溃的堆栈跟踪。 我相信我已将堆栈跟踪添加到主要问题中。 更新了答案——这个问题与警告无关,但我已经把这两个部分都留给了答案。 我已经删除了Button xml文件的onClick属性,并为它添加了一个id属性。在 MainFragment.java 中,我在 onCreateView 中添加了两行。在添加的第二行中,我收到一个错误,指向“视图”并说“变量'视图'已经在范围内定义”。我该怎么办?我还用新代码更新了主要问题。【参考方案2】:这并不是真正的错误,您会发现它实际上很常见。基本上任何不由代码直接控制的 ui 元素(即:片段中的某些东西被单独的活动使用,或在列表适配器中定义的元素。)都会给你这个警告,因为它不能保证 UI 元素存在并且被实例化。 您可以在 .getText() 周围添加一个空检查,以使警告静音并防止它尝试从元素中拉出(如果它确实为空)。
if(textInputEmail != null)
String emailInput = textInputEmail.getEditText().getText().toString().trim();
【讨论】:
我相信我解释得不够好。我忘了说当我按下发送按钮时,我的应用程序会立即崩溃。这就是我要解决的问题。【参考方案3】:如果您确定您的代码是正确的,那么只需将您的项目转换为 Kotlin 项目 Android Studio 会为你做这件事 然后异常将成为历史
【讨论】:
【参考方案4】:问题是因为你正在投射:
textInputEmail = (TextInputLayout) view.findViewById(R.id.text_input_email);
使用:
textInputEmail = (TextInputEditText) view.findViewById(R.id.text_input_email);
【讨论】:
以上是关于片段问题中的 NullPointerException的主要内容,如果未能解决你的问题,请参考以下文章
android中的NullPointerException,同时在menu.xml中使用actionLayout