片段中的空TextView对象

时间:2015-07-26 23:43:28

标签: android textview settext

我正在通过创建一个设置文本的方法,在名为“ChallengeFragment”的片段中动态设置TextView文本。然后,我调用FragmentActivity类中的方法来更新TextView。但是,调用方法时,我收到TextView对象为null的错误。我不确定为什么TextView为null。

这是logcat消息:

16:36:02.437    4072-4072/eie.android.crunch E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: eie.android.crunch, PID: 4072
java.lang.RuntimeException: Unable to start activity ComponentInfo{eie.android.crunch/eie.android.crunch.ChallengePage}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2325)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2390)
        at android.app.ActivityThread.access$800(ActivityThread.java:151)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:135)
        at android.app.ActivityThread.main(ActivityThread.java:5257)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at 

com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
     Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
            at eie.android.crunch.ChallengeFragment.setNameText(ChallengeFragment.java:76)
            at eie.android.crunch.ChallengePage.onCreate(ChallengePage.java:50)
            at android.app.Activity.performCreate(Activity.java:5990)
            at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2278)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2390)
            at android.app.ActivityThread.access$800(ActivityThread.java:151)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5257)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)

这是Fragment类(ChallengeFragment.java):

public class ChallengeFragment extends Fragment {

private Activity mActivity;
private TextView nameText;
private Handler handler =new Handler();

public ChallengeFragment() {

}

public void onAttach(Activity activity) {
    super.onAttach(activity);
    mActivity = activity;
}

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

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

    LayoutInflater lf = getActivity().getLayoutInflater();
    View v = lf.inflate(R.layout.fragment_challenge, null);
    nameText = (TextView) v.findViewById(R.id.user_name_text_view);        

                            ....

    return v;
}

public void setNameText(String s) {
    nameText.setText(s);
}

public TextView getNameText() {
    return nameText;
}

}

这是更新TextView(ChallengePage.java)文本的FragmentActivity代码:

public class ChallengePage extends FragmentActivity {
private FriendChallengeFragment initialFriendHabit;
private ChallengeFragment friendHabit;
private ChallengeFragment myHabit;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_challenge);

    FragmentManager fm = getSupportFragmentManager();
    FragmentTransaction fragmentTransaction = fm.beginTransaction();

    myHabit = new ChallengeFragment();

    initialFriendHabit = new FriendChallengeFragment();

    myHabit.onAttach(ChallengePage.this);
    initialFriendHabit.onAttach(ChallengePage.this);

    fragmentTransaction
            .replace(R.id.my_habit, myHabit ,"fragment_top")
            .replace(R.id.friend_habit, initialFriendHabit, "fragment_bottom")
            .commit();

    Intent intent = getIntent();
    String challengedUsername = intent.getStringExtra("username");
    if(challengedUsername != null) {
        friendHabit = new ChallengeFragment();
        friendHabit.onAttach(ChallengePage.this);
        fragmentTransaction.replace(R.id.friend_habit, friendHabit, "fragment_bottom");
        friendHabit.setNameText(challengedUsername);
    }

}

}

这是包含片段(fragment_challenge.xml)的布局文件:

    <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@color/white"
        android:id="@+id/user_name_text_view"
        android:layout_gravity="center_horizontal"
        android:text="User Name"
        android:textSize="30dp"
        android:layout_marginTop="30dp"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@color/white"
        android:id="@+id/habit_name_text"
        android:layout_gravity="center_horizontal"
        android:text="Habit Name"
        android:textSize="40dp"
        android:layout_marginTop="20dp"/>

    <ProgressBar
        android:layout_height="wrap_content"
        android:layout_width="312dp"
        style="@android:style/Widget.ProgressBar.Horizontal"
        android:id="@+id/progressBar"
        android:layout_marginTop="50dp"
        android:layout_gravity="center_horizontal"/>

</LinearLayout>

我已经查看过与此相关的其他stackoverflow问题,但找不到答案。

1 个答案:

答案 0 :(得分:1)

问题是在setNameText()运行之前调用了片段onCreateView()方法,因此您的TextView尚未初始化。您必须等到稍后才能设置名称文本。

如果在创建和添加片段时总是有文本名称,那么最好将其作为参数传递给片段,并让它在适当的时候设置TextView的文本。像这样:

public class ChallengeFragment extends Fragment {

    public static ChallengeFragment newInstance(String name) {
        ChallengeFragment fragment = new ChallengeFragment();
        Bundle args = new Bundle();
        args.putString("username", name);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        Bundle args = getArguments();
        if (args != null) {
            String name = args.getString("username");
            nameText.setText(name);
        }
    }

    // everything else
}

有几点需要注意:

  1. 创建构造函数。片段需要有一个默认(无参数)构造函数,以便Android可以实例化它们。这种newInstance模式通常被认为是最佳实践。
  2. 使用onActivityCreated,因为当时您知道已创建活动并且已创建片段的视图层次结构。
  3. 片段参数在配置更改中保持不变,因此您不需要为此做任何特殊操作。
  4. 此外,您不应该自己调用onAttach(),这是操作系统调用片段的生命周期方法。