Ссылка на фрагмент из действия имеет неинициализированные элементы (TextView и другие)

Я пытаюсь вызвать метод, из MainActivityкоторого обновления TextViewв фрагменте.

Однако ссылка на фрагмент, который я получил в onCreateметоде inMainActivity, имеет нулевые элементы управления (buttonsиtextviews).

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

MainActivity:

public class MainActivity extends AppCompatActivity {
TabAdapter adapter;
Toolbar toolbar;
ViewPager pager;
SlidingTabLayout tabs;
StopwatchFragment stopwatchFragment;

CharSequence titles[] = {"Stopwatch","Countdown"};
int numOfTabs=2;

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

    setContentView(R.layout.activity_main);

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

    adapter = new TabAdapter(getSupportFragmentManager(),numOfTabs,titles);

    pager = (ViewPager)findViewById(R.id.view_pager);
    pager.setAdapter(adapter);

    tabs = (SlidingTabLayout)findViewById(R.id.tabs);
    tabs.setDistributeEvenly(true);     
    tabs.setViewPager(pager);

    stopwatchFragment =   StopwatchFragment)adapter.getItem(TabAdapter.STOPWATCH_FRAGMENT_POSITION);

   }
}

Секундомер fragment:

public class StopwatchFragment extends Fragment {
private static String TAG = "StopwatchFragment";

private TextView tv_elapsed_time;
private TextView tv_elapsed_time_millis;
private long elapsedTime;
private long startTime;
private static final int REFRESH_RATE = 60;
private boolean stopped = false;

private Button btn_lap;
private ListView lv_laps;

private LapsAdapter lapsAdapter;
private List<String> lapsList;

private Handler handler = new Handler();

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_stopwatch,container,false);       

    tv_elapsed_time=(TextView)view.findViewById(R.id.elapsed_time);
    tv_elapsed_time_millis=(TextView)view.findViewById(R.id.elapsed_time_millis);
    lv_laps = (ListView)view.findViewById(R.id.lv_Laps);

    lapsList = new ArrayList<String>();
    lapsAdapter = new LapsAdapter(getActivity(),R.layout.laps_row,lapsList);
    lv_laps.setAdapter(lapsAdapter);

    return view;
}

TabAdapter:

public class TabAdapter extends FragmentStatePagerAdapter {

public static final int STOPWATCH_FRAGMENT_POSITION = 0;
public static  final int  LAPS_FRAGMENT_POSITION = 1;

CharSequence titles[];
int numOfTabs; 

public TabAdapter(FragmentManager fm,int numberOfTabs,CharSequence titles[])   {
    super(fm);
    this.numOfTabs =numberOfTabs;
    this.titles = titles;
}
@Override
public Fragment getItem(int position) {
    switch(position)
    {
        case 0:
            StopwatchFragment stopwatchFragment = new StopwatchFragment();
            return stopwatchFragment;
        case 1:
            CountdownFragment countdownFragment = new CountdownFragment();
            return countdownFragment;
        default:return null;

    }
}

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

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

}

StopwatchFragment.XML:

<LinearLayout 

android_layout_width="match_parent"
android_layout_height="match_parent"
android_gravity="center_horizontal"
android_orientation="vertical">

<RelativeLayout 
    android_layout_width="wrap_content"
    android_layout_height="wrap_content"
    android_layout_marginTop="@dimen/activity_horizontal_margin">

    <LinearLayout
        android_layout_width="wrap_content"
        android_layout_height="wrap_content"
        android_layout_centerInParent="true">

        <TextView
            android_id="@+id/elapsed_time"
            android_layout_width="wrap_content"
            android_layout_height="wrap_content"
            android_fontFamily="sans-serif-thin"
            android_text="00 00"
            android_textColor="@color/colorAccent"
            android_textSize="112sp" />

        <TextView
            android_id="@+id/elapsed_time_millis"
            android_layout_width="wrap_content"
            android_layout_height="wrap_content"
            android_text="00"
            android_textColor="@color/colorAccent"
            android_textSize="24sp" />
    </LinearLayout>

    <ProgressBar
        android_id="@+id/progressBar"
        style="?android:attr/progressBarStyleHorizontal"
        android_layout_width="360dp"
        android_layout_height="360dp"
        android_max="500"
        android_progress="0"
        android_progressDrawable="@drawable/circular" />
</RelativeLayout>    

<ListView
    android_id="@+id/lv_Laps"
    android_layout_width="fill_parent"
    android_layout_height="wrap_content"
    android_divider="@null"
    android_dividerHeight="0dp" />

2 ответа

  1. StopwatchFragmentВместо этого необходимо переместить код, инициализирующий элементы управления, в onActivityCreatedметод onCreateView. Я внес эти изменения в код ниже:

    public class StopwatchFragment extends Fragment {
    private static String TAG = "StopwatchFragment";
    
    private Button btn_start,btn_stop;
    private TextView tv_elapsed_time;
    private TextView tv_elapsed_time_millis;
    private long elapsedTime;
    private long startTime;
    private static final int REFRESH_RATE = 60;
    private boolean stopped = false;
    
    private Button btn_lap;
    private ListView lv_laps;
    
    private LapsAdapter lapsAdapter;
    private List<String> lapsList;
    
    
    private Handler handler = new Handler();
    
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_stopwatch,container,false);   
            tv_elapsed_time=(TextView)view.findViewById(R.id.elapsed_time);
            tv_elapsed_time_millis= (TextView)view.findViewById(R.id.elapsed_time_millis);
            lv_laps = (ListView)view.findViewById(R.id.lv_Laps); 
        return view;
    }
    
        /**
         * This method is called after the onCreateView() method when the host activity is created. 
         * Activity and fragment instance have been created as well as the view hierarchy of the activity. 
         * At this point, view can be accessed with the findViewById() method.
         */
        @Override
        public void onActivityCreated(Bundle savedInstanceState) {  
            super.onActivityCreated(savedInstanceState);
    
            lapsList = new ArrayList<String>();
            lapsAdapter = new LapsAdapter(getActivity(),R.layout.laps_row,lapsList);
            lv_laps.setAdapter(lapsAdapter);
    
            Log.d(TAG,"Controls initialized");                      
    
            Log.d(TAG, "onCreateView");
    
        }
    

    Пожалуйста, обновите ваш StopwatchFragmentсоответственно, дайте ему попробовать и дайте мне знать, если это поможет.

  2. Проблема была в TabAdapter. Нужно изменить конструктор:

    public TabAdapter(FragmentManager fm,int numberOfTabs,CharSequence titles[]) {
        super(fm);
        this.numOfTabs = numberOfTabs;
        this.titles = titles;
        stopwatchFragment = new StopwatchFragment();
        countdownFragment = new CountdownFragment();
    }
    

    И метод getItem():

    @Override
    public Fragment getItem(int position) {
        switch(position)
        {
            case 0: 
                return stopwatchFragment;
            case 1:                
                return countdownFragment;
            default:return null;
        }
    }