2015-07-26 4 views
0

Я работаю над динамической установкой текста TextView во фрагменте под названием «ChallengeFragment», создав метод, который устанавливает текст. Затем я вызываю метод в классе FragmentActivity для обновления TextView. Тем не менее, я получаю сообщение об ошибке, когда объект TextView имеет значение null при вызове метода. Я не уверен, почему TextView имеет значение null.Объект Null 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) 

Вот фрагмент класса (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, который обновляет текст 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):

<?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 вопросы, связанные с этим, но не смогли найти ответы.

ответ

0

Проблема заключается в том, что метод setNameText() вашего фрагмента вызывается до запуска onCreateView(), поэтому ваш 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. Аргументы фрагментов сохраняются при изменении конфигурации, поэтому вам не нужно ничего делать для этого.

Кроме того, вы не должны сами звонить onAttach(), это метод жизненного цикла, который ОС вызывает ваш фрагмент.

Смежные вопросы