片段问题中的 NullPointerException
NullPointerException in a fragment problem
在过去的几个小时里,我一直在努力寻找我的问题的答案,在尝试了不同的方法之后,我无法解决我的问题。
我想要的是使用一个 Edittext 和一个按钮来处理该 edittext。这是我在 fragment_main.xml:
中的代码
<android.support.design.widget.TextInputLayout
android:id="@+id/text_input_email"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:errorEnabled="true">
<android.support.design.widget.TextInputEditText
android:id="@+id/email_input"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:hint="Email"
android:inputType="textEmailAddress"/>
</android.support.design.widget.TextInputLayout>
<Button
android:id="@+id/send_email_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
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: 这是我认为的 "stack trace".
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)
这并不是真正的错误,您会发现它实际上很常见。基本上任何不受代码直接控制的 ui 元素(IE:片段中由单独的 activity 使用的某些元素,或列表适配器中定义的元素。)都会给你这个警告,因为它不能保证 UI 元素存在并被实例化。
您可以在 .getText() 周围添加空检查以消除警告并防止它在元素确实为空时尝试从元素中拉出。
if(textInputEmail != null){
String emailInput = textInputEmail.getEditText().getText().toString().trim();
}
对于崩溃:
这是因为 android:onClick
属性仅在 Activity
上声明该方法时有效,而不是 Fragment
上。我建议永远不要使用 android:onClick
属性。
相反,在 onCreateView
中解析你的 Button
就像你在 TextInputLayout
中一样,然后手动调用 button.setOnClickListener(view -> buttonSend(view));
来分配点击监听器。
对于警告:
这是因为TextInputLayout
将它的getEditText()
方法声明为@Nullable
(意思是它不保证你在调用它时会得到一个非空值)。
原因是 TextInputLayout
在 inflation(您在 XML 布局中声明的 TextInputEditText
之后分配其内部 EditText
).
如果您没有将 TextInputEditText
作为 TextInputLayout
的子项包括在内,那么 getEditText()
将 return 为空。在你的情况下,你可以保证除非你改变布局,否则你会得到正确的值,所以你可以做的是做出断言以避免警告:
EditText editText = Objects.requireNonNull(textInputEmail.getEditText());
String emailInput = editText.getText().toString().trim();
如果您确定您的代码是正确的,那么只需将您的项目转换为 Kotlin 项目
Android工作室会为你做
然后异常将成为历史
问题是因为您正在投射:
textInputEmail = (TextInputLayout) view.findViewById(R.id.text_input_email);
使用:
textInputEmail = (TextInputEditText) view.findViewById(R.id.text_input_email);
在过去的几个小时里,我一直在努力寻找我的问题的答案,在尝试了不同的方法之后,我无法解决我的问题。
我想要的是使用一个 Edittext 和一个按钮来处理该 edittext。这是我在 fragment_main.xml:
中的代码<android.support.design.widget.TextInputLayout
android:id="@+id/text_input_email"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:errorEnabled="true">
<android.support.design.widget.TextInputEditText
android:id="@+id/email_input"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:hint="Email"
android:inputType="textEmailAddress"/>
</android.support.design.widget.TextInputLayout>
<Button
android:id="@+id/send_email_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
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: 这是我认为的 "stack trace".
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)
这并不是真正的错误,您会发现它实际上很常见。基本上任何不受代码直接控制的 ui 元素(IE:片段中由单独的 activity 使用的某些元素,或列表适配器中定义的元素。)都会给你这个警告,因为它不能保证 UI 元素存在并被实例化。
您可以在 .getText() 周围添加空检查以消除警告并防止它在元素确实为空时尝试从元素中拉出。
if(textInputEmail != null){
String emailInput = textInputEmail.getEditText().getText().toString().trim();
}
对于崩溃:
这是因为 android:onClick
属性仅在 Activity
上声明该方法时有效,而不是 Fragment
上。我建议永远不要使用 android:onClick
属性。
相反,在 onCreateView
中解析你的 Button
就像你在 TextInputLayout
中一样,然后手动调用 button.setOnClickListener(view -> buttonSend(view));
来分配点击监听器。
对于警告:
这是因为TextInputLayout
将它的getEditText()
方法声明为@Nullable
(意思是它不保证你在调用它时会得到一个非空值)。
原因是 TextInputLayout
在 inflation(您在 XML 布局中声明的 TextInputEditText
之后分配其内部 EditText
).
如果您没有将 TextInputEditText
作为 TextInputLayout
的子项包括在内,那么 getEditText()
将 return 为空。在你的情况下,你可以保证除非你改变布局,否则你会得到正确的值,所以你可以做的是做出断言以避免警告:
EditText editText = Objects.requireNonNull(textInputEmail.getEditText());
String emailInput = editText.getText().toString().trim();
如果您确定您的代码是正确的,那么只需将您的项目转换为 Kotlin 项目 Android工作室会为你做 然后异常将成为历史
问题是因为您正在投射:
textInputEmail = (TextInputLayout) view.findViewById(R.id.text_input_email);
使用:
textInputEmail = (TextInputEditText) view.findViewById(R.id.text_input_email);