在我学习Android开发的时候,我意识到使用“上下文”几乎是我们所做的一切的共同主题。
我最近阅读了以下文章,以及它的所有参考文献:What is it about Context?
除了这是关于Context的信息资源之外,我还有一个额外的问题,基于它陈述的内容。
它说(我引用):(6) When in fragment, assign a context to the one from onAttach(Context context) method
问题(1):我目前正在尝试使用Preferencec-API
中的PreferenceFragment
来调整一些首选项。就Context
而言,我该如何解决这个问题?
注意:我在onPreferenceChangedListener
内做这个。
问题(2):是否有一个简单的答案,或者我是否必须遵循我从链接提供的报价中的说明?如果是这样,我将如何做到这一点,因为我的PreferenceFragment没有任何onAttach
方法?
除了将extends PreferenceFragment
改为PreferenceFragmentCompat
之外,我知道我必须在我的代码中实现onAttach(Context context)
。
问题1 - 更改为PreferenceFragmentCompat
是否需要进行任何其他相应的更改?
Q#2 - 我看到我必须将onAttach
添加到我的代码中 - 这会先于onCreate,
还是相反?
问题3 - 我必须将我的所有代码从onCreate
迁移到onAttach
吗? ..或者它的目的是什么?
最终,我需要知道我做错了什么,以及如何轻松纠正它。 请记住,我仍然是许多Android开发概念的新手 - 但我正在学习。
import ...
/* SUPPOSED to CHANGE TO 'PreferenceFragmentCompat' (?) */
public class SettingsFragment extends PreferenceFragment {
// THIS IS A TOGGLE PREFERENCE
public static final String PREF_GPS_STATE_LISTENER = "pref_gpsStateListener";
// THIS IS A LIST-PREFERENCE
public static final String PREF_NOTIFICATION_MODE = "pref_notificationMode";
// I STILL NEED TO IMPLEMENT THESE PREFERENCE CHANGES LATER (DISREGARD)
public static final String NOTIFICATION_MODE_A = "Mode A";
public static final String NOTIFICATION_MODE_B = "Mode B";
// THIS IS A LIST-PREFERENCE
public static final String PREF_NOTIFICATION_TYPE = "pref_notificationType";
// I STILL NEED TO IMPLEMENT THESE PREFERENCE CHANGES LATER (DISREGARD)
public static final String NOTIFICATION_TYPE_SOUND = "Sound";
public static final String NOTIFICATION_TYPE_VIBRATION = "Vibration";
private SharedPreferences.OnSharedPreferenceChangeListener prefChangeListener;
/*
/ IS THIS WHERE I'M SUPPOSED TO IMPLEMENT 'onAttach(Context context)' (?)
/ AND IF SO, WHAT CHANGES TO MY CURRENT CODE MUST I MAKE.. (?)
*/
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
prefChangeListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
@Override
public void onSharedPreferenceChanged
(SharedPreferences sharedPreferences, String key) {
if (key.equals(PREF_GPS_STATE_LISTENER)) {
// FIRE METHOD BELOW TO ENABLE/DISABLE A LISTENER OPTION IN PREFERENCES
gpsListenerChangedMethod();
}
if (key.equals(PREF_NOTIFICATION_MODE)) {
Preference notifModePref = findPreference(key);
notifModePref.setSummary(sharedPreferences.getString(key, ""));
// FIRE METHOD BELOW TO HANDLE [SOME] OF THE CHANGES TO THIS PREFERENCE
notifModeChangedMethod();
}
if (key.equals(PREF_NOTIFICATION_TYPE)) {
Preference notifTypePref = findPreference(key);
notifTypePref.setSummary(sharedPreferences.getString(key, ""));
// FIRE METHOD BELOW TO HANDLE [SOME] OF THE CHANGES TO THIS PREFERENCE
notifTypeChangedMethod();
}
}
};
} // END of [onCreate]
public void gpsListenerChangedMethod() {
final PackageManager pacMan =
getActivity().getApplicationContext().getPackageManager();
final ComponentName comp_LocationReceiver = new ComponentName
("com.studio2bdesigns.gpskillerproalpha122018",".LocationReceiver");
final SharedPreferences getPrefs =
PreferenceManager.getDefaultSharedPreferences(getActivity());
if (getPrefs.getBoolean(PREF_GPS_STATE_LISTENER, true)) {
pacMan.setComponentEnabledSetting(comp_LocationReceiver,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
Log.i(TAG, "PREF_GPS_STATE_LISTENER is 'TRUE' - Enabling Receiver.");
} else if (!getPrefs.getBoolean(PREF_GPS_STATE_LISTENER, true)) {
pacMan.setComponentEnabledSetting(comp_LocationReceiver,
PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
Log.i(TAG, "PREF_GPS_STATE_LISTENER is 'FALSE' - Disabling Receiver.");
}
}
public void notifModeChangedMethod() {
Log.i(TAG, "Firing METHOD [notifModeChangedMethod]");
// Finish NOTIFICATION_MODE changes here, elsewhere, etc
}
public void notifTypeChangedMethod() {
Log.i(TAG, "Firing METHOD [notifTypeChangedMethod]");
// Finish NOTIFICATION_TYPE changes here, elsewhere, etc
}
@Override
public void onResume() {
super.onResume();
getPreferenceScreen().getSharedPreferences()
.registerOnSharedPreferenceChangeListener(prefChangeListener);
Preference notifModePref = findPreference(PREF_NOTIFICATION_MODE);
notifModePref.setSummary(getPreferenceScreen().getSharedPreferences()
.getString(PREF_NOTIFICATION_MODE, ""));
Preference notifTypePref = findPreference(PREF_NOTIFICATION_TYPE);
notifTypePref.setSummary(getPreferenceScreen().getSharedPreferences()
.getString(PREF_NOTIFICATION_TYPE, ""));
}
@Override
public void onPause() {
super.onPause();
getPreferenceScreen().getSharedPreferences()
.unregisterOnSharedPreferenceChangeListener(prefChangeListener);
}
// This METHOD was referenced in the Link I provided in my original post, as a way to retrieve Context from within a Fragment (such as PreferenceFragment I assume).. I'm unsure of how to go about implementing this.
@Override
public void onAttach (Context context) {
super.onAttach(context);
// UNSURE OF HOW TO IMPLEMENT THIS METHOD.
}
}
// END of CLASS [SettingsFragment]
}
所以我的帖子已被上面编辑,包括我当前的PreferenceFragment
代码,以及我有关将其更改为PreferenceFragmentCompat
的问题,以及在何处,何时以及如何使用onAttach()
(目前似乎功能正常相当不错,但我被告知我需要它)。
要初始化首选项(或任何其他服务器),您可以为服务提供任何上下文,无论是您的片段,活动还是您的应用程序上下文,您甚至可以通过View
给出View.getContext()
的上下文!因为它们都解析为首选项/其他API所需的应用程序上下文。
值得注意的是,您应该关注“何时”获取上下文。例如,如果您的片段已分离,则它没有上下文,因此将返回null给您。最好的地方是onViewCreated
或onAttached
。
根据以下指南,链接中提供的规则“良好”,但它们并不完整(不幸的是,Google不提供完整的规则)。 #5是最重要的一个,因为内存泄漏问题,你不应该对你的上下文(或视图,片段,活动)保持静态引用。
要添加首选项更改的侦听器,您需要在onResume
中注册它并在onPaused
中取消注册它,如下所示:
@Override
public void onResume() {
super.onResume();
getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}
@Override
public void onPause() {
getPreferenceManager().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
super.onPause();
}