码迷,mamicode.com
首页 > 其他好文 > 详细

Viewpager+fragment数据更新问题解析

时间:2014-11-15 15:31:15      阅读:222      评论:0      收藏:0      [点我收藏+]

标签:android   style   blog   http   io   color   ar   os   使用   

在一个 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的数据更新问题就可以了,通过接口回掉机制来实现。

bubuko.com,布布扣

首先我们定义一个接口,让我们的主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);
  }
  

}

 

 

 

 

 

 

 

 

Viewpager+fragment数据更新问题解析

标签:android   style   blog   http   io   color   ar   os   使用   

原文地址:http://www.cnblogs.com/zhangqingquan/p/4099321.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!