2015-11-11 2 views
0

Основная цель - обновить информацию о фрагментах в основном из своего собственного класса.Android: Фрагмент и наблюдатель

Основная деятельность:

public class MainActivity extends AppCompatActivity { 
    final Handler GUIHandler = new Handler(); 
    final Runnable r = new Runnable() 
    { 

     public void run() 
     { 
      updateFragments(); 
      GUIHandler.postDelayed(this, 1000); 
     } 
    }; 

    @Override 
    protected void onPause() { 
     super.onPause(); 
     GUIHandler.removeCallbacks(r); 
    } 

    @Override 
    protected void onResume() { 
     super.onResume(); 
     GUIHandler.postDelayed(r, 600); 
    } 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     ... 
     mViewPager = (ViewPager) findViewById(R.id.pager); 
     mPagerAdapter = new PagerAdapter(getSupportFragmentManager(), tabLayout.getTabCount()); 
     mViewPager.setAdapter(mPagerAdapter); 
     ... 
    } 

    private void updateFragments() { 
     mPagerAdapter.updateFragments(); 
    } 

PagerAdapter:

public class PagerAdapter extends FragmentStatePagerAdapter { 
    int mNumOfTabs; 
    private Observable mObservers = new FragmentObserver(); 

    public PagerAdapter(FragmentManager fm, int NumOfTabs) { 
      super(fm); 
      this.mNumOfTabs = NumOfTabs; 
    } 

    @Override 
    public Fragment getItem(int position) { 
     mObservers.deleteObservers(); // Clear existing observers. 
     switch (position) { 
      case 0: 
       FragmentWeather weatherTab = new FragmentWeather(); 
       weatherTab.setActivity(mActivity); 
       if(weatherTab instanceof Observer) 
        mObservers.addObserver((Observer) weatherTab); 
       return weatherTab; 
      case 1: 
       FragmentMemo tab2 = new FragmentMemo(); 
       return tab2; 
      case 2: 
       FragmentHardware tab3 = new FragmentHardware(); 
       return tab3; 
      default: 
       return null; 
     } 
    } 

    public void updateFragments() { 
     mObservers.notifyObservers(); 
    } 

} 

FragmentObserver

public class FragmentObserver extends Observable { 
    @Override 
    public void notifyObservers() { 
     setChanged(); // Set the changed flag to true, otherwise observers won't be notified. 
     super.notifyObservers(); 

     Log.d("Observer", "Sending notification"); 
    } 
} 

FragmentWeather:

public class FragmentWeather extends Fragment implements Observer { 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
         Bundle savedInstanceState) { 
     ... 
     return layout; 
    } 

    public void setTemperatures(){ 
     Log.d("Android", "setTemperatures is called"); 
    } 

    @Override 
    public void update(Observable observable, Object data) { 
     setTemperatures(); 
    } 
} 

Проблема теперь в том, что PagerAdapter::getItem() оленьей коже дозвонилась, когда фрагменты созданы в начале применения. Это означает, что WeatherFragment не ассоциируется с mObservers. Если я перейду к 3-му виду, а затем вернусь назад, все будет работать правильно. Как реорганизовать это, чтобы заставить его работать?

ответ

2

эта линия:

mObservers.deleteObservers(); // Clear existing observers. 

является удаление всех наблюдателей, но метод getItem вызывается несколько раз, это означает, что только в последний раз, когда он называет что-нибудь остается там. REMOVE этот линия.

Кроме того, следующий код является очень плохим шаблоном и ошибутся несколько раз:

 case 0: 
      FragmentWeather weatherTab = new FragmentWeather(); 
      weatherTab.setActivity(mActivity); 
      if(weatherTab instanceof Observer) 
       mObservers.addObserver((Observer) weatherTab); 
      return weatherTab; 

это потому, что фрагменты получают воссозданы с помощью системы, когда это необходимо, так setActivity бессмысленно, так есть addObserver. В тот момент, когда системе нужно уничтожить/воссоздать фрагменты, у вас будет утечка памяти этих старых фрагментов, старая активность, а новые не будут иметь активности и не будут на наблюдателях.

Лучшая ситуация здесь заключается в том, чтобы полагаться на естественные обратные вызовы от фрагментов. Ниже приведен пример (PS .: что был набран на сердце, я уверен, что там могут быть какие-то ошибки, но вы получите идею)

public interface ObservableGetter{ 
    public Observable getObservable(); 
} 

public void MyFragment extends Fragment implements Observer { 

    @Override onAttach(Activity activity){ 
     super.onAtttach(activity); 
     if(activity instanceof ObservableGetter){ 
      ((ObservableGetter)activity).getObservable(). 
       addObserver(this); 
     } 
    } 

    @Overrude onDetach(){ 
     Activity activity = getActivity(); 
     if(activity instanceof ObservableGetter){ 
      ((ObservableGetter)activity).getObservable(). 
       removeObserver(this); 
     } 
     super.onDetach(); 
    } 
} 

, то вы можете просто сделать деятельность реализует ObservableGetter и имеют Наблюдается на нем.

Тогда ваш adapter код будет просто:

  case 0: 
      return new FragmentWeather(); 

все остальные логики использует обычные функции обратного вызова.

Надеюсь, это поможет.

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