web-dev-qa-db-fra.com

Code très simple, mais erreur "L'activité a été détruite" lors de l'utilisation de Fragment 

J'ai fait un très simple Activité qui montre un simple ListFragment comme ci-dessous:

Mon activité:

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();
    }

}

Mon 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));
    }
   ...
}

Lorsque je lance mon application, je reçois un message d'erreur :

 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)
...

Il se plaint que L'activité a été détruite , Pourquoi ???

P.S. 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>
18
Leem.fin

J'ai également fait face à un problème similaire.
J'ai réalisé que c'était parce que l'activité était en cours de destruction alors que la FragmentTransaction était sur le point d'obtenir .commit().

Une solution à ce problème consistait à vérifier si Activity.isFinishing() est vrai ou non.

if (!isFinishing()) {
  FragmentTransaction ft = getSupportFragmentManager()
     .beginTransaction();
  ft.replace(SOME_RES_ID, myFragmentInstance);
  ft.commit();
}
67
rishabhmhjn

Je me suis dit, c'est parce que j'ai raté la fonction super.onCreate(savedInstanceState); dans ma méthode Activity onCreate (). Après avoir ajouté ceci, tout va bien. 

32
Leem.fin

J'ai rencontré le même problème et je suis incapable de le résoudre . L'événement auquel j'ai ajouté isFinishing () check également. mais pas de chance.

puis j'ai ajouté un autre check isDestroyed () et ça fonctionne bien maintenant.

if (!isFinishing() && !isDestroyed()) {
  FragmentTransaction ft = getSupportFragmentManager()
     .beginTransaction();
  ft.replace(LAYOUT_ID, myFragmentInstance);
  ft.commit();
}
12
vikoo

Pour donner une explication:

Le cadre crée la Activity et appelle Activity.onCreate().

Activity.onCreate() s'attachera d'une manière ou d'une autre à la FragmentManager pour l'informer de l'activité d'hébergement. Activity.onDestroy() le désenregistrera à nouveau.

Maintenant, vous étendez Activity et remplacez onCreate(). Vous téléphonez à FragmentManager sans appeler toActivity.onCreate(). Toute la logique d'enregistrement expliquée ci-dessus n'est pas exécutée. La FragmentManager ne connaît donc rien de l'activité et suppose qu'elle a déjà été détruite et génère l'exception avec le message d'erreur trompeur.

4
sstn

Pour m'assurer que je vois bien, MyActivity est l'activité que vous essayez de lancer, puis ajoutez une instance de FirstFragment dans, n'est-ce pas?

Immédiatement, je vois deux choses que vous devez regarder

1) Dans votre activité, vous n’appelez jamais setContentView () ou super.onCreate (). Le premier appel pourrait être un gros problème pour vous car cela signifie que votre mise en page n'a jamais été gonflée et que, par conséquent, la variable R n'existe pas.

2) Votre MyActivity doit avoir son propre fichier de présentation XML, ce qui n’est pas le cas.

2

ce que j'ai fait, c'est tout de suite après que j'appelle

fragmentManager.executePendingTransactions();

et n'essayez jamais de vous engager après l'appel de onpause()

Lire cet article Fragment Transactions & Loss State Activity

1
Asim Habib

Toujours aussi mauvais, parce que j'ai l'erreur "L'activité a été détruite"

ava.lang.IllegalStateException: Activity has been destroyed fragmentTransaction.commitAllowingStateLoss();

Donc, ma solution est d’ajouter check if (!isFinishing()&&!isDestroyed())

 if (!isFinishing()&&!isDestroyed()) {
                        fragmentTransaction.commitAllowingStateLoss();
                    }
                }
1
Serg Burlaka

Si quelqu'un rencontre le même type de problème:

Je faisais face au même moment de problème, mais dans mon cas de Main Activity, j’appelais Fragment1 puis, si l’utilisateur clique sur Fragment1 Layout, je souhaite lancer un autre Fragment2 Layout.

J'ai pu lancer Fragment1 à partir de l'activité principale, mais Fragment1 à Fragment2 ne fonctionnait pas, sauf que "L'activité a été détruite"

J'ai résolu le problème ci-dessus en maintenant l'objet FragmentManager statique dans la classe MainActivity . private FragmentManager statique mfragmentManager = null;

appeler les deux fragments en utilisant le même objet, résolut mon problème.

Vous trouverez ci-dessous le code de commutation de fragment de l'activité principale.

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();
    }
0
Rohan J Mohite

super.onCreate (savedInstanceState) appellera la méthode onCreate dans FragmentActivity, qui appellera mFragments.attachHost(null /*parent*/);

Cette phrase assignera une valeur à mHost dans FragmentController, lorsque vous appelez FragmentTransaction.commit (),

Dans la méthode enqueueAction(), il a cette phrase 

 if (mDestroyed || mHost == null) {
        throw new IllegalStateException("Activity has been destroyed");
 }

Donc, si vous n'avez pas appelé super.onCreate (savedInstanceState) avant de valider une transaction fragmentTransaction, vous obtiendrez cette exception car mHost est null 

0
dx3904