【问题标题】:NullPoinerException in Fragment when handling dialog onclicklistener处理对话框 onclicklistener 时片段中的 NullPointerException
【发布时间】:2020-05-07 13:55:57
【问题描述】:

我想在片段中调用自定义对话框,用户将在其中添加一些数据,我想在该片段中获取它。

为此我创建了一个对话框类和一个特殊的布局(我认为没有必要在这里发布):

public class IntervalsDialog extends DialogFragment {
private TextView interval1, interval2, interval3, interval4;
private EditText weight1, weight2, weight3, weight4;

private IntervalDialogListener listener;



@Override
public void onAttach(@NonNull Context context) {
    super.onAttach(context);
    try {
        listener = (IntervalDialogListener) context;
    } catch (ClassCastException e) {
        throw new ClassCastException(context.toString() + "you must implement IntervalsDialogListener");
    }
}

@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

    LayoutInflater inflater = getActivity().getLayoutInflater();
    View view = inflater.inflate(R.layout.dialog_layout, null);
    builder.setView(view).setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            dialog.dismiss();
        }
    }).setPositiveButton("Go further", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            if (weight1.getText().toString().trim().matches("") || weight2.getText().toString().trim().matches("") ||
                    weight3.getText().toString().trim().matches("") || weight4.getText().toString().trim().matches("")){
                Toast.makeText(getContext(), "You must fill in all the blanks to continue", Toast.LENGTH_SHORT).show();
            }
            else{
                int w1 = Integer.valueOf(weight1.getText().toString().trim());
                int w2 = Integer.valueOf(weight2.getText().toString().trim());
                int w3 = Integer.valueOf(weight3.getText().toString().trim());
                int w4 = Integer.valueOf(weight4.getText().toString().trim());
                listener.onPositiveButtonClicked(w1, w2, w3, w4);
            }
        }
    });

    interval1 = view.findViewById(R.id.interval1);
    interval2 = view.findViewById(R.id.interval2);
    interval3 = view.findViewById(R.id.interval3);
    interval4 = view.findViewById(R.id.interval4);

    weight1 = view.findViewById(R.id.weight1);
    weight2 = view.findViewById(R.id.weight2);
    weight3 = view.findViewById(R.id.weight3);
    weight4 = view.findViewById(R.id.weight4);

    setIntervals();
    return builder.create();
}

public interface IntervalDialogListener{
    void onPositiveButtonClicked(int weigh1, int weight2, int weight3, int weight4);
}

private void setIntervals(){
    int dayStart = 360;
    int dayEnd = 1320;
    ArrayList<Interval> idealInt = new ArrayList<>();
    int dayInterval = (dayEnd - dayStart)/4;
    for (int i = dayStart; i < dayEnd; i+= dayInterval) {
        idealInt.add(new Interval(i, i + dayInterval));
    }
    interval1.setText(idealInt.get(0).toString());
    interval2.setText(idealInt.get(1).toString());
    interval3.setText(idealInt.get(2).toString());
    interval4.setText(idealInt.get(3).toString());
}
}
class Interval{
private int start, end;

Interval(int start, int end){
    this.start = start;
    this.end = end;
}
public String toString() {
    return (toTime(start) + " - " + toTime(end));
}
private static String toTime (int a) {
    String s = "";
    int b = a/60;
    int c = a%60;
    if (c < 10) {
        s =  b + " : " + 0 + c;
    }
    else {
        s =  b + " : " + c;
    }
    return s;
}
}

我遇到了一个问题,我的 MainActivity 无法转换为侦听器。我关注this answer,并首先将数据发送到我的 MainActivity:

 @Override
public void onPositiveButtonClicked(int weigh1, int weight2, int weight3, int weight4) {
    AddDataFragment fragment = new AddDataFragment();
    fragment.getDataFromMainActivity(weigh1, weight2, weight3, weight4);
}

然后编写了一个在我的片段中获取这些数据的方法(我希望,到目前为止,我所做的一切都是正确的):

  public void getDataFromMainActivity(int weigh1, int weight2, int weight3, int weight4){
   Toast.makeText(getContext(), weigh1 + " -- " + weight2 + " -- " +  weight3 + " -- " +  weight4, Toast.LENGTH_LONG).show();
   AddDataFragmentDirections.ActionSort action = AddDataFragmentDirections.actionSort();
   action.setCurrentDate(currentDateGot);
   action.setWeight1(weigh1);
   action.setWeight2(weight2);
   action.setWeight3(weight3);
   action.setWeight4(weight4);
   Navigation.findNavController(getView()).navigate(action);
  }

然后我只想通过 Toast 消息检查数据是否正确保存。然后我得到这个错误:

 java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference
    at android.widget.Toast.<init>(Toast.java:114)
    at android.widget.Toast.makeText(Toast.java:277)
    at android.widget.Toast.makeText(Toast.java:267)
    at com.example.chronosaur.ui.AddDataFragment.getDataFromMainActivity(AddDataFragment.java:232)
    at com.example.chronosaur.ui.MainActivity.onPositiveButtonClicked(MainActivity.java:44)
    at com.example.chronosaur.ui.IntervalsDialog$1.onClick(IntervalsDialog.java:64)
    at com.android.internal.app.AlertController$ButtonHandler.handleMessage(AlertController.java:166)
    ...

为什么会出现这个错误?我错过了什么?请帮我。感谢您的帮助。

【问题讨论】:

  • 当您调用 getDataFromMainActivity 片段未附加到主机 Activity 时,这意味着上下文为空。
  • 我怎样才能附上它?
  • 您使用导航组件的权利应该附加到导航主机。
  • 它不是主要片段。已经附加了一个(家庭片段),我从家里导航到这个。
  • 也许我做错了什么...你能解释一下,如何将它附加到 NavHost 吗? MainActivity 中有我的 NavHost 片段:&lt;fragment android:id="@+id/fragment" android:name="androidx.navigation.fragment.NavHostFragment" android:layout_width="match_parent" android:layout_height="match_parent" app:defaultNavHost="true" app:navGraph="@navigation/nav_graph1" android:layout_above="@+id/bottom_nav"/&gt;

标签: java android android-fragments dialog


【解决方案1】:

您的 DialogFragment 从未附加到您的活动中。实例化您的 AddDataFragment 后,使用以下方式将其附加到您的活动中。

FragmentManager fm = getSupportFragmentManager();
fragment.show(fm, "tag");

如果您的 minSdk 不低于 23,请忽略以下部分。

getContext() 是一种 API 23+ 方法,可能会在较低 API 设备上产生异常。

在您的类中创建一个Context 变量来存储上下文。

...    
private Context context; //add this

@Override
public void onAttach(@NonNull Context context) {
    super.onAttach(context);
    this.context = context; //add this
    ...
}

并将getContext() 替换为context,例如Toast 使用:

Toast.makeText(context, weigh1 + " -- " + weight2 + " -- " +  weight3 + " -- " +  weight4, Toast.LENGTH_LONG).show();

【讨论】:

  • 但是我的 onAttach 方法在一个单独的类 IntervalsDialog 中,我从一个片段中调用 Toast。我如何访问这个contextvariable?
  • 是的,在您创建 listener 变量之后,在您的 IntervalsDialog 类中创建它。请记住,当您调用 fragment.show(fm,"tag") 时将调用 onAttach,否则不会调用。
猜你喜欢
  • 1970-01-01
  • 2023-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-31
  • 1970-01-01
  • 1970-01-01
  • 2014-04-28
相关资源
最近更新 更多