【问题标题】:Null TextView object in a fragment片段中的空 TextView 对象
【发布时间】:2015-07-26 23:43:27
【问题描述】:

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

这是 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文本的FragmentActivity代码(ChallengePage.java):

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 问题,但找不到答案。

【问题讨论】:

    标签: android textview settext


    【解决方案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,因为那时您知道 Activity 已创建并且片段的视图层次结构已创建。
    3. 片段参数在配置更改中持续存在,因此您不需要为此做任何特殊的事情。

    另外,您不应该自己调用onAttach(),这是操作系统在您的片段上调用的生命周期方法。

    【讨论】:

      猜你喜欢
      • 2019-09-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多