1

У меня есть активность с фрагментом на нем, который имеет TextView внутри. В CourseFragment.java я сделал простой метод, который изменяет текст TextView. Однако, когда я пытаюсь вызвать метод фрагмента из Activity, он говорит, что объект TextView имеет значение NULL. Вот некоторые из моего кода:Не удается получить доступ к текстурному фрагменту внутри фрагмента

CourseFragment.java

public class CourseFragment extends Fragment { 

private Subject subject; 
View rootView; 
private TextView title; 

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, 
         Bundle savedInstanceState) { 
    // Inflate the layout for this fragment 
    rootView = inflater.inflate(R.layout.fragment_course, container, 
      false); 

    title = (TextView) rootView.findViewById(R.id.course_title); 

    return rootView; 
} 

public void setTitle() { 
    title.setText("My Title"); 
} 

} 

это код в моей деятельности, что делает новый фрагмент и помещает в нужном месте:

CourseFragment fragment = new CourseFragment(); 
FragmentManager fm = getFragmentManager(); 
FragmentTransaction ft = fm.beginTransaction(); 
ft.replace(R.id.course1, fragment); 
fragment.setTitle(); 
ft.addToBackStack(null); 
ft.commit(); 

в ошибка, возникающая из метода setTitle() внутри фрагмента

Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference 

это кажется таким прямым, но я не понимаю, почему я продолжаю получать NPE. Я посмотрел на подобные вопросы по этому поводу и пробовал все принятые решения, но безуспешно. есть идеи?

заранее спасибо

редактировать: здесь некоторый код в соответствии с просьбой:

начало fragment_course.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:app="http://schemas.android.com/apk/res-auto" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:id="@+id/course_fragment" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    tools:context="com.stagenda.stagenda.CourseFragment" 
    android:padding="16dp" 
    android:orientation="vertical" 
    android:background="@android:color/background_light"> 

    <RelativeLayout 
     android:layout_width="match_parent" 
     tools:ignore="UselessParent" 
     android:background="@color/colorAccent" 
     android:padding="16dp" 
     android:layout_height="wrap_content" 
     android:id="@+id/course_container"> 
<TextView 
     android:text="Course Given Title" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:id="@+id/course_given_title" 
     android:textColor="@android:color/background_light" 
     android:textSize="18sp" /> 

    <TextView 
    android:text="Course Title" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:id="@+id/course_title" 
    android:layout_below="@+id/course_given_title" 
    android:textColor="@android:color/background_light" /> 

    <TextView 
     android:text="Course Code" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:id="@+id/course_code" 
     android:textColor="@android:color/background_light" 
     android:layout_toRightOf="@+id/course_title" 
     android:layout_below="@+id/course_given_title" 
     android:layout_alignParentEnd="false" 
     android:layout_marginStart="10dp" /> 

полная ошибка:

E/AndroidRuntime: FATAL EXCEPTION: main 
        Process: com.stagenda.stagenda, PID: 1654 
        java.lang.IllegalStateException: Could not execute method for android:onClick 
         at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:293) 
         at android.view.View.performClick(View.java:5639) 
         at android.view.View$PerformClick.run(View.java:22387) 
         at android.os.Handler.handleCallback(Handler.java:751) 
         at android.os.Handler.dispatchMessage(Handler.java:95) 
         at android.os.Looper.loop(Looper.java:154) 
         at android.app.ActivityThread.main(ActivityThread.java:6088) 
         at java.lang.reflect.Method.invoke(Native Method) 
         at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886) 
         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776) 
        Caused by: java.lang.reflect.InvocationTargetException 
         at java.lang.reflect.Method.invoke(Native Method) 
         at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:288) 
         at android.view.View.performClick(View.java:5639)  
         at android.view.View$PerformClick.run(View.java:22387)  
         at android.os.Handler.handleCallback(Handler.java:751)  
         at android.os.Handler.dispatchMessage(Handler.java:95)  
         at android.os.Looper.loop(Looper.java:154)  
         at android.app.ActivityThread.main(ActivityThread.java:6088)  
         at java.lang.reflect.Method.invoke(Native Method)  
         at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)  
         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)  
        Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference 
         at com.stagenda.stagenda.CourseFragment.setTitle(CourseFragment.java:34) 
         at com.stagenda.stagenda.MainPage.confirmAddCourse(MainPage.java:435) 
         at java.lang.reflect.Method.invoke(Native Method)  
         at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:288)  
         at android.view.View.performClick(View.java:5639)  
         at android.view.View$PerformClick.run(View.java:22387)  
         at android.os.Handler.handleCallback(Handler.java:751)  
         at android.os.Handler.dispatchMessage(Handler.java:95)  
         at android.os.Looper.loop(Looper.java:154)  
         at android.app.ActivityThread.main(ActivityThread.java:6088)  
         at java.lang.reflect.Method.invoke(Native Method)  
         at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)  
         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)  
I/Process: Sending signal. PID: 1654 SIG: 9 
Disconnected from the target VM, address: 'localhost:8612', transport: 'socket' 

