web-dev-qa-db-fra.com

Que faut-il utiliser à la place de "addPreferencesFromResource" dans un PreferenceActivity?

Je viens de remarquer le fait que la méthode addPreferencesFromResource(int preferencesResId) est marquée déconseillée dans la documentation d'Android ( Entrée de référence ).

Malheureusement, aucune méthode alternative n'est fournie dans la description de la méthode.

Quelle méthode doit être utilisée à la place pour connecter un preferenceScreen.xml à PreferenceActivity correspondant?

355
mweisz

Aucune méthode alternative n'est fournie dans la description de la méthode car l'approche recommandée (à partir de l'API de niveau 11) consiste à instancier des objets PreferenceFragment pour charger vos préférences à partir d'un fichier de ressources. Voir l'exemple de code ici: PreferenceActivity

333
glorifiedHacker

Pour ajouter plus d'informations à la réponse correcte ci-dessus, après avoir lu un exemple d'Android-er j'ai découvert que vous pouvez facilement convertir votre activité de préférence en un fragment de préférence. Si vous avez l'activité suivante:

public class MyPreferenceActivity extends PreferenceActivity
{
    @Override
    protected void onCreate(final Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.my_preference_screen);
    }
}

La seule modification à apporter consiste à créer une classe de fragment interne, à déplacer la addPreferencesFromResources() dans le fragment et à appeler le fragment à partir de l'activité, comme suit:

public class MyPreferenceActivity extends PreferenceActivity
{
    @Override
    protected void onCreate(final Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        getFragmentManager().beginTransaction().replace(Android.R.id.content, new MyPreferenceFragment()).commit();
    }

    public static class MyPreferenceFragment extends PreferenceFragment
    {
        @Override
        public void onCreate(final Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
            addPreferencesFromResource(R.xml.my_preference_screen);
        }
    }
}

Il peut exister d'autres subtilités pour créer des préférences plus complexes à partir de fragments; si c'est le cas, j'espère que quelqu'un les notera ici.

187
Garret Wilson

Garret Wilson @ Merci beaucoup! En tant que noob à Android codage, je suis coincé avec le problème d’incompatibilité des préférences pendant tant d’heures, et je le trouve si décevant qu’ils déconseillent d’utiliser certaines méthodes/approches pour de nouvelles qui ne le sont pas. pris en charge par les anciennes API, ce qui oblige à recourir à toutes sortes de solutions de contournement pour que votre application fonctionne dans un large éventail de périphériques. C'est vraiment frustrant!

Votre classe est excellente, car elle vous permet de continuer à travailler dans de nouvelles API avec des préférences telles qu’elles étaient, mais elle n’est pas compatible avec les versions antérieures. Comme j'essaie d'atteindre un large éventail de périphériques, j'ai un peu bricolé pour le faire fonctionner à la fois dans les périphériques antérieurs à l'API 11 et dans les API plus récentes:

import Android.annotation.TargetApi;
import Android.os.Bundle;
import Android.preference.PreferenceActivity;
import Android.preference.PreferenceFragment;

public class MyPrefsActivity extends PreferenceActivity
{
    private static int prefs=R.xml.myprefs;

    @Override
    protected void onCreate(final Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        try {
            getClass().getMethod("getFragmentManager");
            AddResourceApi11AndGreater();
        } catch (NoSuchMethodException e) { //Api < 11
            AddResourceApiLessThan11();
        }
    }

    @SuppressWarnings("deprecation")
    protected void AddResourceApiLessThan11()
    {
        addPreferencesFromResource(prefs);
    }

    @TargetApi(11)
    protected void AddResourceApi11AndGreater()
    {
        getFragmentManager().beginTransaction().replace(Android.R.id.content,
                new PF()).commit();
    }

    @TargetApi(11)
    public static class PF extends PreferenceFragment
    {       
        @Override
        public void onCreate(final Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
            addPreferencesFromResource(MyPrefsActivity.prefs); //outer class
            // private members seem to be visible for inner class, and
            // making it static made things so much easier
        }
    }
}

Testé avec succès sur deux émulateurs (2.2 et 4.2).

Pourquoi mon code a l'air si merdique:

Je suis un noob à Android coder, et je ne suis pas le plus grand fan de Java.

Afin d'éviter l'avertissement déconseillé et de forcer Eclipse à me permettre de compiler, je devais recourir à des annotations, mais celles-ci ne semblaient affecter que les classes ou les méthodes. J'ai donc dû déplacer le code sur deux nouvelles méthodes pour en tirer parti.

Je n'aimerais pas écrire deux fois mon identifiant de ressource xml à chaque fois que je copie/colle la classe pour une nouvelle PreferenceActivity. J'ai donc créé une nouvelle variable pour stocker cette valeur.

J'espère que cela sera utile à quelqu'un d'autre.

P.S .: Désolé pour mon point de vue, mais quand vous venez de nouveau et trouvez de tels handicaps, vous ne pouvez pas vous empêcher de frustrer!

37
ecv

Mon approche est très proche de Garret Wilson (merci, je vous ai voté;)

De plus, il offre une compatibilité descendante avec Android <3.

Je viens de reconnaître que ma solution est encore plus proche de celle de Kevin Remo . C'est juste un petit peu plus propre (car il ne repose pas sur le "antipection" ).

public class MyPreferenceActivity extends PreferenceActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
            onCreatePreferenceActivity();
        } else {
            onCreatePreferenceFragment();
        }
    }

    /**
     * Wraps legacy {@link #onCreate(Bundle)} code for Android < 3 (i.e. API lvl
     * < 11).
     */
    @SuppressWarnings("deprecation")
    private void onCreatePreferenceActivity() {
        addPreferencesFromResource(R.xml.preferences);
    }

    /**
     * Wraps {@link #onCreate(Bundle)} code for Android >= 3 (i.e. API lvl >=
     * 11).
     */
    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    private void onCreatePreferenceFragment() {
        getFragmentManager().beginTransaction()
                .replace(Android.R.id.content, new MyPreferenceFragment ())
                .commit();
    }
}

Pour un exemple "réel" (mais plus complexe), voir NusicPreferencesActivity et NusicPreferencesFragment .

22
schnatterer

Au lieu d'exceptions, utilisez simplement:

if (Build.VERSION.SDK_INT >= 11)

et utilise

@SuppressLint("NewApi")

supprimer les avertissements.

6
Peter

Au lieu d'utiliser un PreferenceActivity pour charger directement les préférences, utilisez un AppCompatActivity ou un équivalent qui charge un PreferenceFragmentCompat qui charge vos préférences. Cela fait partie de la bibliothèque de support (maintenant Android Jetpack) et assure la compatibilité avec l'API 14.

Dans votre build.gradle, ajoutez une dépendance pour la bibliothèque de prise en charge des préférences:

dependencies {
    // ...
    implementation "androidx.preference:preference:1.0.0-alpha1"
}

Remarque: Nous allons supposer que vos préférences XML ont déjà été créées.

Pour votre activité, créez une nouvelle classe d'activité. Si vous utilisez des thèmes matériels, vous devriez étendre un AppCompatActivity, mais vous pouvez être flexible avec ceci:

public class MyPreferencesActivity extends AppCompatActivity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.my_preferences_activity)
        if (savedInstanceState == null) {
            getSupportFragmentManager().beginTransaction()
                    .replace(R.id.fragment_container, MyPreferencesFragment())
                    .commitNow()
        }
    }
}

Passons maintenant à la partie importante: créez un fragment qui charge vos préférences à partir de XML:

public class MyPreferencesFragment extends PreferenceFragmentCompat {

    @Override
    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
        setPreferencesFromResource(R.xml.my_preferences_fragment); // Your preferences fragment
    }
}

Pour plus d'informations, lisez le Android Developers docs pour PreferenceFragmentCompat.

0