Предупреждение об устаревшем методе Android относительно PreferenceActivity

Когда я пытаюсь следовать руководствам и руководствам для разработчиков Android по созданию действия настроек с использованием настроек, я получаю такие предупреждения, как:

«Метод addPreferencesFromResource (int) из типа PreferenceActivity устарел»

для обеих этих строк в коде:

getPreferenceManager().setSharedPreferencesName(PREFS_NAME);
addPreferencesFromResource(R.xml.default_values);

Я знаю, что это просто предупреждения, но мне было интересно, вызовут ли они какие-либо проблемы сейчас или в будущем, когда я запускаю разрабатываемое мной приложение.

public class DefaultValues extends PreferenceActivity {

    static final String PREFS_NAME = "defaults";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        getPrefs(this);
        getPreferenceManager().setSharedPreferencesName(PREFS_NAME);
        addPreferencesFromResource(R.xml.default_values);
    }

    static SharedPreferences getPrefs(Context context) {
        PreferenceManager.setDefaultValues(context, PREFS_NAME, MODE_PRIVATE,
                R.xml.default_values, false);
        return context.getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
    }
}

person jillianjiggs    schedule 07.02.2013    source источник
comment
Этот метод устарел, потому что вы должны использовать PreferenceFragment, но вы должны использовать его для версий до HONEYCOMB.   -  person Arnaud    schedule 21.11.2013


Ответы (5)


Поскольку этот метод устарел, рекомендуется не использовать его в своем коде, так как вполне возможно, что он может быть удален в будущих версиях Android. Однако мне еще предстоит встретить устаревший метод, который фактически был удален из Android.

В описании метода не указан альтернативный метод, поскольку предпочтительный подход (начиная с уровня API 11) заключается в создании экземпляра PreferenceFragment объекты, чтобы загрузить свои предпочтения из файла ресурсов. См. Пример кода здесь: PreferenceActivity

person Raghav Sood    schedule 07.02.2013

PreferenceActivity() устарел, но PreferenceFragment() теперь тоже. PreferenceFragmentCompat() теперь путь к успеху:

Добавить зависимость

implementation "androidx.preference:preference:1.1.1"

Или, если вы все еще используете библиотеку поддержки:

implementation "com.android.support:preference-v7:28.0.0"

Расширить PreferenceFragmentCompat

class MyPreferenceFragment : PreferenceFragmentCompat() {
    override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
        addPreferencesFromResource(R.xml.app_preferences)
    }
}

Покажите свой фрагмент

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    supportFragmentManager.beginTransaction().replace(android.R.id.content, MyPreferenceFragment()).commit()
}

Укажите тему предпочтений

В AppTheme добавьте любую из следующих тем предпочтений, в зависимости от того, какая, по вашему мнению, выглядит лучше:

<item name="preferenceTheme">@style/PreferenceThemeOverlay</item>
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
person Cristan    schedule 03.07.2018

Если вы столкнулись с предупреждением об устаревании от такого метода:

addPreferencesFromResource(R.xml.default_values);

Вы должны использовать PreferenceFragment, потому что API 11 и выше требует такого метода.

Вот пример использования PreferenceFragment:

1. Создайте /res/xml/preferences.xml, чтобы определить наши предпочтения.

 <PreferenceScreen
    xmlns:android="http://schemas.android.com/apk/res/android">

<PreferenceCategory
        android:title="PreferenceCategory A">

    <CheckBoxPreference
            android:key="checkbox_preference"
            android:title="title_checkbox_preference"
            android:summary="summary_checkbox_preference" />

</PreferenceCategory>

<PreferenceCategory
        android:title="PreferenceCategory B">

    <EditTextPreference
            android:key="edittext_preference"
            android:title="title_edittext_preference"
            android:summary="summary_edittext_preference"
            android:dialogTitle="dialog_title_edittext_preference" />

</PreferenceCategory>

