2011-08-02 8 views
9

私は、ユーザーがViewPagerの複数のページを切り替えることを可能にするアプリケーションを設計しています。私はそれが画面上に表示されなくなったときにページからFragmentインスタンスを削除し、HashMapにキャッシュしてから、そのインスタンスを復元することができるようにするために苦労してきました。そのページに戻って、そのビュー内の他のものは削除前と同じ状態になります。たとえば、私の最初のページは、ログインに成功するとその特定のページの特定のレイアウト要素を表示/非表示にするログイン画面です。十分なページを前にして最初のページに戻すと、レイアウトがリセットされます。これは、巨大な水平/垂直スクロールグリッドのデータグリッドが含まれている私のページの別のものではより問題になり、初期化時にバックグラウンドでスレッドを使用して描画します。進捗状況のダイアログを使用して進捗状況をユーザーに通知し、ロードする度に本当に迷惑になります。Android:ViewpagerとFragmentStatePageAdapter

だから、私はFragmentStatePageAdapterのためのソースコードを閲覧し、destroyItem()コールバックで、削除されるフラグメント・インスタンスの状態は、ArrayListに保存されている...

をいくつかの研究をしました。 instantiateItem()コールバックでフラグメントの新しいインスタンスが作成されているときに、アイテムのインスタンスが存在しない場合(ArrayListを使用してこれを追跡している場合)、新しいFragmentインスタンスが作成され、対応するFragment.SavedStateデータで初期化されます。残念ながら、このデータにはビューの状態は含まれていませんが、GridView/ListViewのページではビューの状態が何らかの形で復元されていることがわかりました(ランダムな位置にスクロールして数ページを反転して戻ったリセットされません)。

APIによると:

保存状態は他の断片の依存関係を含むことができませんに - ので、それは フラグメント参照を格納するputFragment(バンドル、文字列、フラグメント)を使用することはできませんですこの 保存された状態が後で使用されるとき、その参照は有効でない可能性があります。同様に、フラグメントのターゲットおよび結果 コードはこの状態に含まれません。

私は最後の声明をよく理解していません。

つまり、ビューの状態をキャッシュする方法はありますか?もしそうでなければ、私は先に進み、すべてのフラグメントページをメモリに残すことになると思う。

答えて

1

さまざまなドキュメントを見ると、自分が作成しているビューにはIDが関連付けられていないことが一番の推測です。フラグメントの保存された状態がFragment.onSaveInstanceStateから作成されると仮定すると、フラグメントはidを持つビューの状態を自動的に保存します。レイアウトファイルから作成した場合は、ListView/GridViewに関連付けられている既定のIDがある可能性があります。また、idをビューに関連付けるには、setIdを呼び出します。

また、カスタムの埋め込みフラグメントの場合、onSaveInstanceStateでカスタムを行う必要があります。

4

私は同じ問題の問題を抱えていたし、私が保存したかったフラグメントにこれら二つの機能

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

を実装することによってそれを解決しました。最初の関数では、ビューを復元する必要がある日付をBundleに保存する必要があります(私の場合、スピンナーがたくさんあるので、位置を保存するためにint配列 を使用しました)。フラグメントを復元するときに呼び出される第2の関数は、復元プロセスを実装する場所です。

こちらがお役に立てば幸いです。私もFragmentStatePageAdapterから継承するためにアダプタを作成しましたが、これは必須であるとは確信していません。 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; 
} 

の設定main.xmlの

+3

を保存するためにonSaveInstanceState()を使用します。 – Scott

2

リスト

<?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> 

は、詳細についてはこちらをご覧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あなただけにしてFragmentPagerAdapterを使用する場合は、FragmentStatePagerAdapterから継承する必要サテ

関連する問題