Wurde PreferenceFragment absichtlich aus dem Kompatibilitätspaket ausgeschlossen?
Lesezeit: 10 Minuten
James
Ich möchte Einstellungen schreiben, die sowohl auf 3.0- als auch auf Geräte vor 3.0 angewendet werden können. Das entdecken PreferenceActivity veraltete Methoden enthält (obwohl diese im beigefügten Beispielcode verwendet werden), habe ich mir angesehen PreferenceFragement und das Kompatibilitätspaket, um meine Probleme zu lösen.
Es scheint aber so PreferenceFragment ist nicht im Kompatibilitätspaket. Kann mir jemand sagen ob das Absicht war? Wenn ja, kann ich problemlos auf eine Reihe von Geräten abzielen (z. B. < 3.0 und >= 3.0) oder muss ich um die Wette springen? Wenn es nicht absichtlich ausgeschlossen wurde, können wir eine neue Version des Kompatibilitätspakets erwarten? Oder gibt es eine andere Problemumgehung, die sicher zu verwenden ist?
Beifall
James
Dies ist mein Ansatz zur Lösung des Problems: stackoverflow.com/questions/14076073/…
– ev
28. Dezember 2012 um 23:50 Uhr
Jemand hat einen Dritten gemacht PreferenceFragment dass Sie vergessen werden, ist sogar da. Siehe meine Antwort.
– das Blang
23. September 14 um 21:25 Uhr
Chris Banes spricht dies an in einem Kommentar auf seinem Blog. Er sagte, der Grund sei, "Because most of Preferences' implementation is hidden, therefore impossible to backport without lots of hackery."
– das Blang
23. Oktober 14 um 20:23 Uhr
Siehe meine aktualisierte Antwort. PreferenceFragmentCompat wurde kürzlich zur Support-Bibliothek hinzugefügt.
– das Blang
31. August 15 um 13:39 Uhr
CommonsWare
Entdecken, dass PreferenceActivity veraltete Methoden enthält (obwohl diese im begleitenden Beispielcode verwendet werden)
Die veralteten Methoden sind ab Android 3.0 veraltet. Sie sind auf allen Versionen von Android vollkommen in Ordnung, aber die Richtung ist zu verwenden PreferenceFragment auf Android 3.0 und höher.
Kann mir jemand sagen ob das Absicht war?
Meine Vermutung ist, dass es eine Frage der Entwicklungszeit ist, aber das ist nur eine Vermutung.
Wenn ja, kann ich problemlos auf eine Reihe von Geräten abzielen (z. B. < 3.0 und >= 3.0) oder muss ich um die Wette springen?
Ich halte es für “einfach”. Habe zwei getrennt PreferenceActivity Implementierungen, eine mit Präferenzheadern und PreferenceFragments, der andere mit dem ursprünglichen Ansatz. Wählen Sie an der erforderlichen Stelle die richtige aus (z. B. wenn der Benutzer auf das Optionsmenüelement klickt). Hier ist ein Beispielprojekt dies demonstrieren. Oder haben Sie eine Single PreferenceActivity das beide Fälle behandelt, wie in dieses Beispielprojekt.
Wenn es nicht absichtlich ausgeschlossen wurde, können wir eine neue Version des Kompatibilitätspakets erwarten?
Sie werden es herausfinden, wenn der Rest von uns es herausfindet, das heißt, ob und wann es versendet wird.
Oder gibt es eine andere Problemumgehung, die sicher zu verwenden ist?
Siehe oben.
Gruß Mark. Ich habe gesehen, dass Sie an einigen Stellen (Android-Google-Gruppe und Ihr Blog) Kommentare dazu abgegeben haben, aber eine endgültige Antwort wollten (soweit dies unter den gegebenen Umständen möglich ist).
– James
31. März 11 um 14:46 Uhr
@James: Ja, der Haken wird in der bevorzugten XML-Definition liegen, etwas zu bekommen, das gut als Fragmente funktioniert und auch miteinander verkettet wird, da ich mir nicht sicher bin <include> arbeitet mit Präferenz-XML. Übrigens, wenn Sie Abonnent sind, wurde das Buch-Update, das sich auf dieses Projekt bezieht, vor Minuten angekündigt.
– CommonsWare
31. März 11 um 15:22 Uhr
Es tut mir leid, aber ich bin mir nicht sicher, was Sie hier sagen wollen. Sie antworten überhaupt nicht, kommentieren/raten/verweisen lediglich auf irrelevante externe Links, die nichts mit dem Problem zu tun haben. Die Frage ist, ob die Auslassung beabsichtigt war oder nicht, ohne In der Kompatibilitätsversion von PreferenceFragment gibt es keine Möglichkeit, PreferenceActivity auf die von Ihnen beschriebene Weise zu erweitern, denn wenn PreferenceFragment nicht vorhanden ist, gibt es weder getSupportFragmentManager() noch eine der anderen Methoden, die erforderlich sind, um Fragmente überhaupt zu verwenden.
– Justin Buser
16. August 2012 um 17:02 Uhr
@JustinBuser: “Die Frage ist, ob die Auslassung beabsichtigt war oder nicht” – die einzigen Personen, die diese Arbeit für Google beantworten können. Sie können gerne einen Job bei Google annehmen, um es herauszufinden. “Es gibt keine Möglichkeit, PreferenceActivity so zu erweitern, wie Sie es beschrieben haben” – Sie können gerne den von mir verlinkten Code herunterladen.
– CommonsWare
16. August 2012 um 17:18 Uhr
@JustinBuser Fürs Protokoll, Mark hat meine Frage beantwortet. Das geht daraus hervor, dass ich seine Antwort akzeptiere.
– James
26. September 2012 um 08:05 Uhr
Zäh
Die subtile Implikation der Antwort von @CommonsWare ist, dass Ihre App zwischen der Kompatibilitäts-API oder der integrierten Fragment-API (seit SDK 11 oder so) wählen muss. Genau das hat die „einfach“-Empfehlung getan. Mit anderen Worten, wenn Sie PreferenceFragment verwenden möchten, muss Ihre App die integrierte Fragment-API verwenden und mit den veralteten Methoden auf PreferenceActivity umgehen. Umgekehrt, wenn es wichtig ist, dass Ihre App die Datei compat. API werden Sie damit konfrontiert, dass Sie überhaupt keine PreferenceFragment-Klasse haben. Das Targeting von Geräten ist also kein Problem, aber das Reifenspringen passiert, wenn Sie sich für die eine oder andere API entscheiden müssen und damit Ihr Design unvorhergesehenen Workarounds unterwerfen. Ich brauche das Kompat. API, also werde ich meine eigene PreferenceFragment-Klasse erstellen und sehen, wie das funktioniert. Im schlimmsten Fall erstelle ich einfach ein normales (Fragment-)Layout und binde die Ansichtskomponenten manuell an die Sharedprefs … ugh.
EDIT: Nach dem Ausprobieren und Betrachten des Codes bei http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.0.1_r1/android/preference/PreferenceFragment.java?av=h — das Erstellen meines eigenen PreferenceFragments wird nicht passieren. Es scheint, dass die großzügige Verwendung von „package-private“ in PreferenceManager anstelle von „protected“ der Hauptblocker ist. Es sieht wirklich nicht so aus, als gäbe es eine Sicherheit oder eine wirklich gute Motivation, dies getan zu haben, und es ist nicht großartig für Komponententests, aber na ja … weniger Tippen, denke ich …
EDIT v2: Tatsächlich ist es passiert und es hat funktioniert. Es war definitiv ein Problem, den Code mit dem Kompatibilitäts-API-JAR zum Laufen zu bringen. Ich musste etwa 70 % des com.android.preference-Pakets aus dem SDK in meine App kopieren und mich dann mit typisch mittelmäßigem Java-Code in Android herumschlagen. Ich habe v14 des SDK verwendet. Es wäre für einen Goog-Ingenieur viel einfacher gewesen, das zu tun, was ich getan habe, im Gegensatz zu dem, was einige führende Android-Ingenieure zu diesem Thema sagen.
Übrigens – habe ich gesagt, dass das Targeting von Geräten kein Problem ist? Es ist absolut … wenn Sie com.android.preference verwenden, können Sie ohne größere Umgestaltung nicht mit der Kompatibilitäts-API austauschen. Lustiges Protokoll!
Lassen Sie mich direkter sein. Wenn Sie nur auf Honeycomb und höher abzielen (was hat wie viel Marktanteil?), dann stimmen Sie für die Antwort von @Commonsware! Wenn Sie sich für die Mehrheit der heute auf dem Markt erhältlichen Android-Geräte interessieren, sollten Sie meine Antwort lesen.
– Hartnäckig
3. März 12 um 5:12 Uhr
wärst du bereit zu teilen, wie du das gemacht hast? Ich habe genau das gleiche Problem, nur meine PreferenceActivity muss Loaders verwenden und daher ich muss Verwenden Sie die Kompatibilitätsbibliothek.
– Karakuri
30. Mai 2012 um 22:11 Uhr
@Tenacious Ich mag deine Untersuchung – gut gemacht. Ich bin jedoch der Meinung, dass jemand Ihren ersten Kommentar dort klarstellen sollte – der Code von Commonsware funktioniert auf Pre- und Post-HC-Geräten – versuchen Sie es zuerst, bevor Sie solche Kommentare abgeben. Was Sie beachten müssen, ist die späte Bindung, die zur Laufzeit verwendet wird, um frühere Geräte zu unterstützen. Die Versionsprüfung zur Laufzeit sorgt dafür, dass beide Betriebssystemfamilien unterstützt werden – dies ist ein gängiges Android-Muster (das ich nicht mag – aber eines, das Android-Entwickler lernen und sich damit vertraut machen sollten) … Also an zukünftige Leser – don verwerfen Sie keinen der beiden Ansätze.
– Richard Le Mesurier
15. Oktober 12 um 6:30 Uhr
@RichardLeMesurier, aber die Methode von Commonsware ist nicht richtig, wenn Sie Einstellungen innerhalb von DrawerLayout benötigen
– Neuwelt
20. Februar 14 um 9:10 Uhr
Onkel Code Affe
Aufbauend auf der Antwort von CommonsWare sowie den Beobachtungen von Tenacious habe ich eine Lösung mit einer einzelnen Nachkommenklasse entwickelt, die in der Lage ist, alle aktuellen Android-API-Versionen mit minimalem Aufwand und ohne Code- oder Ressourcenduplizierung anzusprechen. Bitte lesen Sie meine Antwort auf die verwandte Frage hier: PreferenceActivity Android 4.0 und früher
Jetzt können Sie die verwenden PreferenceFragmentCompat mit jedem Activity oder AppCompatActivity
public static class PrefsFragment extends PreferenceFragmentCompat {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.preferences);
}
}
Du musst einstellen preferenceTheme in deinem thema:
Auf diese Weise können Sie die anpassen preferenceTheme um die für jeden Einstellungstyp verwendeten Layouts zu gestalten, ohne andere Teile Ihrer Aktivität zu beeinflussen.
Ich glaube, Sie vermissen eine Funktion: onCreatePreferences
– Android-Entwickler
26. September 15 um 7:58 Uhr
Das hat meinen Tag gerettet! Ich frage mich, warum das nicht in der Projektstruktur von Android Studio sichtbar ist…?? Übrigens hast du einen Tippfehler in deinem Code. Sollte “erweitert PreferenceFragmentCompat” sein
– Grzegorz D.
19. März 16 um 21:34 Uhr
Die Antwort von Tenacious ist richtig, aber hier sind einige weitere Details.
Der Grund, warum Sie kein “normales Layout erstellen und die Ansichtskomponenten manuell an die Sharedprefs binden können”, liegt darin, dass es einige überraschende Auslassungen in der android.preferences-API gibt. PreferenceActivity und PreferenceFragment haben beide Zugriff auf kritische, nicht öffentliche PreferenceManager-Methoden, ohne die Sie keine eigene Benutzeroberfläche für Einstellungen implementieren können.
Um insbesondere eine Preference-Hierarchie aus einer XML-Datei zu erstellen, müssen Sie einen PreferenceManager verwenden, aber alle Konstruktoren von PreferenceManager sind entweder paketprivat oder verborgen. Die Methode zum Anhängen der Preference onClick-Listener an Ihre Aktivität ist ebenfalls paketprivat.
Und Sie können dies nicht umgehen, indem Sie Ihre Implementierung heimlich in das android.preferences-Paket einfügen, da nicht öffentliche Methoden in Android-APIs tatsächlich aus dem SDK weggelassen werden. Mit ein wenig Kreativität, die Reflexion und dynamische Proxys beinhaltet, können Sie sie immer noch erreichen. Die einzige Alternative, wie Tenacious sagt, besteht darin, das gesamte android.preference-Paket zu forken, einschließlich mindestens 15 Klassen, 5 Layouts und einer ähnlichen Anzahl von style.xml- und attrs.xml-Elementen.
Um die ursprüngliche Frage zu beantworten, der Grund, warum Google PreferenceFragment nicht in das Kompatibilitätspaket aufgenommen hat, ist, dass sie genau die gleichen Schwierigkeiten gehabt hätten wie Tenacious und ich. Selbst Google kann nicht in der Zeit zurückgehen und diese Methoden auf den alten Plattformen veröffentlichen (obwohl ich hoffe, dass sie dies in zukünftigen Versionen tun).
Ich glaube, Sie vermissen eine Funktion: onCreatePreferences
– Android-Entwickler
26. September 15 um 7:58 Uhr
Das hat meinen Tag gerettet! Ich frage mich, warum das nicht in der Projektstruktur von Android Studio sichtbar ist…?? Übrigens hast du einen Tippfehler in deinem Code. Sollte “erweitert PreferenceFragmentCompat” sein
– Grzegorz D.
19. März 16 um 21:34 Uhr
Herr_und_Frau_D
Mein App-Ziel ist API +14, aber aufgrund der Verwendung der Support-Bibliothek für eine ausgefallene Navigation konnte ich die nicht verwenden android.app.Fragment und verwenden musste android.support.v4.app.Fragment, aber ich musste auch haben PreferenceFragment an Ort und Stelle ohne große Änderungen am Code dahinter.
Also meine einfache Lösung, um beide Welten der Support-Bibliothek und zu haben PreferenceFragment:
private android.support.v4.app.Fragment fragment;
private android.app.Fragment nativeFragment = null;
private void selectItem(int position) {
fragment = null;
boolean useNativeFragment = false;
switch (position) {
case 0:
fragment = new SampleSupprtFragment1();
break;
case 1:
fragment = new SampleSupprtFragment2();
break;
case 2:
nativeFragment = new SettingsFragment();
useNativeFragment = true;
break;
}
if (useNativeFragment) {
android.app.FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.content_frame, nativeFragment).commit();
} else {
if (nativeFragment != null) {
getFragmentManager().beginTransaction().remove(nativeFragment)
.commit();
nativeFragment = null;
}
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.content_frame, fragment).commit();
}
}
.
7590900cookie-checkWurde PreferenceFragment absichtlich aus dem Kompatibilitätspaket ausgeschlossen?yes
Dies ist mein Ansatz zur Lösung des Problems: stackoverflow.com/questions/14076073/…
– ev
28. Dezember 2012 um 23:50 Uhr
Jemand hat einen Dritten gemacht
PreferenceFragment
dass Sie vergessen werden, ist sogar da. Siehe meine Antwort.– das Blang
23. September 14 um 21:25 Uhr
Chris Banes spricht dies an in einem Kommentar auf seinem Blog. Er sagte, der Grund sei,
"Because most of Preferences' implementation is hidden, therefore impossible to backport without lots of hackery."
– das Blang
23. Oktober 14 um 20:23 Uhr
Siehe meine aktualisierte Antwort.
PreferenceFragmentCompat
wurde kürzlich zur Support-Bibliothek hinzugefügt.– das Blang
31. August 15 um 13:39 Uhr