2013-07-13 16 views
17

データベースへの変更を通知する必要があるいくつかのフラグメントを含むFragmentPagerAdapterを使用します。私は、コールバックインターフェイスを実装するフラグメントを繰り返し処理し、refreshData()メソッドを呼び出すことによってこれを行います。FragmentPagerAdapter - オリエンテーションの変更を処理する方法は?

これは、デバイスの向きが変わるまでうまく動作します。向きが変更された後、メソッド呼び出しが機能しているように見えるにもかかわらず、フラグメントUIが目に見えるように更新されません。

これまでに私が読んだことは、FragmentPagerAdapterがフラグメントのライフサイクルを処理し、コールバックを受け取るフラグメントが実際に表示されるものではないためです。

private class DataPagerAdapter extends FragmentPagerAdapter { 

    private DataFragment[] fragments = new DataFragment[] { 
            new FooDataFragment(), BarDataFragment()}; 

    public DataPagerAdapter(android.support.v4.app.FragmentManager fm) { 
     super(fm); 
    } 

    @Override 
    public Fragment getItem(int position) { 
     return fragments[position]; 
    } 

    @Override 
    public int getCount() { 
     return fragments.length; 
    } 

    public DataFragment[] getFragments() { 
     return fragments; 
    } 
} 

protected void refreshData() { 
    for (DataFragment dataFragment : mPagerAdapter.getFragments()) { 
    dataFragment.refreshData(); 
} 

この問題は、各フラグメント内にブロードキャスト受信機を使用して一時的に修正されましたが、この解決策は無駄であり、メモリリークを引き起こす可能性があります。これを正しく修正する方法は?私はランドスケープの変更後に新しく作成されたフラグメントを使いたいので、ランドスケープモードで別のレイアウトとロジックを使用します。

+1

マニフェストアンドロイドでウルactivtyタグにこれを追加します。configChanges =「オリエンテーション|画面サイズ| keyboardHidden」(ターゲットAPI 13+) – TheFlash

+0

minSdkVersionがが私 –

答えて

52

はい、FragmentManagerは方向変更後にフラグメントを処理するので、アダプタのgetItemは呼び出されません。しかし、オリエンテーションを変更した後でも呼び出されるメソッドinstantiateItem()をオーバーライドし、Object to Fragmentをキャストして配列に保存することができます。

@Override 
public Object instantiateItem(ViewGroup container, int position) { 
    DataFragment fragment = (DataFragment) super.instantiateItem(container, position); 
    fragments[position] = fragment; 
    return fragment; 
} 
+0

このため7ので、この文句を言わない仕事です残念ながら、行動はまだ同じです。私はまた、アンドロイドを追加しようとしました:configChanges = "方向"マニフェストに。 –

+1

manifestにorientantionChangesを使用することはお勧めできません。だからあなたはまだrefreshData()が古いフラグメントで呼び出されていると言っていますか?あなたはいつrefreshData()を呼び出しますか? instantiateItem()が実際に呼び出され、refreshData()メソッドの前に呼び出されたかどうかを確認する必要があります。 – koso

+0

あなたは正しいです、呼び出されていません。奇妙な助言がありますか? refreshData()は、フラグメントインスタンシエーションの後に長時間呼び出されます。たとえば、ユーザーがボタンを押したときなど、バックグラウンドサービスによって非同期にトリガーされる場合があります。 –

-1

私は実用的なソリューションと同様の問題を抱えていた:あなたのアダプタでの活動場所で アダプタコールがadapter.notifyDataSetChanged();

でオーバーライドgetItemPostion()メソッド

@Override 
    public int getItemPosition(Object object) { 
     MyFragment frag = (MyFragment)object; 
     frag.refresh(); 
     return POSITION_UNCHANGED; 
    } 

私のFragmentStatePagerAdapaterを(私のアダプタ)が含まれ私はあなたがinstanceof(より多くの種類のフラグメント用)を使用し、次にキャストを使用するか、またはすべてのフラグメントがメソッドを使用して実装されると思うと思います

は、その後、あなたのフラグメント(複数可)でメソッドrefresh()を追加し、この実装を使用します。

public void refresh() { 
     LayoutInflater inflater = LayoutInflater.from(getActivity()); 
     ViewGroup viewGroup = (ViewGroup) getView(); 
     viewGroup.removeAllViewsInLayout(); 
     View view = onCreateView(inflater, viewGroup, null); 
     viewGroup.addView(view); 

    } 

は、これは私のために働きました。 私の意見: デバイスが向きを変えてアダプタが破損しても、フラグメントがメモリに残っていて、システムが方向変更後に再利用しようとしましたが、フラグメントに含まれるビューも破棄されました。フラグメントは "再作成"する必要があります(onCreateViewメソッドを呼び出します)。多分私は間違っているので、私を修正してください...。

(私の英語のため申し訳ありませんが)

+0

このソリューションはほとんどのアプリケーションでうまくいかないでしょう。 Androidが最適化として(たとえば、向きを変更した後に)フラグメントをあなたのために再インスタンス化するケースがあります。これにより、常に望ましい結果が得られるわけではありません。たとえば、ViewPagerをアクティビティのonCreateの外に追加すると、フラグメントはnullコンテナを取得します。このような問題を修正するには、フラグメントのonCreateView(){if(container == null){removeMeFromFragmentManager();でフラグメントを削除できます。 nullを返す。 ...}。新しいFragmentPageAdapterがこのフラグメントインスタンスを再作成するようになりました。 – dzlatkov

関連する問題