explanation of layout (image)

+0

Попробуйте установить заголовок после метода фиксации. –

+0

лучше передать текст в putExtra. Таким образом, этот фрагмент не связан. – Nepster

+0

Без разницы, если я установил заголовок после фиксации. спасибо за быстрый ответ –

ответ

1

Я сам это понял. Проблема здесь:

CourseFragment fragment = new CourseFragment(); 
FragmentManager fm = getFragmentManager(); 
FragmentTransaction ft = fm.beginTransaction(); 
ft.replace(R.id.course1, fragment); 
fragment.setTitle(); 
ft.addToBackStack(null); 
ft.commit(); 

Проблема заключалась в том, что я звоню SETTITLE() на фрагменте, который не создал его вида. когда вместо этого я сделал следующее, проблема была решена:

CourseFragment fragment = new CourseFragment(); 
FragmentManager fm = getFragmentManager(); 
FragmentTransaction ft = fm.beginTransaction(); 
ft.replace(R.id.course1, fragment); 
ft.addToBackStack(null); 
ft.commit(); 

CourseFragment frag = fm.findFragmentById(R.id.course1); 
frag.setTitle(); 

Я в конечном итоге изменил свой код, но надеюсь, что это кому-то поможет. Спасибо за ответы.

2

Идите с этим соглашением.

Bundle bundle = new Bundle(); 
    bundle.putString("title", "whatever you want to pass"); 

     CourseFragment fragment = new CourseFragment(); 
     fragment.setArguments(bundle); 
     FragmentManager fm = getFragmentManager(); 
     FragmentTransaction ft = fm.beginTransaction(); 
     ft.replace(R.id.course1, fragment); 
     ft.addToBackStack(null); 
     ft.commit(); 



    public class CourseFragment extends Fragment { 

    private Subject subject; 
    View rootView; 
    private TextView title; 
    Bundle bundle; 

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

      bundle = getArguments(); 
     } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
          Bundle savedInstanceState) { 
     // Inflate the layout for this fragment 
     rootView = inflater.inflate(R.layout.fragment_course, container, 
       false); 

     title = (TextView) rootView.findViewById(R.id.course_title); 

     String text = bundle.getString("title"); 
     title.setText(text); 

     return rootView; 
    } 


    } 
+0

Без разницы, если я это сделаю. такая же ошибка –

+0

@krz, если это не работает, тогда проверьте свой XML-файл 'course_title' id или нет. – Spartan

+0

Я добавил часть xml-файла. Здесь есть курс –

0

Одна вещь, которую вы можете сделать, это передать ваши данные в качестве параметров:

CourseFragment fragment = new CourseFragment(Your title); 
FragmentManager fm = getFragmentManager(); 
FragmentTransaction ft = fm.beginTransaction(); 
ft.replace(R.id.course1, fragment); 
ft.addToBackStack(null); 
ft.commit(); 

Вы также можете использовать Bundle передать ваши данные.

+0

проблема не в передаче данных. проблема заключается в том, что фрагмент обновляет свой TextView –

+0

