web-dev-qa-db-ja.com

回転中にフラグメントオブジェクトを保持する

Honeycombでアプリを開発し、フラグメントを使用しています。
これは私のアプリです

  • アクティビティ(Say A1)があり、その中にフラグメントがあります
  • 最初、このフラグメントは、1つのフラグメントオブジェクト(F1)と言うオブジェクトを保持します
  • その後、ユーザーのアクションに応じて、他のオブジェクトF2、F3 ...に変更される場合があります。

私の問題は何ですか

ユーザーがデバイスを回転させると、アクティビティが再作成され、回転前ではなかったにもかかわらずF1がフラグメントオブジェクトとして作成されます。
_What is the way to retain the fragment object while rotating?_
setRetainInstance(true);を使用しましたが、うまくいきませんでした
そして、このようなonCreate関数にコードでフラグメントを追加しました

_@Override
public void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.main);

   FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();

   Fragment homeFragment = new Home();
   fragmentTransaction.add(R.id.mainFragement, homeFragment);
   fragmentTransaction.commit();
}
_
48
Jithin

デフォルトでは、Androidはフラグメントオブジェクトを保持します。コードでは、homeFragment関数でonCreateを設定しています。これが常にhomeFragmentまたはflは、onCreateで設定したものです。

回転するたびに、onCreateが実行され、フラグメントオブジェクトが最初のオブジェクトに設定されるため

簡単な解決策は、savedInstanceStateバンドルがnullかどうかを確認し、フラグメントオブジェクトを設定することです

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    if(null == savedInstanceState) {
        // set you initial fragment object 
    }
 }
63

フラグメントに一意のタグを付け、このフラグメントが既にアクティビティに追加されているかどうかを確認する必要があります。

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    String tag = "my_fragment";
    FragmentManager fragmentManager = getFragmentManager();
    if(fragmentManager.findFragmentByTag(tag) == null) {
        FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
        Fragment homeFragment = new Home();
        fragmentTransaction.add(R.id.mainFragement, homeFragment, tag);
        fragmentTransaction.commit();
    }
}

savedInstanceStateがnullであるかどうかを確認することは、フラグメントが既に設定されているかどうかを確認する安全な方法ではありません。ほとんどの場合は機能しますが、場合によっては(デバイスが低メモリにある場合など)、Androidはアクティビティを停止する可能性があり、これによりアプリケーションが破損する可能性があります。

これを実際に見るには、デバイスの開発オプションで[アクティビティを保持しない]にチェックマークを付けます(設定はAndroid 4.0+、以前のバージョンは不明)で利用できます。アクティビティ、最初のアクティビティは破棄されます。(戻るボタンを押すことで)戻ると、再び作成され、savedInstanceStateはnotnullです。フラグメントはアクティビティに含まれていないため、再度追加する必要があります。

編集-元の原則を表示しますが、SupportFragmentManagerを使用

public class ActivityAwesome extends AppCompatActivity
{
    private final String TAG = getClass().getSimpleName();
    private FragmentHome mHomeFragment;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_layout);

        FragmentManager fragmentManager = getSupportFragmentManager();
        Fragment fragment = fragmentManager.findFragmentByTag(TAG);
        if(fragment == null)
        {
            // Create the detail fragment and add it to the activity using a fragment transaction.
            mHomeFragment = new FragmentHome();
            fragmentManager.beginTransaction()
                    .add(R.id.fragment_container, mHomeFragment, TAG)
                    .commit();
        }
        else
        {
            // get our old fragment back !
            mHomeFragment = (FragmentHome)fragment;
        }
    }
}

これは、デバイスを回転させた後にフラグメント(この場合はmHomeFragment)を操作する場合に特に便利です。

38
Ralf

ActivityonAttachFragment()を使用して、オブジェクトを再割り当てします。

@Override
public void onAttachFragment(Fragment fragment) {
    if (fragment instanceof MyFragment)
        this.myFragment = (MyFragment) fragment;
}
3
Oded Breiner

フラグメントクラスのRetainInstance内にOnCreateプロパティを設定するだけです。

public override void OnCreate(Bundle savedInstanceState)
{
    base.OnCreate(savedInstanceState);
    RetainInstance = true;
}

回転中にFragmentオブジェクトを保持する

0

アクティビティのレイアウトでFragmentを定義しました。onSaveInstanceStateFragmentは呼び出されますが、フラグメントのsavedInstanceStateBundleonCreatViewはnullになります。

その理由は、私のFragmentにXMLのIDがなかったからです。

Android:id="@+id/compass_fragment" ...
0
zomarev

@Ralfの答えをより動的に再配線するだけで、保持する特定のフラグメントを指定する必要はありませんが、指定する場合は可能です。

 public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //set Home/Main/default fragment
        changeFragmentTo(HomeFragment.newInstance(), FRAGMENT_TAG_HOME_FRAGMENT);


        if (getCurrentFragment() != null) {
            //if screen rotated retain Fragment
            changeFragmentTo(getCurrentFragment(), getCurrentFragment().getTag());

        }

    }


    private Fragment getCurrentFragment() {
//fl_main_container is FarmeLayout where I load my Fragments
        return getSupportFragmentManager().findFragmentById(R.id
                .fl_main_container);
    }



    /**
     * changeFragmentTo(Fragment fragmentToLoad, String fragmentTag)
     *
     * @param fragmentToLoad : dataType > v4.app.Fragment :: the object of the fragment you want to load in form of MyFragment() or MyFragment().newInstance()
     * @param fragmentTag    :  dataType > String :: a String which identify the "tag" of the fragment in form of "FRAGMENT_TAG_MY_FRAGMENT", Value must be stored in {@link models.MyConstants}
     */


    public void changeFragmentTo(Fragment fragmentToLoad, String fragmentTag) {

        if (getSupportFragmentManager().findFragmentByTag(fragmentTag) == null) {
            getSupportFragmentManager()
                    .beginTransaction()
                    .replace(R.id.fl_main_container, fragmentToLoad, fragmentTag)
                    .setTransitionStyle(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
                    .addToBackStack(fragmentTag)
                    .commit();

        } else {
            getSupportFragmentManager()
                    .beginTransaction()
                    .replace(R.id.fl_main_container, fragmentToLoad, fragmentTag)
                    .setTransitionStyle(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
                    .commit();
        }
    }



}
0
Joseph Ali