.getSupportActionBar pas disponible dans le Fragment; solution conduit à NullPointerException lors de la rotation

Structure

(noms de Activies/Fragments changé)

Basé sur des conseils écrits dans Android de Programmation: Le Big Nerd Ranch Guide, j'ai la structure suivante:

  • MyListFragment extends ListFragment
  • MyListActivity extends SimpleFragmentActivity
  • SimpleFragmentActivity extends ActionBarActivity

MyListActivity.java

public class MyListActivity extends SingleFragmentActivity {

    @Override
    protected Fragment createFragment() {
        return new MyListFragment();
    }
}

SingleFragmentActivity.java

public abstract class SingleFragmentActivity extends ActionBarActivity {

    protected abstract Fragment createFragment ();

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

        FragmentManager fm = getSupportFragmentManager();
        Fragment fragment = fm.findFragmentById(R.id.fragmentContainer);

        if (fragment == null) {
            fragment = createFragment();
            fm.beginTransaction().add(R.id.fragmentContainer, fragment).commit();
        }
    }
}

Après avoir présenté et programmé les fonctionnalités de base de mon application (y compris Contextuel de la Barre d'Action, navigation, ...), je voulais vous assurer que l'application est aussi compatible que possible sans trop d'effort supplémentaire. Donc, j'ai commencé à utiliser le AppCompat (com.android.support:appcompat-v7:20+) ActionBar.

Ce qui m'a dérouté au début était que—contrairement à toutes tutoriel ou Android du Développeur lignes directrices j'ai lu—l'getSupportActionBar méthode n'a jamais été disponible dans Android Studio (je suis sous Android Studio v0.8.2 et JRE 1.7_60). Chaque fois que je tape getActivity().getSup, la seule suggestions que je reçois sont getSupportFragmentManager et getSupportLoaderManager.

Comme une solution de contournement, j'ai créer une variable de membre ActionBar mActionBar dans MyListFragment et l'initialiser:

@Override
public void onAttach (Activity activity) {
    super.onAttach(activity);
    mActionBar = ((ActionBarActivity) activity).getSupportActionBar();
}

Qui semblait faire l'affaire sur Android 4.4.4 (Moto G) et 2.3.4 (LG E-510)—les seuls appareils que j'ai à ma disposition.

Toutefois—pour en venir au problème que j'ai sur la rotation de l'ActionBar affectation se perd et l'application se bloque avec une NullPointerException. Débogage de l'application et de fixer un point d'arrêt sur la ligne suivante dans onCreate:

mActionBar.setTitle(R.string.title_activity_my_list);

J'ai trouvé que mActionBar est nulle après la rotation. Placer la ligne dans onCreateView n'a pas aidé.

Ce que j'ai essayé

  • Plaçant l'initialisation de mActionBar dans
    • onAttach
    • onActivityCreated
    • onCreate/onCreateView juste avant .setTitle est appelée

Je suis à court d'idées ici et reconnaissant pour les conseils.

EDIT-0 (30.07.)

Exception levée (après l'édition selon Alex’ suggestion)

07-30 15:05:25.239    5049-5049/MYAPPNAME E/AndroidRuntime [Blue Error Handler] Make Debugging Report file for main
java.lang.RuntimeException: Unable to start activity ComponentInfo{MYAPPNAME/MYAPPNAME.MYLISTACTIVITY}: java.lang.NullPointerException
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1653)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1669)
at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:2838)
at android.app.ActivityThread.access$1600(ActivityThread.java:117)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:935)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:130)
at android.app.ActivityThread.main(ActivityThread.java:3737)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:894)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:652)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at MYAPPNAME.MYLISTFRAGMENT.onCreate(MYLISTFRAGMENT.java:54)
at android.support.v4.app.Fragment.performCreate(Fragment.java:1481)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:908)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1121)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1103)
at android.support.v4.app.FragmentManagerImpl.dispatchCreate(FragmentManager.java:1896)
at android.support.v4.app.FragmentActivity.onCreate(FragmentActivity.java:216)
at android.support.v7.app.ActionBarActivity.onCreate(ActionBarActivity.java:98)
at MYAPPNAME.SingleFragmentActivity.onCreate(SingleFragmentActivity.java:22)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1617)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1669)
at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:2838)
at android.app.ActivityThread.access$1600(ActivityThread.java:117)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:935)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:130)
at android.app.ActivityThread.main(ActivityThread.java:3737)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:894)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:652)
at dalvik.system.NativeStart.main(Native Method)

MyListFragment ligne 54 (exception s'est produite en utilisant soit SingleFragmentActivity et ActionBarActivity comme un cast)

((SingleFragmentActivity) getActivity()).getSupportActionBar().setTitle(R.string
.title_activity_my_list);

SingleFragmentActivity lignes 20-22:

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

OriginalL'auteur PattaFeuFeu | 2014-07-30