Honeycombでアプリを開発し、フラグメントを使用しています。
これは私のアプリです
私の問題は何ですか
ユーザーがデバイスを回転させると、アクティビティが再作成され、回転前ではなかったにもかかわらず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();
}
_
デフォルトでは、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
}
}
フラグメントに一意のタグを付け、このフラグメントが既にアクティビティに追加されているかどうかを確認する必要があります。
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
)を操作する場合に特に便利です。
Activity
でonAttachFragment()
を使用して、オブジェクトを再割り当てします。
@Override
public void onAttachFragment(Fragment fragment) {
if (fragment instanceof MyFragment)
this.myFragment = (MyFragment) fragment;
}
フラグメントクラスのRetainInstance
内にOnCreate
プロパティを設定するだけです。
public override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
RetainInstance = true;
}
アクティビティのレイアウトでFragment
を定義しました。onSaveInstanceState
のFragment
は呼び出されますが、フラグメントのsavedInstanceState
のBundle
onCreatView
はnullになります。
その理由は、私のFragment
にXMLのIDがなかったからです。
Android:id="@+id/compass_fragment" ...
@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();
}
}
}