将文本设置为textview在android代码中返回null

时间:2016-02-19 22:00:24

标签: java android nullpointerexception butterknife

每次更新用户界面时,我都会尝试为textview设置文本。

public class CourseDetailsFragment extends Fragment {
  private static final String TAG = "CourseDetailsFragment";
  private OnFragmentInteractionListener listener;
  private static CourseDetailsFragment instance;
  protected @Bind(R.id.courseName)TextView courseName;
  Course c;
  View view;


public static CourseDetailsFragment getInstance(){
    if (instance == null) {
        instance = new CourseDetailsFragment();
    }
    return instance;
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    instance = this;
}

@Override
public void onActivityCreated(Bundle savedInstance) {
    super.onActivityCreated(savedInstance);
    ((AppCompatActivity)getActivity()).getSupportActionBar().setLogo(R.drawable.ic_overview);
    ((AppCompatActivity)getActivity()).getSupportActionBar().setTitle("Course Detail"); //redundant?

}

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
}

@Override
public void onDetach() {
    super.onDetach();
    listener = null;
}

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    try {
        listener = (OnFragmentInteractionListener) activity;
    } catch (ClassCastException e) {
        throw new ClassCastException(activity.toString()
                + " must implement OnFragmentInteractionListener");
    }
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    view = inflater.inflate(R.layout.fragment_course_details, container, false);
    ButterKnife.bind(this, view);
    return view;
}
public void updateUI(Course cData) {
    c = cData
    courseName.setText(cData.getName());
}

}

我正在尝试为textview设置文本。但courseName仍为null

public void updateUI(Course cData) {
    c = cData
    courseName.setText(cData.getName());
}

这是调用updateUI的地方。

public void onDataEntry(boolean saved, Fragment fragment, String identifier,     Object T) {
    if (T instanceof Course){
        Course courseData = (Course)T;
        Log.d(TAG, "onDataEntry: " + courseData.getName() + " " + courseData.getGrade());
        CourseDetailsFragment.getInstance().updateUI(courseData);
    }
}  

这是我的堆栈跟踪:

02-19 17:31:56.317 4689-4689/hsleiden.nl.barometer E/AndroidRuntime: FATAL EXCEPTION: main
                                                                 Process: hsleiden.nl.barometer, PID: 4689
                                                                 java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
                                                                     at hsleiden.nl.barometer.views.fragment.CourseDetailsFragment.updateUI(CourseDetailsFragment.java:101)
                                                                     at hsleiden.nl.barometer.views.activity.BaseActivity.onDataEntry(BaseActivity.java:306)
                                                                     at hsleiden.nl.barometer.adapter.CourseAdapter$1.onClick(CourseAdapter.java:57)
                                                                     at android.view.View.performClick(View.java:5198)
                                                                     at android.view.View$PerformClick.run(View.java:21147)
                                                                     at android.os.Handler.handleCallback(Handler.java:739)
                                                                     at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                     at android.os.Looper.loop(Looper.java:148)
                                                                     at android.app.ActivityThread.main(ActivityThread.java:5417)
                                                                     at java.lang.reflect.Method.invoke(Native Method)
                                                                     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                                                                     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

1 个答案:

答案 0 :(得分:1)

问题在于这一行:

CourseDetailsFragment.getInstance().updateUI(courseData);

问题是,@butterknife.Bind带注释的TextView在调用ButterKnife.bind(this, view)之前将保持为空。要进行该调用,您需要视图层次结构的有效父级,您可以在调用onCreateView生命周期方法之前获得该父级,因此TextViewonCreateView之前为空。现在,在onCreateView之后调用onCreateonAttachActivity之后调用,这是通过将片段附加到FragmentManager来触发的,通常是通过使用{CourseDetailsFragment.getInstance().updateUI(courseData) 1}}。调用Fragment不会自动触发片段生命周期,它只会实例化Fragment实例,直到Activity附加到onCreateViewcourseName为止在调用时,updateUi是一个空引用,这意味着在创建Fragment后立即调用Fragment方法注定会导致空指针异常。

这行代码在没有抛出异常的情况下工作的唯一选择是,如果此onCreateView先前已实例化,附加到活动并且已经通过updateUi方法。

由于上述原因,我不建议将片段实现为单例,特别是如果您想直接调用其他组件对此类片段的引用。由于生命周期,活动和碎片在实践中是状态机,并且您的onFragmentsResumed方法不考虑该状态,这是您问题的根源。

对于快速修复,您可以覆盖Activity中的{{1}}方法 - 如果片段之前已附加过,那么您的引用应该在此时有效。< / p>