PreferenceFragment kasıtlı olarak uyumluluk paketinden çıkarıldı mı?


153

Hem 3.0 hem de 3.0 öncesi cihazlara uygulanabilen tercihleri ​​yazmak istiyorum. Kullanımdan PreferenceActivitykaldırılan yöntemler içeren keşifler (bunlara eşlik eden örnek kodda kullanılmasına rağmen) baktım PreferenceFragementve sıkıntılarımı çözmek için uyumluluk paketine baktım .

Bununla birlikte, PreferenceFragmentuyumluluk paketinde görünmüyor. Biri bana bunun kasıtlı olup olmadığını söyleyebilir mi? Öyleyse, bir dizi cihazı kolayca hedefleyebilir miyim (yani <3.0 ve> = 3.0) yoksa kasnaklardan atlamak zorunda kalacak mıyım? Kasıtlı olarak hariç tutulmadıysa, uyumluluk paketinin yeni bir sürümünü bekleyebilir miyiz? Yoksa kullanımı güvenli başka bir geçici çözüm var mı?

Şerefe

James


1
Bu benim problemi çözme yaklaşımım: stackoverflow.com/questions/14076073/…
ecv

Birisi PreferenceFragmentunutacağınız üçüncü bir parti yaptı bile orada. Cevabımı gör .
theblang

Chris Banes bunu blogunda yaptığı bir yorumda ele alıyor . Nedeni olduğunu söyledi,"Because most of Preferences' implementation is hidden, therefore impossible to backport without lots of hackery."
theblang

Güncellenmiş cevabımı görün . PreferenceFragmentCompatkısa süre önce destek kitaplığına eklendi.
theblang

Yanıtlar:


90

PreferenceActivity'nin kullanımdan kaldırılmış yöntemler içerdiğini keşfetme (bunlar eşlik eden örnek kodda kullanılmasına rağmen)

Kullanımdan kaldırılan yöntemler Android 3.0'dan itibaren kullanımdan kaldırılmıştır. Android'in tüm sürümlerinde mükemmel durumdalar, ancak yön PreferenceFragmentAndroid 3.0 ve daha yeni sürümlerde kullanmaktır .

Biri bana bunun kasıtlı olup olmadığını söyleyebilir mi?

Tahminimce bu mühendislik zamanı meselesi, ama bu sadece bir tahmin.

Öyleyse, bir dizi cihazı kolayca hedefleyebilir miyim (yani <3.0 ve> = 3.0) yoksa kasnaklardan atlamak zorunda kalacak mıyım?

"Kolay" yapıldığını düşünüyorum. PreferenceActivityBiri tercih başlıklarını PreferenceFragments, diğeri orijinal yaklaşımı kullanarak iki ayrı uygulamaya sahip olun . İhtiyacınız olan noktada doğru olanı seçin (örneğin, kullanıcı seçenekler menüsü öğesini tıkladığında). İşte bunu gösteren örnek bir proje . Veya bu örnek projedePreferenceActivity olduğu gibi her iki durumu da ele alan bir single'a sahip olun .

Kasıtlı olarak hariç tutulmadıysa, uyumluluk paketinin yeni bir sürümünü bekleyebilir miyiz?

Geri kalanımızın ne zaman öğrendiğini, yani geminin ne zaman ve ne zaman gönderileceğini öğreneceksiniz.

Yoksa kullanımı güvenli başka bir geçici çözüm var mı?

Yukarıyı görmek.


Şerefe Mark. Birkaç yerde (android google grubu ve blogunuz) bu konuda yorum yaptığınızı gördüm, ancak kesin bir cevap istedim (şartlar verilebildiği sürece).
James

@James: Evet, ovmak tercih XML tanımında olacak, parçalar gibi iyi çalışacak ve aynı zamanda bir araya getirilecek bir şey elde edecek, çünkü <include>tercih XML ile çalıştığından emin değilim . BTW, abone iseniz, bu projeye referans veren kitap güncellemesi birkaç dakika önce duyuruldu.
CommonsWare

7
Üzgünüm ama burada hangi noktayı ifade etmeye çalıştığınızdan emin değilim. Hiçbir şeye cevap vermiyorsunuz, sadece yorum / tahmin / sorunla ilgisi olmayan alakasız dış bağlantılara atıfta bulunuyorsunuz. Soru, ihmalin kasıtlı olup olmadığıdır , PreferenceFragment'ın uyumluluk sürümü olmadan PreferenceActivity'yi tanımladığınız şekilde genişletmenin bir yolu yoktur çünkü PreferenceFragment yoksa, getSupportFragmentManager () veya diğer yöntemlerden hiçbiri parçaları ilk etapta kullanmanız gerekir.
Justin Buser

