在片段空TextView的对象 [英] Null TextView object in a fragment

查看:360
本文介绍了在片段空TextView的对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的工作动态设置TextView中的一个通过创建设置文本的方法称为ChallengeFragment片段的文字。然后,我调用FragmentActivity类的方法来更新TextView的。不过,我得到错误的TextView对象为空时,方法被调用。我不知道为什么的TextView为null。

I'm working on dynamically setting a text of TextView in a fragment called 'ChallengeFragment' by creating a method that sets the text. Then, I call the method in FragmentActivity class to update the TextView. However, I am getting error that TextView object is null when the method is called. I am not sure why TextView is null.

下面是logcat的消息:

Here's the logcat message:

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)

下面是片段类(ChallengeFragment.java):

Here is the Fragment class (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;
}

}

这是FragmentActivity的code,更新的TextView(ChallengePage.java)的文本:

And this is the code for FragmentActivity that updates the text of TextView (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)的布局的文件:

And this is the layout file that contains the fragment (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>

我已经看了关于这个计算器等问题,但无法找到答案。

I've looked at other stackoverflow questions relating to this but could not find answers.

推荐答案

问题是你的片段的 setNameText()方法之前, onCreateView称为( )已运行,所以你的TextView尚未初始化。你必须等待,直到后来设置的名称的文本。

The problem is your fragment's setNameText() method is called before onCreateView() has run, so your TextView has not been initialized yet. You have to wait until later to set the name text.

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

If you always have the name text when you are creating and adding the fragment, then it's better to pass that as an argument to the fragment and have it set the text of the TextView at the appropriate time. Something like this:

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
}

有几件事情需要注意:

A few things to note:


  1. 不可以创建一个构造。片段需要有一个默认的(无参数)构造函数,以便能够Android的实例他们。这的newInstance 模式通常被认为是最好的做法。

  2. 使用 onActivityCreated 因为当时你知道活动是创建该片段的视图层次结构已创建。

  3. 片段参数之间保留更改配置,所以你不需要做什么特别了点。

  1. Do not create a constructor. Fragments need to have a default (no argument) constructor so that Android can instantiate them. This newInstance pattern is typically regarded as the best practice.
  2. Use onActivityCreated because at that time you know the Activity is created and that the fragment's view hierarchy has been created.
  3. Fragment arguments persist across configuration changes, so you shouldn't need to do anything special for that.

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

Also, you should not be calling onAttach() yourself, that's a lifecycle method that the OS calls on your fragment.

这篇关于在片段空TextView的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