Was sollte anstelle von “addPreferencesFromResource” in einer PreferenceActivity verwendet werden?

Mir ist gerade aufgefallen, dass die Methode addPreferencesFromResource(int preferencesResId) in der Android-Dokumentation ( Reference Entry ) als veraltet markiert ist.

Leider ist in der Beschreibung der Methode keine alternative Methode vorgesehen.

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

In der Beschreibung der Methode wird keine alternative Methode angegeben, da der bevorzugte Ansatz (ab API-Ebene 11) die Instanziierung von PreferenceFragment- Objekten zum Laden Ihrer Einstellungen aus einer Ressourcendatei ist. Siehe den Beispielcode hier: PreferenceActivity

Um weitere Informationen zu der richtigen Antwort oben hinzuzufügen, nachdem ich ein Beispiel von Android-er gelesen habe, fand ich, dass Sie Ihre Präferenzaktivität leicht in ein Präferenzfragment umwandeln können. Wenn Sie 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 das Erstellen einer internen Fragmentklasse, das Verschieben der addPreferencesFromResources() in das Fragment und das Aufrufen des Fragments aus der Aktivität wie addPreferencesFromResources() :

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

Es mag andere Feinheiten geben, komplexere Präferenzen aus Fragmenten zu machen; Wenn ja, hoffe ich, dass jemand sie hier notiert.

@Garret Wilson Vielen Dank! Als Noob zu Android-Codierung, habe ich für so viele Stunden mit der Präferenz Inkompatibilität Problem stecken, und ich finde es so enttäuschend sie verwarf die Verwendung einiger Methoden / Ansätze für neue, die nicht von den älteren APIs so unterstützt werden Sie müssen auf alle möglichen Problemumgehungen zurückgreifen, damit Ihre App in einer Vielzahl von Geräten funktioniert. Es ist wirklich frustrierend!

Ihre class ist großartig, denn sie ermöglicht es Ihnen, weiterhin in neuen APIs mit Voreinstellungen zu arbeiten, wie es einmal war, aber es ist nicht abwärtskompatibel. Da ich versuche, eine breite Palette von Geräten zu erreichen, habe ich ein bisschen daran herumgebastelt, um es in Pre-API-11-Geräten sowie in neueren APIs funktionieren zu lassen:

 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 sieht mein Code so beschissen aus:

Ich bin ein Noob zu Android-Codierung, und ich bin nicht der größte Java-Fan.

Um die veraltete Warnung zu vermeiden und zu erzwingen, dass Eclipse mir erlaubt zu kompilieren, musste ich auf Annotationen zurückgreifen, aber diese scheinen nur classn oder Methoden zu beeinflussen, also musste ich den Code auf zwei neue Methoden verschieben, um dies auszunutzen.

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

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

PS: Tut mir leid für meine eigensinnigen Ansichten, aber wenn du neu kommst und solche Handicaps findest, kannst du nicht anders, als frustriert zu sein!

Mein Ansatz ist sehr nah an Garret Wilson (danke, ich habe dich gewählt;)

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

Ich habe gerade erkannt, dass meine Lösung noch näher an der von Kevin Remo liegt . Es ist nur ein bisschen sauberer (da es nicht auf die “Expectation” Antipattern angewiesen ist).

 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 (ie API lvl * < 11). */ @SuppressWarnings("deprecation") private void onCreatePreferenceActivity() { addPreferencesFromResource(R.xml.preferences); } /** * Wraps {@link #onCreate(Bundle)} code for Android >= 3 (ie 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 und NusicPreferencesFragment .

Verwenden Sie anstelle von Ausnahmen einfach:

 if (Build.VERSION.SDK_INT >= 11) 

und benutzen

 @SuppressLint("NewApi") 

um die Warnungen zu unterdrücken.

Verwenden Sie anstelle einer PreferenceActivity zum direkten Laden von AppCompatActivity eine AppCompatActivity oder eine entsprechende AppCompatActivity , die ein PreferenceFragmentCompat lädt, das Ihre PreferenceFragmentCompat lädt. Es ist Teil der Support-Bibliothek (jetzt Android Jetpack) und bietet Kompatibilität zu API 14.

build.gradle in Ihrer build.gradle eine Abhängigkeit für die Preference-Support-Bibliothek hinzu:

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

Hinweis: Wir gehen davon aus, dass Ihre Präferenzen XML bereits erstellt wurde.

Erstellen Sie für Ihre Aktivität eine neue Aktivitätsklasse. Wenn Sie Materialthemen verwenden, sollten Sie eine AppCompatActivity , aber Sie können dabei flexibel sein:

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

Nun zum wichtigsten Teil: Erstellen Sie ein Fragment, das Ihre Präferenzen aus XML lädt:

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

Weitere Informationen finden Sie in den Android Developers- Dokumenten für PreferenceFragmentCompat .