Bir PreferenceActivity'de "addPreferencesFromResource" yerine ne kullanılır?


360

Sadece yöntemin Android belgelerinde ( Referans Girişi ) kullanımdan kaldırılmışaddPreferencesFromResource(int preferencesResId) olarak işaretlendiğini fark ettim .

Ne yazık ki, yöntemin açıklamasında alternatif bir yöntem sağlanmamıştır.

Bir preferenceScreen.xml dosyasını eşleşen PreferenceActivity'ye bağlamak için bunun yerine hangi yöntem kullanılmalıdır?


2
WannaGetHigh tarafından stackoverflow.com/questions/23523806/…
Sabin

Oradaki çözüm hala kullanıyor addPreferencesFromResource(int preferencesResId). Bir şey mi kaçırıyorum?
Jammo

@ Jammo Evet, ancak yeni parça -> parçasını yansıtmak için Faaliyet'ten Parçaya taşındı.
WannaGetHigh

Yanıtlar:


332

Tercih edilen yaklaşım (API seviye 11'den itibaren) PreferenceFragment'ı başlatmak olduğundan yöntemin açıklamasında alternatif bir yöntem sağlanmamıştır tercihlerinizi bir kaynak dosyasından yüklemek için nesnelerini . Örnek koda bakın: PreferenceActivity


Cevabınız için çok teşekkür ederim. Ben sadece PreferenceActivity'nin yöntemin sürümünü kullanmamı sağlayan "Video2Brain-Android Development" dan kullanımdan kaldırılmış talimatları izliyordum. Btw: Cevabınızı sadece yapabilseydim faydalı olarak değerlendirmek isterim.
mweisz

33
Şimdi sadece PreferenceFragment uyumluluk paketine dahil edilmişse, onu kullanmak mantıklı olacaktır stackoverflow.com/questions/5501431/…
christoff

1
Eylem Çubuğu Sherlock'u kullandığım için, bu sorunu çözmek için aşağıdaki blogu izledim
Birisi

2
Yine de, uygulamanın 11'den daha eski (api düzeyi) ile geriye dönük olarak uyumlu olmasını istiyorsanız addPreferencesFromResource (int PreferencesID) öğesini çağırmanız gerekir. Ama sanırım o eski cihazları da dereceli olarak düşünebilirsiniz.
Einar Sundgren

5
@EinarSundgren Ben Nexus Tek sahibiyim ve kullanılabilir maksimum sürüm 2.2: beni durdurmayacaksın! ASLA itiraz edilmeyeceğim! Grayskull'ın Gücü ile ... Gücüm Var!
TechNyquist

186

Yukarıdaki doğru cevaba daha fazla bilgi eklemek için, Android-er'den bir örnek okuduktan sonra , tercih etkinliğinizi bir tercih parçasına kolayca dönüştürebileceğinizi buldum. Aşağıdaki etkinliğiniz varsa:

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

Yapmanız gereken tek değişiklik bir iç parça sınıfı oluşturmak, parçayı parçaya taşımak addPreferencesFromResources()ve parçayı şu şekilde etkinlikten çağırmaktır:

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

Parçalardan daha karmaşık tercihler yapmak için başka incelikler olabilir; eğer öyleyse, umarım birisi onları buraya not eder.


6
Güzel, bunun için teşekkürler. Java ve bu tür düşünce şimdiye kadar benim güzel küçük .net dünyamdan kaldırıldı :)
Tom

44
addPreferencesFromResources()PreferenceFragment ticaretinde neden değer kaybederler? Başlangıç ​​açısından gereksiz görünüyor.
Howdy_McGee

4
Çağrı API seviye 11 gerektirir
mehmet

1
Peki API Seviye 9'daysa ne olacak? @mehmet
gumuruh

2
Müthiş cevap! android.R.id.content değiştirmeden bunu başarmanın bir yolu var mı? bir nedenden dolayı bana
yetersiz

37

@Gretret Wilson Çok teşekkür ederim! Android kodlama için bir noob olarak, saatlerce tercihler uyumsuzluk sorunuyla sıkıştım ve eski API'lar tarafından desteklenmeyen yeni yöntemler için bazı yöntemlerin / yaklaşımların kullanılmasını onaylamadım. uygulamanızın çok çeşitli cihazlarda çalışmasını sağlamak için her türlü geçici çözüme başvurmanız gerekir. Gerçekten sinir bozucu!

Sınıfınız harika, çünkü eskisi gibi yeni API'larda çalışmaya devam etmenizi sağlıyor, ancak geriye dönük uyumlu değil. Çok çeşitli cihazlara ulaşmaya çalıştığımdan, API 11 öncesi cihazlarda ve yeni API'larda çalışmasını sağlamak için biraz uğraştım:

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

İki emülatörde (2.2 ve 4.2) başarıyla test edilmiştir.

Kodum neden bu kadar berbat görünüyor:

Ben android kodlama için bir noob ve en büyük java hayranı değilim.

Kullanımdan kaldırılmış uyarıyı önlemek ve Eclipse'i derlememe izin vermeye zorlamak için ek açıklamalara başvurmak zorunda kaldım, ancak bunlar sadece sınıfları veya yöntemleri etkiliyor gibi görünüyor, bu yüzden bundan yararlanmak için kodu iki yeni yönteme taşımak zorunda kaldım.

