Android 开发中的上下文用例(片段等)

Use cases of Context in Android Development (Fragment, etc)

在我学习 Android 开发的过程中,我意识到 "Context" 的使用几乎是我们所做的每一件事的共同主题。
我最近阅读了以下文章及其所有参考资料:What is it about Context?

除了这是有关 Context 的信息资源之外,我还有一个额外的问题,基于它所说的内容..
它说(我引用):(6) When in fragment, assign a context to the one from onAttach(Context context) method

问题 (1): 我目前正在尝试使用 PreferenceFragment 中的 Preferencec-API 调整一些首选项。就 Context 而言,如何我应该这样做吗?
注意: 我是在 onPreferenceChangedListener.
中执行此操作的
问题 (2): 是否有一个简单的答案,或者我必须按照 Link 提供的报价中的说明进行操作?如果是这样,我该怎么做,因为我的 PreferenceFragment 没有任何 onAttach 方法?

除了将 extends PreferenceFragment 更改为 PreferenceFragmentCompat,我明白我还必须在我的代码中实现 onAttach(Context context)

Q #1 - 更改为 PreferenceFragmentCompat 是否需要任何其他相应更改?

Q #2 - 我看到我必须将 onAttach 添加到我的代码中 - 这会 先于 onCreate, 而不是 ?

Q #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]
}

所以我的 post 已经在上面进行了编辑,以包括我当前的 PreferenceFragment 代码,以及我将其更改为 PreferenceFragmentCompat 的相关问题,以及在哪里、何时以及如何开始使用 onAttach()(因为目前一切似乎运行良好,但有人告诉我我需要它)。

要初始化首选项(或与此相关的任何其他服务器),您可以为服务提供任何上下文,无论是您的片段、activity 还是您的应用程序上下文,您甚至可以提供 View 的上下文由 View.getContext() 提供!因为它们都解析为 preferences/other API 需要的应用程序上下文。

值得注意的是,您应该关心 "when" 您正在获取上下文。例如,如果您的片段是分离的,它没有上下文,因此对您来说 return 为 null。最好的地方是 onViewCreatedonAttached.

link 中提供的规则是 "good" 作为以下指南,但它们并不完整(很遗憾,Google 没有提供完整的规则集) . #5 是最重要的一个,因为内存泄漏问题,您不应该保留对上下文(或视图、片段、活动)的静态引用。

要添加偏好更改侦听器,您需要在 onResume 中注册它并在 onPaused 中取消注册,如下所示:

@Override
public void onResume() {
    super.onResume();
    getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);

}

@Override
public void onPause() {
    getPreferenceManager().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
    super.onPause();
}