@krz. передайте данные и в 'onCreateView' обновите заголовок вашего фрагмента.(если вы передаете данные динамически из фрагмента в фрагмент или из активности в фрагмент, рассмотрите прослушиватели (интерфейс). – Spartan

0

Фрагментные транзакции не являются синхронными. Когда вы добавляете транзакцию, она может быть выполнена, когда основной петлевой механизм имеет возможность запустить его (он будет поставлен в очередь на потом).

Это означает, что фрагмент прикрепляется до окончания текущего метода. Проверьте порядок, в котором выполнены CourseFragment.setTitle() и onCreateView().

См документы для FragmentTransaction.commit(): commit

Рассмотрите возможность использования commitNow(), если он работает для вас.

Кроме того, рассмотрите передачу заголовка в качестве аргумента фрагменту, чтобы его можно было прочитать внутри onCreateView с использованием getArguments().

+0

Я понял, что фрагмент будет иметь метод для каждого элемента управления, доступного из этой активности. Из моих исследований о том, как работают фрагменты андроида, Я понял, что это правильный способ изменить элементы управления внутри фрагмента. Не понял ли я? –

+0

Рассмотрите, что происходит, когда устройство повернуто, а активность и фрагмент воссозданы. Будет ли снова запущен вызов 'CourseFragment.setTitle()' «Я не могу сказать из примера кода, который вы опубликовали. Идеальным является то, что ему не нужно. Фрагмент должен иметь информацию, чтобы узнать, какой текст будет отображаться в TextView. Это делается путем передачи ее в качестве аргумента. И я по-прежнему рекомендую вам проверить порядок, в котором вызываются две функции: порядок не должен быть связан. – frozenkoi

0

Layout для вкладок:

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

     <android.support.v7.widget.Toolbar 
      android:id="@+id/toolbar" 
      android:layout_width="match_parent" 
      android:layout_height="?attr/actionBarSize" 
      app:layout_scrollFlags="scroll|enterAlways" 
      app:layout_collapseMode="pin" 
      android:background="#000000" 
      app:titleTextColor="#ffffff" 

      app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" 
      app:popupTheme="@style/PopupMenuStyle"> 

      <TextView 
       android:layout_width="match_parent" 
       android:layout_height="?attr/actionBarSize" 
       android:id="@+id/textview" 
       android:textColor="@color/colorTrueWhite"/> 

     </android.support.v7.widget.Toolbar> 

     <!-- our tablayout to display tabs --> 
     <android.support.design.widget.TabLayout 
      android:id="@+id/tabLayout" 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:background="@color/colorBlack" 
      android:minHeight="?attr/actionBarSize" 

      app:tabIndicatorColor="@color/colorTrueWhite" 
      app:tabIndicatorHeight="5dp" 
      android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/> 

     <!-- View pager to swipe views --> 


     <android.support.v4.view.ViewPager 
      android:id="@+id/pager" 
      android:layout_width="match_parent" 
      android:layout_height="fill_parent"/> 


    </LinearLayout> 

активность с использованием этого макета:

public class Main2Activity extends AppCompatActivity implements TabLayout.OnTabSelectedListener { 

    private TabLayout tabLayout; 
    public static ViewPager viewPager; 
    public static Context ctx; 
    Pager adapter; 
    public static int expired, paid; 
    Boolean isConnection; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main2); 

     Toolbar tb = (Toolbar) findViewById(R.id.toolbar); 
     setSupportActionBar(tb); 

     TextView tv = (TextView) findViewById(R.id.textview); 

     //getSupportActionBar().setDisplayHomeAsUpEnabled(true); 


     ctx = getApplicationContext(); 


     StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); 
     StrictMode.setThreadPolicy(policy); 


     tabLayout = (TabLayout) findViewById(R.id.tabLayout); 
     viewPager = (ViewPager) findViewById(R.id.pager); 


     tabLayout.addTab(tabLayout.newTab().setText("title1")); 
     tabLayout.addTab(tabLayout.newTab().setText("title2")); 
     tabLayout.addTab(tabLayout.newTab().setText("title3")); 
     tabLayout.setTabGravity(TabLayout.GRAVITY_FILL); 
     tabLayout.setupWithViewPager(viewPager); 

     adapter = new Pager(getSupportFragmentManager(), tabLayout.getTabCount(), ctx); 
     viewPager.setAdapter(adapter); 


     if(some condition) 
     { 
      viewPager.setCurrentItem(2); 
     } 
     else 
     { 
      viewPager.setCurrentItem(1); 
     } 
     viewPager.setOffscreenPageLimit(2); 

     tabLayout.addOnTabSelectedListener(this); 

     ViewGroup vg = (ViewGroup) tabLayout.getChildAt(0); 
     int tabsCount = vg.getChildCount(); 
     for (int j = 0; j < tabsCount; j++) { 
      ViewGroup vgTab = (ViewGroup) vg.getChildAt(j); 
      int tabChildsCount = vgTab.getChildCount(); 
      for (int i = 0; i < tabChildsCount; i++) { 
       View tabViewChild = vgTab.getChildAt(i); 
       if (tabViewChild instanceof TextView) { 
        ((TextView) tabViewChild).setTypeface(Typeface.DEFAULT, Typeface.BOLD); 
       } 
      } 
     } 
    } 


    @Override 
    public void onTabSelected(TabLayout.Tab tab) { 
     viewPager.setCurrentItem(tab.getPosition()); 
    } 

    @Override 
    public void onTabReselected(TabLayout.Tab tab) { 
    } 

    @Override 
    public void onTabUnselected(TabLayout.Tab tab) { 
    } 


} 

код пейджера:

public class Pager extends FragmentStatePagerAdapter 
{ 
    int tabcount; 
    Context ctx; 
    private String [] Titles = {"title1", "title2", "title3"}; 

    public Pager(FragmentManager fm, int tabcount, Context ctx) 
    { 
     super(fm); 
     this.tabcount = tabcount; 
     this.ctx = ctx; 
    } 

    @Override 
    public int getCount() { 
     return tabcount; 
    } 

    @Override 
    public CharSequence getPageTitle(int position) { 
     return Titles[position]; 
    } 

    @Override 
    public Fragment getItem(int position) { 

     switch (position) { 

      case 0: 
       Tab1 tab1 = new Tab1(); 
       return tab1; 

      case 1: 
       Tab2 tab2 = new Tab2(); 
       return tab2; 

      case 2: 
       Tab3 tab3 = new Tab3(); 
       return tab3; 

      default: 
       return null; 
     } 
    } 


} 
+0

Используйте этот подход, отлично работали со мной! –

0

onCreateView() метод вызывается после fragmentTransaction.commit(). Поскольку вы звоните SETTITLE() перед тем fragmentTransaction.commit(), то TextView экземпляр название не инстанцирован и поэтому является недействительным. Добавить строку fragment.setTitle() после фрагментTransaction.commit().