私は非常に単純なActivityを作成しました。これは以下のような単純なListFragmentを示しています。
私の活動:
public class MyActivity extends FragmentActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
FragmentManager fragMgr = getSupportFragmentManager();
FirstFragment list = new FirstFragment();
fragMgr.beginTransaction().add(Android.R.id.content, list).commit();
}
}
私のListFragment:
public class FirstFragment extends ListFragment{
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
inflater.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.main, null);
return view;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
String listContent[] = {"Larry", "Moe", "Curly"};
setListAdapter(new ArrayAdapter<String>(getActivity(), R.layout.list_item, listContent));
}
...
}
アプリを起動すると、エラーメッセージが表示されました。
Java.lang.IllegalStateException: Activity has been destroyed
E/AndroidRuntime( 947): at Android.app.ActivityThread.performLaunchActivity(ActivityThread.Java:2496)
E/AndroidRuntime( 947): at Android.app.ActivityThread.handleLaunchActivity(ActivityThread.Java:2512)
E/AndroidRuntime( 947): at Android.app.ActivityThread.access$2200(ActivityThread.Java:119)
E/AndroidRuntime( 947): at Android.app.ActivityThread$H.handleMessage(ActivityThread.Java:1863)
E/AndroidRuntime( 947): at Android.os.Handler.dispatchMessage(Handler.Java:99)
E/AndroidRuntime( 947): at Android.os.Looper.loop(Looper.Java:123)
E/AndroidRuntime( 947): at Android.app.ActivityThread.main(ActivityThread.Java:4363)
E/AndroidRuntime( 947): at Java.lang.reflect.Method.invokeNative(Native Method)
...
アクティビティが破壊された、なぜ???と文句を言う
追伸main.xml:
<?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"
Android:paddingLeft="8dp"
Android:paddingRight="8dp">
<Button
Android:layout_width="fill_parent"
Android:layout_height="wrap_content"
Android:text="next" />
<ListView
Android:id="@Android:id/list"
Android:layout_width="fill_parent"
Android:layout_height="fill_parent"
Android:background="#00FF00"
Android:layout_weight="1"
Android:drawSelectorOnTop="false" />
<TextView
Android:id="@Android:id/empty"
Android:layout_width="fill_parent"
Android:layout_height="fill_parent"
Android:background="#FF0000"
Android:text="No data" />
</LinearLayout>
私も同様の問題に直面しました。
これは、FragmentTransaction
が.commit()
を取得しようとしたときにアクティビティが破棄されたために発生したことに気付きました。
これに対する解決策は、Activity.isFinishing()
がtrueかどうかをチェックすることでした。
if (!isFinishing()) {
FragmentTransaction ft = getSupportFragmentManager()
.beginTransaction();
ft.replace(SOME_RES_ID, myFragmentInstance);
ft.commit();
}
私は自分自身を理解しました。それは、アクティビティのonCreate()メソッドでsuper.onCreate(savedInstanceState);
を逃したためです。これを追加した後、問題はありません。
私は同じ問題に直面し、それを修正することができませんでした。追加したイベントはisFinishing()チェックでもあります。しかし運はありません。
次に、もう1つのチェックisDestroyed()を追加し、正常に機能するようにしました。
if (!isFinishing() && !isDestroyed()) {
FragmentTransaction ft = getSupportFragmentManager()
.beginTransaction();
ft.replace(LAYOUT_ID, myFragmentInstance);
ft.commit();
}
説明するには:
フレームワークはActivity
を作成し、Activity.onCreate()
を呼び出します。
Activity.onCreate()
はFragmentManager
に接続して、ホスティングアクティビティについて通知します。 Activity.onDestroy()
は再び登録を解除します。
次に、Activity
を拡張し、onCreate()
をオーバーライドします。 toActivity.onCreate()
を介さずにFragmentManager
を呼び出します。上記で説明した登録ロジック全体は実行されません。したがって、FragmentManager
はアクティビティについて何も認識せず、すでに破棄されていると想定し、誤解を招くエラーメッセージで例外を生成します。
この権利が正しく表示されていることを確認するために、MyActivityは、起動してFirstFragmentのインスタンスを追加しようとしているアクティビティです。
すぐに私はあなたが見る必要がある2つのことを見る
1)アクティビティでは、setContentView()またはsuper.onCreate()を呼び出すことはありません。最初の呼び出しは、レイアウトが膨らんだことがないため、R変数が存在しないため、大きな問題になる可能性があります。
2)MyActivityには独自のxmlレイアウトファイルが必要ですが、それはありません。
私がやったことは、コミットした直後です
fragmentManager.executePendingTransactions();
onpause()
が呼び出された後はコミットしないでください
このアーティカルを読む フラグメントトランザクションとアクティビティ状態の損失
それでも悪い、「アクティビティが破棄されました」というエラーが発生したため
_ava.lang.IllegalStateException: Activity has been destroyed fragmentTransaction.commitAllowingStateLoss();
_
だから私の解決策はチェックを追加することですif (!isFinishing()&&!isDestroyed())
_ if (!isFinishing()&&!isDestroyed()) {
fragmentTransaction.commitAllowingStateLoss();
}
}
_
似たような問題が発生した場合:
私は同じ問題に直面していましたが、私の場合、メインアクティビティからFragment1を呼び出していたため、ユーザーがFragment1レイアウトをクリックした場合、別のFragment2レイアウトを起動します。
メインアクティビティからFragment1を起動することはできましたが、Fragment1からFragment2に例外が発生しました"Activity has been destroy"。
MainActivityクラスでFragmentManagerオブジェクトを静的として維持することにより、上記の問題を解決しました。プライベート静的FragmentManager mfragmentManager = null;
上記の同じオブジェクトを使用して両方のフラグメントを呼び出すと、問題が解決しました。
以下は、メインアクティビティのフラグメント切り替えコードです。
public void switchToFragment(String fragmentName){
Fragment fragment = null;
switch (fragmentName) {
case "Fragment1":{
fragment = new Fragment1();
break;
}
case "Fragment2": {
fragment = new Fragment2();
break;
}
}
FragmentTransaction transaction = mfragmentManager.beginTransaction();
transaction.replace(R.id.fragment_container, fragment);
transaction.commit();
}
super.onCreate(savedInstanceState)は、mFragments.attachHost(null /*parent*/);
を呼び出すFragmentActivityのonCreateメソッドを呼び出します
この文は、FragmentTransaction.commit()を呼び出すと、FragmentControllerのmHost
に値を割り当てます。
メソッドenqueueAction()
では、この文があります
if (mDestroyed || mHost == null) {
throw new IllegalStateException("Activity has been destroyed");
}
したがって、fragmentTransactionをコミットする前にsuper.onCreate(savedInstanceState)を呼び出さなかった場合、mHostがnullであるため、この例外が発生します。