【问题标题】:Android- deprecated method warning regarding PreferenceActivity关于 PreferenceActivity 的 Android 已弃用方法警告
【发布时间】:2013-02-07 16:49:05
【问题描述】:

当我尝试按照 Android 的开发人员指南和教程使用首选项创建设置活动时,我收到如下警告:

“不推荐使用 PreferenceActivity 类型的 addPreferencesFromResource(int) 方法”

代码中的这两行:

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

【问题讨论】:

  • 此方法已弃用,因为您应该使用 PreferenceFragment 但您必须将其用于 HONEYCOMB 之前的版本

标签: android sharedpreferences deprecated android-preferences preferenceactivity


【解决方案1】:

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>

【讨论】:

    【解决方案2】:

    由于该方法已被弃用,因此建议您不要在代码中使用它,因为它完全有可能在未来的 Android 版本中被移除。但是,我还没有遇到实际上已从 Android 中删除的已弃用方法。

    该方法的描述中没有提供替代方法,因为首选方法(从 API 级别 11 开始)是实例化 PreferenceFragment 对象以从资源文件加载您的首选项。在此处查看示例代码:PreferenceActivity

    【讨论】:

      【解决方案3】:

      如果您遇到这样的方法的弃用警告:

      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 将 PreferenceFragment 扩展为 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.主Activity,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>
      

      【讨论】:

        【解决方案4】:

        首选实现现在使用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);
                }
            }
        }
        

        【讨论】:

        • 只有当您使用 API 级别 > 10 时它才会工作。对于较低的 API 级别,您仍然必须使用 PreferenceActivity,因为支持库不包含 PreferenceFragment
        【解决方案5】:

        Raghav Sood 是正确的。但是,如果您需要 PreferenceFragment bad(我需要在选项卡中),您可以使用它。但它可以在未来刹车,所以最好只将它用于旧的 api。 这是我使用 SupportLibrary 和反射制作的一点修改的 PreferenceFragment。

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多