2011-08-02 24 views
9

我正在设计一个应用程序,允许用户在ViewPager中的多个页面之间切换。我一直在努力研究如何从页面中删除一个Fragment实例,当它不再在屏幕上可见时将其缓存(对HashMap),然后将其恢复,以便当用户翻转回该页面,其中的视图和其他所有内容将处于删除前的相同状态。例如,我的第一个页面是一个登录屏幕,可以使某个特定页面上的某些布局元素在成功登录时可见/不可见。当我翻转足够的页面然后翻回第一页时,布局被重置。对于另一个包含巨大的水平/垂直滚动数据网格的页面来说,这变成了一个问题,我使用背景中的线程在初始化时进行绘制。我使用一个进度对话框来通知用户加载进度,每次我必须加载时它变得非常烦人。Android:Viewpager和FragmentStatePageAdapter

所以我做了一些研究...

我通过了FragmentStatePageAdapter的源代码,并在destroyItem()回调浏览,片段实例被删除的状态保存到一个ArrayList。当在instantiateItem()回调中创建Fragment的新实例时,如果某个项目的实例尚不存在(它们通过使用ArrayList跟踪此事件),则会创建一个新的Fragment实例并创建其保存的状态使用相应的Fragment.SavedState数据进行初始化。不幸的是,这些数据并不包含视图所在的状态,尽管我注意到对于具有GridView/ListView的页面,视图的状态以某种方式恢复(如果我滚动到某个随机位置,翻转几页并返回,它不会被重置)。

根据API:

保存的状态不能包含在其它片段的依赖性 - 即它不能使用putFragment(捆绑,字符串,片段),用于存储一个 片段引用,因为当以后使用此保存的状态时,该引用可能无效。同样,片段的目标和结果 代码不包含在此状态中。

作为Android的noob,我不太确定我理解最后的声明。

这就是说,有什么办法来缓存视图状态?如果没有,我想我会继续前进,并将所有的片段页面留在内存中。

回答

1

查看各种文档,我最好的猜测是您创建的视图没有附加ID。假设片段的保存状态是从Fragment.onSaveInstanceState创建的,那么片段将自动保存具有ID的任何视图的状态。如果您从布局文件创建它们,您可能有一个与您的ListView/GridView关联的默认ID。您也可以通过调用setId将id与视图相关联。

此外,对于您的自定义填充片段,您可能还必须在onSaveInstanceState中执行一些自定义操作。

4

我有同样的问题的问题,并通过对,我想救片段实现这两种功能

public void onSaveInstanceState (Bundle outState) 
    public void onActivityCreated (Bundle savedInstanceState) 

解决它。在第一个函数中,你应该在Bundle中保存你需要恢复视图的日期(在我的情况下,我有一堆微调,所以我用 一个int数组来保存它们的位置)。第二个函数在恢复片段时被调用,它是您实现恢复过程的地方。

我希望这会有所帮助。我也使我的适配器从FragmentStatePageAdapter继承,但我不确定这是强制性的。

+3

你需要从FragmentStatePagerAdapter继承,如果你只使用FragmentPagerAdapter然后将的onSaveInstanceState不会被调用。 – Scott

2

main.xml中

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical" android:layout_width="fill_parent" 
    android:layout_height="fill_parent"> 
    <TextView android:text="Page 1" android:id="@+id/textViewHeader" 
     android:layout_width="fill_parent" android:layout_height="wrap_content" 
     android:gravity="center" android:padding="10dip" android:textStyle="bold"></TextView> 
    <android.support.v4.view.ViewPager 
     android:layout_width="fill_parent" android:layout_height="fill_parent" 
     android:id="@+id/viewPager" /> 
</LinearLayout> 

建立ViewPager

ViewPager viewPager = (ViewPager) findViewById(R.id.viewPager); 
MyPagerAdapter adapter = new MyPagerAdapter(this); 
viewPager.setAdapter(adapter); 

的PagerAdapter

@Override 
public void destroyItem(View view, int arg1, Object object) { 
     ((ViewPager) view).removeView((View)object); 
} 
@Override 
public int getCount() { 
      return views.size(); 
} 
@Override 
public Object instantiateItem(View view, int position) { 
      View view = views.get(position); 
      ((ViewPager) view).addView(view); 
      return view; 
} 
@Override 
public boolean isViewFromObject(View view, Object object) { 
      return view == object; 
} 

看这里了解更多详情view pager example

1

H的上市这是我在PagerAdapter中实现缓存的一个例子。填充缓存后,所有将来的查看请求都从缓存中提供,只有数据被替换。

public class TestPageAdapter extends PagerAdapter{ 

private int MAX_SIZE = 3; 
private ArrayList<SoftReference<View>> pageCache = new ArrayList<SoftReference<View>>(3); 


public TestPageAdapter(Context context){ 
    // do some initialization 
} 

@Override 
public int getCount() { 
    // number of pages 
} 

private void addToCache(View view){ 
    if (pageCache.size() < MAX_SIZE){ 
     pageCache.add(new SoftReference<View>(view)); 
    } else { 
     for(int n = (pageCache.size()-1); n >= 0; n--) { 
      SoftReference<View> cachedView = pageCache.get(n); 
      if (cachedView.get() == null){ 
       pageCache.set(n, new SoftReference<View>(view)); 
       return; 
      } 
     } 
    } 
} 

private View fetchFromCache(){ 
    for(int n = (pageCache.size()-1); n>= 0; n--) { 
     SoftReference<View> reference = pageCache.remove(n); 
     View view = reference.get(); 
     if (view != null) { 
      return view; 
     } 
    } 
    return null; 
} 

@Override 
public Object instantiateItem(View collection, int position) { 
    View view = fetchFromCache(); 
    if (view == null) { 
     // not in cache, inflate manually 
     LayoutInflater inflater = (LayoutInflater) collection.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     view = inflater.inflate(R.layout.page, null); 
    } 
    setData(view, position); 
    ((ViewPager) collection).addView(view, 0); 
    return view;   
} 

private void setData(View view, int position){ 
    // set page data (images, text ....) 
} 

public void setPrimaryItem(ViewGroup container, int position, Object object) { 
    currentItem = (View)object; 
} 

public View getCurrentItem() { 
    return currentItem; 
} 

@Override 
public boolean isViewFromObject(View view, Object object) { 
    return view == ((View) object); 
} 

@Override 
public void destroyItem(View collection, int arg1, Object view) { 
    ((ViewPager) collection).removeView((View) view); 
    addToCache((View) view); 
} 

} 
0

我也遇到了这个问题,我用的时候PagerSlidingTabStrip使用和FragmentPagerAdapter的情况下,切换到FragmentStatePagerAdapter肯定工作。

然后我用的onSaveInstanceState()保存沙爹

相关问题