2.Create PrefsFragment.java extends PreferenceFragment to addPreferencesFromResource.

   package com.example.androidpreferencefragment;

   import android.os.Bundle;
   import android.preference.PreferenceFragment;

   public class PrefsFragment extends PreferenceFragment {

   @Override
   public void onCreate(Bundle savedInstanceState) {
   // TODO Auto-generated method stub
   super.onCreate(savedInstanceState);

   // Load the preferences from an XML resource
    addPreferencesFromResource(R.xml.preferences);
   }

 }

3. Создайте SetPreferenceActivity.java для загрузки PrefsFragment.

package com.example.androidpreferencefragment;

import android.app.Activity;
import android.os.Bundle;

public class SetPreferenceActivity extends Activity {

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  // TODO Auto-generated method stub
  super.onCreate(savedInstanceState);

  getFragmentManager().beginTransaction().replace(android.R.id.content,
                new PrefsFragment()).commit();
 }

}

4. Измените основной макет, /res/layout/activity_main.xml, чтобы отобразить предпочтение.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:padding="@dimen/padding_medium"
    android:text="@string/hello_world"
    tools:context=".MainActivity" />

<CheckBox
    android:id="@+id/prefCheckBox"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="CheckBoxPreference" />

<TextView
    android:id="@+id/prefEditText"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content" />

</LinearLayout>

5. Основное направление деятельности - MainActivity.java.

package com.example.androidpreferencefragment;

import android.os.Bundle;
import android.preference.PreferenceManager;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.CheckBox;
import android.widget.TextView;

public class MainActivity extends Activity {

 CheckBox prefCheckBox;
 TextView prefEditText;

    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    prefCheckBox = (CheckBox)findViewById(R.id.prefCheckBox);
 prefEditText = (TextView)findViewById(R.id.prefEditText);

 loadPref();
}

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.activity_main, menu);
    return true;
}

 @Override
 public boolean onOptionsItemSelected(MenuItem item) {

  /*
   * Because it's onlt ONE option in the menu.
   * In order to make it simple, We always start SetPreferenceActivity
   * without checking.
   */

  Intent intent = new Intent();
    intent.setClass(MainActivity.this, SetPreferenceActivity.class);
    startActivityForResult(intent, 0); 

    return true;
 }

  @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  // TODO Auto-generated method stub
  //super.onActivityResult(requestCode, resultCode, data);

  /*
   * To make it simple, always re-load Preference setting.
   */

  loadPref();
 }

 private void loadPref(){
  SharedPreferences mySharedPreferences =        PreferenceManager.getDefaultSharedPreferences(this);

  boolean my_checkbox_preference = mySharedPreferences.getBoolean("checkbox_preference", false);
  prefCheckBox.setChecked(my_checkbox_preference);

  String my_edittext_preference = mySharedPreferences.getString("edittext_preference", "");
  prefEditText.setText(my_edittext_preference);

 }

}

5. Наконец, измените AndroidManifest.xml, чтобы добавить SetPreferenceActivity.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.androidpreferencefragment"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk
    android:minSdkVersion="11"
    android:targetSdkVersion="15" />

<application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name=".MainActivity"
        android:label="@string/title_activity_main" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity
        android:name=".SetPreferenceActivity"
        android:label="@string/title_activity_main" >
    </activity>
</application>

person Joshua Hoe    schedule 05.06.2014

В предпочтительной реализации теперь используется Fragments. Следующее будет работать:

public class DefaultValues extends Activity {

    static final String PREFS_NAME = "defaults";    
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        // Display the fragment as the main content.
        if (savedInstanceState == null)
            getFragmentManager().beginTransaction().add(android.R.id.content, new PrefFragment()).commit();
    }

    public static class PrefFragment extends PreferenceFragment
    {
        @Override
        public void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);

            getPreferenceManager().setSharedPreferencesName(PREFS_NAME);
            addPreferencesFromResource(R.xml.default_values);
        }
    }
}
person Justin Breitfeller    schedule 07.02.2013
comment
Он будет работать только в том случае, если вы используете API уровня ›10. Для более низких уровней API вам все равно придется использовать PreferenceActivity, поскольку библиотека поддержки не включает PreferenceFragment. - person Phantômaxx; 06.12.2013

