Android : 片段和观察者

Android : Fragment and Observer

主要目标是更新主要来自其自身的片段信息class。

主要activity:

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

片段天气:

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 相关联。如果我滑动到第三个视图然后向后滑动,一切正常。如何对其进行重组以使其发挥作用?

这一行:

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 也是如此。系统需要 destroy/recreate 片段的那一刻,你就会有那些旧片段的内存泄漏,旧的 activity,而新的不会有 activity 并且赢了不要在旁观者身上。

这里最好的情况是依赖片段的自然回调。下面是一个示例(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();
   }
}

然后你可以让 activity 实现 ObservableGetter 并在其上安装 Observable。

那么您的 adapter 代码将是:

         case 0:
            return new FragmentWeather();

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

希望对您有所帮助ps。