当我尝试按照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);
}
}
答案 0 :(得分:15)
PreferenceActivity()
已过时,但PreferenceFragment()
也已过时。 PreferenceFragmentCompat()
现在是解决方法:
添加依赖项
implementation "androidx.preference:preference:1.0.0-alpha3"
或者如果您仍在使用支持库:
implementation "com.android.support:preference-v7:27.1.1"
扩展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>
答案 1 :(得分:7)
由于该方法已弃用,建议您不要在代码中使用它,因为完全有可能在未来的Android版本中将其删除。但是,我还没有遇到过已经从Android中删除的已弃用的方法。
方法描述中没有提供替代方法,因为首选方法(从API级别11开始)是实例化PreferenceFragment个对象以从资源文件加载首选项。请在此处查看示例代码:PreferenceActivity
答案 2 :(得分:1)
Raghav Sood是对的。但是如果你需要PreferenceFragment坏(我需要在标签中)你可以使用它。但它可以在将来制动,以便更好地将它用于旧的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;
}
};
}
答案 3 :(得分:1)
首选实现现在使用Fragment
s。以下内容适用:
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);
}
}
}
答案 4 :(得分:0)
如果您遇到来自以下方法的弃用警告:
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.主要活动,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>