Рагхав Суд прав. Но если вам нужен PreferenceFragment плохо (мне нужно на вкладке), вы можете использовать это. Но в будущем он может тормозить, поэтому лучше использовать его только для старых API. Это немного измененный PreferenceFragment, который я сделал с помощью SupportLibrary и отражения.

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.preference.Preference;
import android.preference.PreferenceManager;
import android.preference.PreferenceScreen;
import android.support.v4.app.Fragment;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnKeyListener;
import android.widget.ListView;

@SuppressLint("HandlerLeak")
public abstract class PreferenceFragment
        extends Fragment
{

    private static final String PREFERENCES_TAG = "android:preferences";

    private PreferenceManager mPreferenceManager;
    private ListView mList;
    private boolean viewCreated;
    // private boolean mHavePrefs;
    // private boolean mInitDone;

    /**
     * The starting request code given out to preference framework.
     */
    private static final int FIRST_REQUEST_CODE = 100;

    private static final int MSG_BIND_PREFERENCES = 1;
    private final Handler mHandler = new Handler()
    {
        @Override
        public void handleMessage(Message msg)
        {
            switch (msg.what) {

            case MSG_BIND_PREFERENCES:
                if (viewCreated) {
                    bindPreferences();
                }
                break;
            }
        }
    };

    private final Runnable mRequestFocus = new Runnable()
    {
        @Override
        public void run()
        {
            mList.focusableViewAvailable(mList);
        }
    };

    /**
     * Interface that PreferenceFragment's containing activity should implement
     * to be able to process preference items that wish to switch to a new
     * fragment.
     */
    public interface OnPreferenceStartFragmentCallback
    {
        /**
         * Called when the user has clicked on a Preference that has a fragment
         * class name associated with it. The implementation to should
         * instantiate and switch to an instance of the given fragment.
         */
        boolean onPreferenceStartFragment(PreferenceFragment caller,
                Preference pref);
    }

    @SuppressLint("NewApi")
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        try {
            Constructor<?> constructor = PreferenceManager.class
                    .getDeclaredConstructor(Activity.class, int.class);
            constructor.setAccessible(true);
            mPreferenceManager = (PreferenceManager) constructor.newInstance(
                    getActivity(), FIRST_REQUEST_CODE);
        } catch (Throwable e) {
            throw new RuntimeException(
                    "Could not instantiate PreferenceManager: "
                            + e.getMessage());
        }

    }

    @Override
    public final View onCreateView(LayoutInflater inflater,
            ViewGroup container, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.activity_preferences, null);
        this.viewCreated = true;
        return v;
    }

    // @Override
    // public View onCreateView(LayoutInflater inflater, ViewGroup container,
    // Bundle savedInstanceState) {
    // return inflater.inflate(R.layout.preference_list_fragment, container,
    // false);
    // }

    @Override
    public void onActivityCreated(Bundle savedInstanceState)
    {
        super.onActivityCreated(savedInstanceState);

        // if (mHavePrefs) {
        bindPreferences();
        // }

        // mInitDone = true;

        if (savedInstanceState != null) {
            Bundle container = savedInstanceState.getBundle(PREFERENCES_TAG);
            if (container != null) {
                final PreferenceScreen preferenceScreen = getPreferenceScreen();
                if (preferenceScreen != null) {
                    preferenceScreen.restoreHierarchyState(container);
                }
            }
        }
    }

    // @Override
    // public void onStart() {
    // super.onStart();
    // IllegalAccessException
    // try {
    // Method m = PreferenceManager.class
    // .getDeclaredMethod("setOnPreferenceTreeClickListener",
    // Class.forName("android.preference.PreferenceManager$OnPreferenceTreeClickListener"));
    // m.invoke(mPreferenceManager, this);
    // } catch (Exception e) {
    // e.printStackTrace();
    // }
    // mPreferenceManager.setOnPreferenceTreeClickListener(this);
    // }

    @Override
    public void onStop()
    {
        super.onStop();
        try {
            Method m = PreferenceManager.class
                    .getDeclaredMethod("dispatchActivityStop");
            m.setAccessible(true);
            m.invoke(mPreferenceManager);
        } catch (Exception e) {
            e.printStackTrace();
        }
        // IllegalAccessException
        // try {
        // Method m = PreferenceManager.class
        // .getDeclaredMethod("setOnPreferenceTreeClickListener",
        // Class.forName("android.preference.PreferenceManager$OnPreferenceTreeClickListener"));
        // m.invoke(mPreferenceManager, (Object) null);
        // } catch (Exception e) {
        // e.printStackTrace();
        // }
        // mPreferenceManager.setOnPreferenceTreeClickListener(null);
    }

    @Override
    public void onDestroyView()
    {
        this.viewCreated = false;
        mList = null;
        mHandler.removeCallbacks(mRequestFocus);
        mHandler.removeMessages(MSG_BIND_PREFERENCES);
        super.onDestroyView();
    }

    @Override
    public void onDestroy()
    {
        super.onDestroy();
        try {
            Method m = PreferenceManager.class
                    .getDeclaredMethod("dispatchActivityDestroy");
            m.setAccessible(true);
            m.invoke(mPreferenceManager);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState)
    {
        super.onSaveInstanceState(outState);

        final PreferenceScreen preferenceScreen = getPreferenceScreen();
        if (preferenceScreen != null) {
            Bundle container = new Bundle();
            preferenceScreen.saveHierarchyState(container);
            outState.putBundle(PREFERENCES_TAG, container);
        }
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data)
    {
        super.onActivityResult(requestCode, resultCode, data);

        try {
            Method m = PreferenceManager.class.getDeclaredMethod(
                    "dispatchActivityResult", int.class, int.class,
                    Intent.class);
            m.setAccessible(true);
            m.invoke(mPreferenceManager, requestCode, resultCode, data);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Returns the {@link PreferenceManager} used by this fragment.
     * 
     * @return The {@link PreferenceManager}.
     */
    public PreferenceManager getPreferenceManager()
    {
        return mPreferenceManager;
    }

    /**
     * Sets the root of the preference hierarchy that this fragment is showing.
     * 
     * @param preferenceScreen
     *            The root {@link PreferenceScreen} of the preference hierarchy.
     */
    public void setPreferenceScreen(PreferenceScreen preferenceScreen)
    {
        try {
            Method m = PreferenceManager.class.getDeclaredMethod(
                    "setPreferences", PreferenceScreen.class);
            m.setAccessible(true);
            boolean result = (Boolean) m.invoke(mPreferenceManager,
                    preferenceScreen);
            if (result && preferenceScreen != null) {
                postBindPreferences();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Gets the root of the preference hierarchy that this fragment is showing.
     * 
     * @return The {@link PreferenceScreen} that is the root of the preference
     *         hierarchy.
     */
    public PreferenceScreen getPreferenceScreen()
    {
        try {
            Method m = PreferenceManager.class
                    .getDeclaredMethod("getPreferenceScreen");
            m.setAccessible(true);
            return (PreferenceScreen) m.invoke(mPreferenceManager);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * Adds preferences from activities that match the given {@link Intent}.
     * 
     * @param intent
     *            The {@link Intent} to query activities.
     */
    public void addPreferencesFromIntent(Intent intent)
    {
        requirePreferenceManager();
        try {
            Method m = PreferenceManager.class
                    .getDeclaredMethod("inflateFromIntent");
            m.setAccessible(true);
            PreferenceScreen ps = (PreferenceScreen) m.invoke(
                    mPreferenceManager, intent, getPreferenceScreen());
            setPreferenceScreen(ps);
        } catch (Throwable e) {

        }
    }

    /**
     * Inflates the given XML resource and adds the preference hierarchy to the
     * current preference hierarchy.
     * 
     * @param preferencesResId
     *            The XML resource ID to inflate.
     */
    public void addPreferencesFromResource(int preferencesResId)
    {
        requirePreferenceManager();

        try {
            Method m = PreferenceManager.class.getDeclaredMethod(
                    "inflateFromResource", Context.class, int.class,
                    PreferenceScreen.class);
            m.setAccessible(true);
            PreferenceScreen prefScreen = (PreferenceScreen) m.invoke(
                    mPreferenceManager, getActivity(), preferencesResId,
                    getPreferenceScreen());
            setPreferenceScreen(prefScreen);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * {@inheritDoc}
     */
    public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,
            Preference preference)
    {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            try {
                Method m = Preference.class.getDeclaredMethod("getFragment");
                Object o = m.invoke(preference);
                if (o != null
                        && getActivity() instanceof OnPreferenceStartFragmentCallback) {
                    return ((OnPreferenceStartFragmentCallback) getActivity())
                            .onPreferenceStartFragment(this, preference);
                }
            } catch (Throwable e) {
            }
        }
        return false;
    }

    /**
     * Finds a {@link Preference} based on its key.
     * 
     * @param key
     *            The key of the preference to retrieve.
     * @return The {@link Preference} with the key, or null.
     * @see PreferenceGroup#findPreference(CharSequence)
     */
    public Preference findPreference(CharSequence key)
    {
        if (mPreferenceManager == null) {
            return null;
        }
        return mPreferenceManager.findPreference(key);
    }

    private void requirePreferenceManager()
    {
        if (mPreferenceManager == null) {
            throw new RuntimeException(
                    "This should be called after super.onCreate.");
        }
    }

    private void postBindPreferences()
    {
        if (mHandler.hasMessages(MSG_BIND_PREFERENCES))
            return;
        mHandler.obtainMessage(MSG_BIND_PREFERENCES).sendToTarget();
    }

    private void bindPreferences()
    {
        final PreferenceScreen preferenceScreen = getPreferenceScreen();
        if (preferenceScreen != null) {
            preferenceScreen.bind(getListView());
        }
    }

    /** @hide */
    public ListView getListView()
    {
        ensureList();
        return mList;
    }

    private void ensureList()
    {
        if (mList != null) {
            return;
        }
        View root = getView();
        if (root == null) {
            throw new IllegalStateException("Content view not yet created");
        }
        View rawListView = root.findViewById(android.R.id.list);
        if (!(rawListView instanceof ListView)) {
            throw new RuntimeException(
                    "Content has view with id attribute 'android.R.id.list' "
                            + "that is not a ListView class");
        }
        mList = (ListView) rawListView;
        if (mList == null) {
            throw new RuntimeException(
                    "Your content must have a ListView whose id attribute is "
                            + "'android.R.id.list'");
        }
        mList.setOnKeyListener(mListOnKeyListener);
        mHandler.post(mRequestFocus);
    }

    private OnKeyListener mListOnKeyListener = new OnKeyListener()
    {

        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event)
        {
            Object selectedItem = mList.getSelectedItem();
            if (selectedItem instanceof Preference) {
                View selectedView = mList.getSelectedView();
                Preference p = (Preference) selectedItem;
                try {
                    Method m = Preference.class.getDeclaredMethod("onKey",
                            View.class, int.class, KeyEvent.class);
                    m.setAccessible(true);
                    boolean result = (Boolean) m.invoke(p, selectedView,
                            keyCode, event);
                    return result;
                } catch (Throwable e) {
                }
            }
            return false;
        }

    };
}
person Yaroslav Mytkalyk    schedule 07.02.2013