2012年12月11日火曜日

Android ActionBarとFragmentを利用したTab画面でFragment#OnCreateが2回走る

結構ハマった・・・。

以前作ったActionBarを使ったTab画面で
Android ActionBarとFragmentを使用してTab画面を表示する(Android 2.x)
Android ActionBarとFragmentを使用してTab画面を表示する(Android 4.0以上)
エミュレータの縦横を切り替えると、描画が2重になっているような現象になってました。
FragmentのOnCreateが2回呼ばれていて、Fragmentが2つ重なっているような感じ。

原因はTabLisnerでした。
エミュレータの縦横を切り替えると、Activityが再作成される。
このときFragmentは自動で復元されており1回目のonCreateが走る。
で、Activityが再作成されたので、TabLisnerも再作成されてonTabSelectedが走る。
この時インスタンス変数mFragmentはnullなのでFragmentManagerに再度addされ
2つ目のFragmentがインスタンス化され2回目のonCreateが走る。
たぶん・・・こんな感じ・・・?

なのでコンストラクタでFragmentを探すように変更し
onTabSelectedでもdetachされていないときだけattachするよう変更しました

コードは Android ActionBarとFragmentを使用してTab画面を表示する(Android 2.x)
のTabListenerです。
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;

import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.ActionBar.Tab;
import com.actionbarsherlock.app.SherlockFragmentActivity;

public class TabListener implements ActionBar.TabListener {

    private Fragment mFragment;
    private final SherlockFragmentActivity mActivity;
    private final String mTag;
    private final Class mClass;
    
    /**
     * @brief コンストラクタ
     * @param activity
     * @param tag
     * @param clz
     */
    public TabListener(SherlockFragmentActivity activity, String tag, Class clz) {
        mActivity = activity;
        mTag = tag;
        mClass = clz;
        //FragmentManagerからFragmentを探す。
        mFragment = mActivity.getSupportFragmentManager().findFragmentByTag(mTag);
    }

    /**
     * @brief  タブが選択されたときの処理
     */
    public void onTabSelected(Tab tab, FragmentTransaction ft) {
        //ftはnullではないが使用するとNullPointExceptionで落ちる
        if (mFragment == null) {
            mFragment = Fragment.instantiate(mActivity, mClass.getName());
            FragmentManager fm = mActivity.getSupportFragmentManager();
            fm.beginTransaction().add(R.id.container, mFragment, mTag).commit();
        } else {
         //detachされていないときだけattachするよう変更
            if (mFragment.isDetached()) {
                FragmentManager fm = mActivity.getSupportFragmentManager();
                fm.beginTransaction().attach(mFragment).commit();
             }
        }
    }
    /**
     * @brief  タブの選択が解除されたときの処理
     */
    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
        //ftはnullではないが使用するとNullPointExceptionで落ちる
        if (mFragment != null) {
            FragmentManager fm = mActivity.getSupportFragmentManager();
            fm.beginTransaction().detach(mFragment).commit();
       }    
    }
    /**
     * @brief タブが2度目以降に選択されたときの処理
     */
    public void onTabReselected(Tab tab, FragmentTransaction ft) {
    }
}

0 件のコメント: