Android:片段和观察者

时间:2015-11-11 22:34:07

标签: android android-fragments observers

主要目标是主要从自己的班级更新片段信息。

主要活动:

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();
    }
}

现在的问题是,在应用程序启动时创建Fragments时,PagerAdapter::getItem()不会被调用。这意味着WeatherFragmentmObservers无关。如果我滑动到第三个视图然后向后滑动,一切正常。如何对其进行重组以使其正常工作?

1 个答案:

答案 0 :(得分:2)

这一行:

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

正在移除所有观察者,但是方法getItem被多次调用,这意味着只有最后一次调用任何观察者停留在那里。 删除此行。

此外,以下代码是一个非常糟糕的模式,它会在几种情况下出错:

        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并在其上设置Observable。

然后您的adapter代码就是:

         case 0:
            return new FragmentWeather();

所有其余逻辑都使用常规回调。

我希望它有所帮助。

相关问题