8
@JustinBuser: "Soru, ihmalin kasıtlı olup olmadığıdır" - Google için bu işe cevap verebilecek tek kişi. Öğrenmeye çalışmak için Google'da bir iş bulabilirsin. "PreferenceActivity'yi tanımladığınız şekilde genişletmenin bir yolu yok" - bağlandığım kodu indirebilirsiniz.
CommonsWare

9
@JustinBuser Kayıt için Mark sorumu yanıtladı. Cevabını kabul etmek benden açık.
James

21

@CommonsWare'den gelen yanıtın en ince anlamı şudur: Uygulamanız uyumluluk API'sı veya yerleşik parça API'sı arasında seçim yapmalıdır (SDK 11 veya sonrasında). Aslında "kolay" öneri bunu yaptı. Başka bir deyişle, PreferenceFragment kullanmak istiyorsanız, uygulamanızın yerleşik parça API'sını kullanması ve PreferenceActivity ile ilgili kullanımdan kaldırılmış yöntemlerle ilgilenmesi gerekir. Tersine, uygulamanızın uyumluluğunu kullanması önemliyse. Hiç bir PreferenceFragment sınıfına sahip olmadığınız API ile karşılaşacaksınız. Bu nedenle, cihazları hedeflemek bir sorun değildir, ancak bir veya diğer API'yi seçmeniz ve böylece tasarımınızı öngörülemeyen geçici çözümlere göndermeniz gerektiğinde çember atlama gerçekleşir. Uyumluluğa ihtiyacım var. API bu yüzden kendi PreferenceFragment sınıfımı oluşturacağım ve bunun nasıl çalıştığını göreceğim. En kötü senaryoda ben '

DÜZENLEME: http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.0.1_r1/android/preference/PreferenceFragment.java adresindeki koda baktıktan sonra ? av = h - kendi PreferenceFragment'ımı oluşturmak olmaz. PreferenceManager'da paket korumalı 'liberal' kullanımı yerine 'korumalı' ana engelleyici gibi görünüyor. Bunu yapmak için herhangi bir güvenlik veya gerçekten iyi bir motivasyon var gibi görünmüyor ve birim test için harika değil ama oh ... daha az yazım sanırım ...

EDIT v2: Aslında oldu ve işe yaradı. Kodun Uyumluluk API JAR ile çalışmasını sağlamak kesinlikle bir baş ağrısıydı. Com.android.preference paketinin yaklaşık% 70'ini SDK'dan uygulamama kopyalamak ve daha sonra Android'de vasat kalitede Java kodu ile güreşmek zorunda kaldım. SDK'nın v14'ünü kullandım. Bazı Google mühendislerinin bu konu hakkında söylediklerinin aksine, bir Goog mühendisinin yaptığım şeyi yapması çok daha kolay olurdu.

BTW - "hedefleme cihazları sorun değil" mi dedim? Tamamen ... com.android.preference kullanırsanız, büyük bir yeniden düzenleme yapmadan Uyumluluk API'sını değiştiremezsiniz. Eğlenceli günlük!


Daha doğrudan olalım. İlgilendiğiniz tek şey Honeycomb ve üstünü hedefliyorsa (ki bu pazar payı ne kadar?) @Commonsware'in cevabına oy verin! Bugün piyasadaki Android cihazların çoğunu önemsiyorsanız, yanıtımı okumalısınız.
Tenacious

4
bunu nasıl yaptığınızı paylaşmak ister misiniz? Ben tamamen aynı sorunla karşılaşıyorum, sadece benim PreferenceActivity Yükleyiciler kullanmak zorunda ve bu nedenle uyumluluk kitaplığı kullanmanız gerekir .
Karakuri

3
@Tasarımcı Soruşturmanızı seviyorum - aferin. Ancak, birisinin ilk kayıt üzerinde doğrudan kayıt ayarlaması gerektiğini hissediyorum - Commonsware kod HC öncesi ve sonrası cihazlarda çalışacaktır - böyle yorum yapmadan önce ilk deneyin. Farkına varmanız gereken şey, önceki cihazları desteklemek için çalışma zamanında kullanılan geç bağlamadır. Çalışma zamanında sürüm kontrolü, her iki işletim sistemi ailesini de desteklemekle ilgilenir - bu yaygın bir Android kalıbıdır (sevdiğim değil - ancak Android geliştiricilerinin öğrenmesi ve aşina olması için önemli olan) ... Yani gelecekteki okuyucular için - don her iki yaklaşımı da reddetmez.
Richard Le Mesurier

@RichardLeMesurier ama DrawerLayout içinde tercihlere ihtiyacınız varsa Commonsware'in yöntemi uygun değil
neworld

