2011-08-02 23 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()保存沙爹

相關問題