Ben yeni bir PreferenceActivity için sınıf kopyalamak ve yapıştırmak her zaman iki kez benim xml kaynak kimliğini yazmak zorunda kalmak istemiyorum, bu yüzden bu değeri depolamak için yeni bir değişken yarattı.

Umarım bu başka birisi için faydalı olacaktır.

Not: Düşünülen görüşlerim için özür dilerim, ancak yeni geldiğinizde ve böyle handikaplar bulduğunuzda, yardım edemezsiniz, ancak sinirli olmak için!


Oh şey ... Sadece kopyalayıp yapıştırdığımda dış sınıf adını iki kez değiştirmem gerektiğini fark ettim. Aslında bunu önlemenin bir yolu var, iç sınıfı tercih ediyor. Tercihler, PreferenceFragment türetilmiş sınıflar için önerilmediği için parametre olarak kabul eden bir iç sınıf yapıcısı oluşturamazsınız. Ayrıca, super.onCreate çağrıldıktan sonra addPreferencesFromResource çağrılmasından ve PreferenceFragment türetilmiş sınıftan hemen sonra addPreferencesFromResource'un çağrılması gerektiğinden prefs almak ve addPreferencesFromResource'u hemen çağırmak için iç sınıfta bir yöntem oluşturamayabilirsiniz ...
ecv

... somutlaştırıldı. Bu nedenle, iç sınıfta yeni bir değişken oluşturmanız, iç sınıfta bunun için bir genel küme yöntemi oluşturmanız, addPreferencesFromResource'u super.onCreate çağrısından sonra olduğu yerde bırakın, onCreate içinde, iç sınıfı somutlaştırın, tercihleri ​​ayarlayın ve daha önce olduğu gibi getFragmentManager () ... çağrısında kullanın.
ecv

2
Kodunuz bir cankurtaran oldu !! Hem eski hem de yeni telefonu hedeflemeye çalışıyordum ve 3 gün boşa harcadım ... Ve Cevap çok basit. Teşekkürler
Devdatta Tengshe

22

Yaklaşımım Garret Wilson'a çok yakın (teşekkürler, sana oy verdim;)

Ayrıca Android <3 ile aşağı doğru uyumluluk sağlar.

Sadece benim çözümümün çözümüne daha yakın olduğunu fark ettim. Kevin Remo'nun . (Sadece "beklenti" antipattern dayanmaz gibi sadece bir çiş biraz temiz ).

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

"Gerçek" (ancak daha karmaşık) bir örnek için bkz. NusicPreferencesActivity ve NusicPreferencesFragment .


@SuppressLint("NewApi")- kaçının - daha kesin olun. Düşük apis için çalıştırdınız mı? Bu atacağımVerifyError
Mr_and_Mrs_D

Yukarıda API seviye 10 çalıştıran emülatörde test yaptım, APK SDK Sürüm 19 kullanılarak oluşturuldu. Bina için hangi SDK sürümünü kullandınız? Hangi cihaz API'sını çalıştırdınız? Emülatörde veya fiziksel bir cihazda çalıştırdınız mı? Hata tam olarak ne zaman oluştu? SDK <= 16 ile URL oluşturma yapıyorsanız, bu yanıta bakın .
schnatterer

Konuyu kaçırıyorsunuz - ve bana bildirilmesini istiyorsanız @Mr_and_Mrs_D'yi ekleyin. VE için burayı okuyun: stackoverflow.com/questions/20271593/… . @SuppressLint("NewApi")Sadece kötü tarzıdır
Mr_and_Mrs_D

@M Peki, @SuppressLint("NewApi")bu özel durumda nasıl önleneceğine dair bir öneriye ne dersiniz ?
schnatterer

@TargetApi(Build.VERSION_CODES.HONEYCOMB)- herhangi bir api için tüm uyarılar :)
Mr_and_Mrs_D

6

İstisnalar yerine şunları kullanın:

if (Build.VERSION.SDK_INT >= 11)

ve kullan

@SuppressLint("NewApi")

uyarıları bastırmak için.


1
çünkü
çökmekten

1
eğer
çökerse

0

PreferenceActivityTercihleri ​​doğrudan yüklemek için a kullanmak yerine, tercihlerinizi AppCompatActivityyükleyen a veya eşdeğerini kullanın PreferenceFragmentCompat. Destek kitaplığının bir parçası (şimdi Android Jetpack) ve API 14 ile tekrar uyumluluk sağlıyor.

Gözlerinde farklı build.gradle, tercih desteği kütüphanesi için bir bağımlılık ekleyin:

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

Not: Tercihlerinizin XML'inin önceden oluşturulduğunu varsayacağız.

Etkinliğiniz için yeni bir etkinlik sınıfı oluşturun. Materyal temalar kullanıyorsanız, bir'yi genişletmelisiniz AppCompatActivity, ancak bununla esnek olabilirsiniz:

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

Şimdi önemli kısım için: XML'den tercihlerinizi yükleyen bir parça oluşturun:

public class MyPreferencesFragment extends PreferenceFragmentCompat {

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

Daha fazla bilgi için için Android Geliştiricileri dokümanlarını okuyun PreferenceFragmentCompat.

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.