16

CommonsWare'in yanı sıra Tenacious 'gözlemlerine dayanarak, mevcut tüm Android API sürümlerini minimum yaygarayla ve kod veya kaynak çoğaltması olmadan hedefleyebilen tek bir alt sınıf çözümü bulduk. Lütfen buradaki ilgili soruya verdiğim cevaba bakın: PreferenceActivity Android 4.0 ve öncesi

veya blogumda: http://www.blackmoonit.com/2012/07/all_api_prefsactivity/

4.0.3 ve 4.0.4 çalıştıran iki tabletin yanı sıra 4.0.4 ve 2.3.3 çalıştıran bir telefonda ve 1.6 çalıştıran bir emülatörde test edilmiştir.



10

Ağustos 2015'te Google yeni Tercihler Destek Kütüphanesi v7'yi yayınladı .

Artık PreferenceFragmentCompat'ı herhangi bir ActivityveyaAppCompatActivity

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

preferenceThemeTemanızı ayarlamanız gerekiyor:

<style name="AppTheme" parent="@style/Theme.AppCompat.Light">
  ...
  <item name="preferenceTheme">@style/PreferenceThemeOverlay</item>
</style>

Bu şekilde preferenceTheme, Etkinliğinizin diğer bölümlerini etkilemeden her tercih türü için kullanılan mizanpajları biçimlendirmek için özelleştirebilirsiniz .


1
Ben bir işlevi özledim düşünüyorum: onCreatePreferences
android geliştirici

Bu benim günümü kurtardı! Acaba bu neden Android Studio'nun Proje Yapısında görünmüyor ... ?? BTW kodunuzda bir yazım hatası var. "PreferenceFragmentCompat genişletir" olmalıdır
Grzegorz

7

Tenacious'un cevabı doğrudur, ama işte bazı ayrıntılar.

"Normal bir düzen oluşturmanın ve görünüm bileşenlerini elle paylaşılanpref'lere bağlayamamanızın nedeni android.preferences API'sında bazı şaşırtıcı eksiklikler olmasıdır. PreferenceActivity ve PreferenceFragment öğelerinin her ikisi de, sizin tercih ettiğiniz bir kullanıcı arayüzünü uygulayamayacağınız, herkese açık olmayan kritik PreferenceManager yöntemlerine erişebilir.

Özellikle, bir XML dosyasından bir Tercih hiyerarşisi oluşturmak için bir PreferenceManager kullanmanız gerekir, ancak PreferenceManager'ın tüm kurucuları paket özel veya gizlidir. Tercihinizi onClick dinleyicilerini etkinliğinize ekleme yöntemi de pakete özeldir.

Android API'larındaki herkese açık olmayan yöntemler aslında SDK'dan çıkarıldığı için, uygulamanızı android.preferences paketine gizlice koyarak bu sorunu çözemezsiniz. Yansıma ve dinamik proxy'leri içeren biraz yaratıcılıkla, yine de bunlara ulaşabilirsiniz. Tenacious'un söylediği gibi tek alternatif, en az 15 sınıf, 5 düzen ve benzer sayıda style.xml ve attrs.xml öğeleri dahil olmak üzere tüm android.preference paketini çatallamaktır.

Dolayısıyla, orijinal soruyu cevaplamak için Google'ın uyumluluk paketine PreferenceFragment'ı dahil etmemesinin nedeni, Tenacious ve benimle tam olarak aynı zorlukta olmalarıdır. Google bile zaman içinde geri gidemez ve bu yöntemleri eski platformlarda herkese açık hale getiremez (umarım gelecek sürümlerde bunu yaparlar).


2

Uygulama hedefim API +14, ancak bazı süslü gezinme için destek kitaplığı kullanması nedeniyle, kullanamadım android.app.Fragmentve kullanmak zorunda kaldım android.support.v4.app.Fragment, ancak PreferenceFragmentarka planda kodda büyük değişiklikler olmadan da yer almam gerekiyordu .

Bu yüzden her iki destek kütüphanesine de sahip olduğum kolay düzeltme ve 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();
    }
}

2

Tercihleri ​​uygulamanın tasarımına entegre etmem ve 2.3 android için destek tutmam gerekiyordu. Bu yüzden hala Tercihler Parçası'na ihtiyacım vardı.

Biraz arama yaptıktan sonra android-support-v4-preferencefragment lib buldum . Bu lib, Tenacious'un dediği gibi orijinal PreferencesFragment'ı kopyalamak ve yeniden düzenlemek için çok zaman kazandırıyor. İyi çalışır ve kullanıcılar tercihlerin tadını çıkarır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.