您的位置:首页 > 其它

Viewpager+fragment数据更新问题解析

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

[java] view
plaincopy

@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;

}

我们特别关注下以下这句

[java] view
plaincopy

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

[java] view
plaincopy

private List<String> tagList;

第二部重写instantiateItem方法,把fragment对应的标签存储在taglist集合里

[java] view
plaincopy

public Object instantiateItem(ViewGroup container, int position) {

tagList.add(makeFragmentName(container.getId(), getItemId(position)));

return super.instantiateItem(container, position);

}

makeFragmentName()是FragmentPageAdapter源码里打fragment标签的方法

[java] view
plaincopy

public static String makeFragmentName(int viewId, int index) {

return "android:switcher:" + viewId + ":" + index;

}

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

[java] view
plaincopy

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来实现

[java] view
plaincopy

public interface FragmentListener {

public void onFragmentClickListener(int item);

}

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

[java] view
plaincopy

public void onAttach(Activity activity) {

super.onAttach(activity);

try {

listener = (FragmentListener)activity;

} catch (Exception e) {

e.printStackTrace();

}

}

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

[java] view
plaincopy

if (listener != null) {

listener.onFragmentClickListener(1);

}

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

[java] view
plaincopy

public void onFragmentClickListener(int item) {

adapter.update(item);

adapter.update(item);

}

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

[java] view
plaincopy

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

}

}

本文固定链接: http://www.devba.com/index.php/archives/5826.html | 开发吧
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: