365 Stimmen

Was ist anstelle von "addPreferencesFromResource" in einer PreferenceActivity zu verwenden?

Mir ist gerade aufgefallen, dass die Methode addPreferencesFromResource(int preferencesResId) markiert ist Abgelehnt in der Dokumentation von Android ( Referenzeintrag ).

Leider wird in der Methodenbeschreibung keine alternative Methode angegeben.

Welche Methode sollte stattdessen verwendet werden, um eine preferenceScreen.xml mit der passenden PreferenceActivity zu verbinden?

334voto

glorifiedHacker Punkte 6410

In der Beschreibung der Methode wird keine alternative Methode angegeben, da der bevorzugte Ansatz (ab API-Stufe 11) darin besteht, Folgendes zu instanziieren PräferenzFragment Objekte, um Ihre Einstellungen aus einer Ressourcendatei zu laden. Sehen Sie sich den Beispielcode hier an: PreferenceActivity

189voto

Garret Wilson Punkte 15709

Um die obige richtige Antwort zu ergänzen, sollten Sie nach dem Lesen eines Beispiel von Android-er Ich habe festgestellt, dass Sie Ihre Präferenzaktivität leicht in ein Präferenzfragment umwandeln können. Wenn Sie die folgende Aktivität haben:

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

Die einzigen Änderungen, die Sie vornehmen müssen, sind die Erstellung einer internen Fragmentklasse, die Verschiebung der addPreferencesFromResources() in das Fragment einfügen und das Fragment von der Aktivität aus aufrufen, etwa so:

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

Vielleicht gibt es noch andere Feinheiten, um aus Fragmenten komplexere Präferenzen zu machen; falls ja, hoffe ich, dass jemand sie hier erwähnt.

38voto

ecv Punkte 708

@Garret Wilson Vielen Dank! Als Neuling in der Android-Programmierung habe ich mich stundenlang mit dem Problem der Inkompatibilität der Einstellungen herumgeschlagen, und ich finde es so enttäuschend, dass einige Methoden/Ansätze für neue, die von den älteren APIs nicht unterstützt werden, veraltet sind, so dass man auf alle möglichen Workarounds zurückgreifen muss, damit die App auf einer Vielzahl von Geräten funktioniert. Das ist wirklich frustrierend!

Ihre Klasse ist großartig, denn sie ermöglicht es Ihnen, in neuen APIs mit den Einstellungen zu arbeiten, wie es früher war, aber sie ist nicht abwärtskompatibel. Da ich versuche, eine breite Palette von Geräten zu erreichen, habe ich ein bisschen daran herumgebastelt, damit es sowohl in Geräten vor API 11 als auch in neueren APIs funktioniert:

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
        }
    }
}

Getestet in zwei Emulatoren (2.2 und 4.2) mit Erfolg.

Warum mein Code so beschissen aussieht:

Ich bin ein Neuling in der Android-Programmierung und nicht der größte Java-Fan.

Um die veraltete Warnung zu vermeiden und Eclipse zu zwingen, mich kompilieren zu lassen, musste ich auf Anmerkungen zurückgreifen, aber diese scheinen nur Klassen oder Methoden zu betreffen, also musste ich den Code in zwei neue Methoden verschieben, um davon zu profitieren.

Ich möchte nicht jedes Mal, wenn ich die Klasse für eine neue PreferenceActivity kopiere und einfüge, meine xml-Ressourcen-ID zweimal schreiben müssen, also habe ich eine neue Variable erstellt, um diesen Wert zu speichern.

Ich hoffe, dass dies für jemand anderen nützlich sein wird.

P.S.: Entschuldigen Sie bitte meine Meinung, aber wenn man neu ist und solche Nachteile vorfindet, kann man nicht anders, als frustriert zu sein!

22voto

schnatterer Punkte 6859

Mein Ansatz ist sehr ähnlich zu Garret Wilson's (danke, ich habe dich hochgestimmt ;)

Darüber hinaus bietet es Abwärtskompatibilität mit Android < 3.

Ich habe gerade festgestellt, dass meine Lösung noch näher an der Lösung von Kevin Remo . Es ist nur ein bisschen sauberer (da es sich nicht auf die Antipattern "Prüfung" ).

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

Für ein "echtes" (aber komplexeres) Beispiel siehe NusicPreferencesActivity y NusicPreferencesFragment .

6voto

Peter Punkte 69

Verwenden Sie anstelle von Ausnahmen einfach:

if (Build.VERSION.SDK_INT >= 11)

und verwenden

@SuppressLint("NewApi")

um die Warnungen zu unterdrücken.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X