zoukankan      html  css  js  c++  java
  • Viewpager+fragment数据更新问题解析

    在一个 Android 应用中,我们可以使用 FragmentPageAdapter

    来处理多 Fragment 页面的横向滑动。但是当 Fragment 对应的数据集发生改变时,我们都希望能够通过调用 mAdapter.notifyDataSetChanged() 来触发 Fragment 页面使用新的数据调整或重新生成其内容,可是当我们使用 notifyDataSetChanged() 后,我们会发现这个方法不会生效。那为什么会这样呢,之前遇到了相同的问题一直没法解决,在网上给出的乱七八糟的答案感觉也不是正解,终于在今早彻底解决了这个问题。我们先来了解下FragmentPagerAdapter的源代码。

    @Override  
      public Object instantiateItem(ViewGroup container, int position) {  
        if (mCurTransaction == null) {  
          mCurTransaction = mFragmentManager.beginTransaction();  
        }  
        
        final long itemId = getItemId(position);  
        
        // Do we already have this fragment?  
        String name = makeFragmentName(container.getId(), itemId);  
        Fragment fragment = mFragmentManager.findFragmentByTag(name);  
        if (fragment != null) {  
          if (DEBUG) Log.v(TAG, "Attaching item #" + itemId + ": f=" + fragment);  
          mCurTransaction.attach(fragment);  
        } else {  
          fragment = getItem(position);  
          if (DEBUG) Log.v(TAG, "Adding item #" + itemId + ": f=" + fragment);  
          mCurTransaction.add(container.getId(), fragment,  
              makeFragmentName(container.getId(), itemId));  
        }  
        if (fragment != mCurrentPrimaryItem) {  
          fragment.setMenuVisibility(false);  
          fragment.setUserVisibleHint(false);  
        }  
        
        return fragment;  
      }

    我们特别关注下以下这句

    String name = makeFragmentName(container.getId(), itemId);  
        Fragment fragment = mFragmentManager.findFragmentByTag(name);

    根据原代码我们可以知道系统给每一个Fragment都打上了一个标签,通过标签来寻找相应的fragment,所以当我们第二次进入fragment的时候,fragment的oncreate,oncreateView方法都不会被调用的,因为FragmentPageAdapter中的getitem()方法根本不会被调用,因为系统会根据标签找到相应的fragment,如果已经存在,就不会被调用,fragment有一个缓存机制在这里。那么如果我们一定要更新fragment,那么我们又该如何处理呢,我们就可以以其人之道,还治其人之身,我们可以通过tag标签找到我们相应的fragment,就可以对该fragment进行更新。那么我们现在就开始吧。

    我们先来定义一个list<String> tagList 来存储一下tag

    private List<String> tagList;

    第二部

    重写instantiateItem

    方法,把fragment对应的标签存储在taglist集合里

    public Object instantiateItem(ViewGroup container, int position) {  
            tagList.add(makeFragmentName(container.getId(), getItemId(position)));  
            return super.instantiateItem(container, position);  
        }

    makeFragmentName()是

    FragmentPageAdapter源码里打fragment标签的方法

    public static String makeFragmentName(int viewId, int index) {
        return "android:switcher:" + viewId + ":" + index;
      }

    第三步我们再adapter里自己写一个update()方法

    public void update(int item) {
          Fragment fragment = fm.findFragmentByTag(tagList.get(item));
          if (fragment != null) {
            switch (item) {
            case 0:
    
              break;
            case 1:
              ((QueryFragment) fragment).update();
              break;
            case 2:
    
              break;
            default:
              break;
            }
          }
        }

    我们可以发现在queryFragment里也有一个update()方法,这个方法呢就是接下来我们用接口回掉机制更新我们相应fragment的要使用的方法,方法里的内容根据自己的需要编译就可以了。

    好的现在万事具备只要实现fragment的数据更新问题就可以了,通过接口回掉机制来实现。

    首先我们定义一个接口,让我们的主Activity来实现

    public interface FragmentListener {  
          
            public void onFragmentClickListener(int item);  
        }

    之后比如我们在A Fragment 里头插入了数据,需要BFragment对该数据进行显示,那么我们现在AFragment的onAttach方法中

    public void onAttach(Activity activity) {  
      super.onAttach(activity);  
      try {  
          listener = (FragmentListener)activity;  
      } catch (Exception e) {  
          e.printStackTrace();  
         
      }  
        }

        然后对数据更新的时候,我们就在Afragment调用这个接口

    if (listener != null) {
                  listener.onFragmentClickListener(1);
                }

    然后我们回到Activity实现该接口里的方法,更新BFragment界面

    public void onFragmentClickListener(int item) {
        adapter.update(item);
        adapter.update(item);
      }

       大功告成了,贴一下完整的MainAcitivity代码吧!

    package com.example.account.main;
    
    import java.util.ArrayList;
    
    import java.util.List;
    
    import com.example.account.add.AddFragment;
    import com.example.account.query.QueryFragment;
    import com.example.account.setting.SettingFragment;
    import com.example.account.utils.PagerSlidingTabStrip;
    import com.melhc.xiji.R;
    
    import android.annotation.SuppressLint;
    import android.content.Intent;
    import android.graphics.Color;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Message;
    import android.support.v4.app.Fragment;
    import android.support.v4.app.FragmentActivity;
    import android.support.v4.app.FragmentManager;
    import android.support.v4.app.FragmentPagerAdapter;
    
    import android.support.v4.view.ViewPager;
    
    import android.util.DisplayMetrics;
    
    import android.util.TypedValue;
    
    import android.view.KeyEvent;
    import android.view.ViewGroup;
    import android.widget.Toast;
    
    public class MainActivity extends FragmentActivity implements FragmentListener{
      private MyPagerAdapter adapter;
      private AddFragment addFragment;
      private List<String> tagList;
      private SettingFragment settingFragment;
      private boolean isExit;
      private QueryFragment queryFragment;
      private ViewPager pager;
      private PagerSlidingTabStrip tabs;
      private FragmentManager fm;
      private DisplayMetrics dm;
      private List<Fragment> list;
    
      @Override
      protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        pager = (ViewPager) findViewById(R.id.pager);
        tabs = (PagerSlidingTabStrip) findViewById(R.id.tabs);
        initFragment();
        fm = getSupportFragmentManager();
        tagList = new ArrayList<String>();
        adapter = new MyPagerAdapter(fm);
        pager.setAdapter(adapter);
        tabs.setViewPager(pager);
      
      }
    
      public void initFragment() {
        list = new ArrayList<Fragment>();
        addFragment = new AddFragment();
        queryFragment = new QueryFragment();
        settingFragment = new SettingFragment();
        list.add(addFragment);
        list.add(queryFragment);
        list.add(settingFragment);
      }
    
    
    
      public class MyPagerAdapter extends FragmentPagerAdapter {
    
        public MyPagerAdapter(FragmentManager fm) {
    
          super(fm);
        }
    
        private final String[] titles = { "1", "2", "3" };
    
        @Override
        public CharSequence getPageTitle(int position) {
          return titles[position];
        }
    
        @Override
        public int getCount() {
          return titles.length;
        }
    
        @Override
        public Fragment getItem(int position) {
          return list.get(position);
        }
    
    
        public Object instantiateItem(ViewGroup container, int position) {
          tagList.add(makeFragmentName(container.getId(),
              (int) getItemId(position)));
          return super.instantiateItem(container, position);
        }
    
        public void update(int item) {
          Fragment fragment = fm.findFragmentByTag(tagList.get(item));
          if (fragment != null) {
            switch (item) {
            case 0:
    
              break;
            case 1:
              ((QueryFragment) fragment).update();
              break;
            case 2:
    
              break;
            default:
              break;
            }
          }
        }
    
      }
    
      public static String makeFragmentName(int viewId, int index) {
        return "android:switcher:" + viewId + ":" + index;
      }
    
    
    
      public void onFragmentClickListener(int item) {
        adapter.update(item);
        adapter.update(item);
      }
      
    
    }

     

  • 相关阅读:
    写一个列表生成式,产生一个公差为11的等差数列
    如果对方网站反爬取,封IP了怎么办?
    为什么会选择redis数据库?
    你是否了解谷歌的无头浏览器?
    遇到的反爬虫策略以及解决方法?
    常见的HTTP方法有哪些?
    遇到反爬机制怎么处理?
    列举网络爬虫所用到的网络数据包,解析包?
    python中的关键字yield有什么作用?
    如下代码输出的是什么?
  • 原文地址:https://www.cnblogs.com/zhangqingquan/p/4099321.html
Copyright © 2011-2022 走看看