片段问题中的 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 -&gt; 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

java - 如何使用Java中的Volley库将JSON api数据放入recyclerview?

Android片段中的问题:仍然单击上一个片段

Android中的片段事务问题

片段中的片段

如何处理片段和活动中的后压