简体   繁体   中英

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

In the time I have spent learning Android Development, I have realized that the use of "Context" is a common theme in nearly everything we do.
I recently read the following Article, and all of it's references: What is it about Context ?

In addition to this being an informative resource regarding Context, I had an additional question, based on something it states..
It says (and I quote): (6) When in fragment, assign a context to the one from onAttach(Context context) method

QUESTION (1) : I am currently trying to adjust some Preferences using the Preferencec-API from within a PreferenceFragment .. In terms of Context , how should I go about this?
NOTE : I am doing this from within onPreferenceChangedListener .

QUESTION (2) : Is there a simple answer, or must I follow the instructions from the Quote I provided from the Link? And if so, how would I go about doing this, as my PreferenceFragment does not have any onAttach Method?

Aside from changing extends PreferenceFragment to be PreferenceFragmentCompat , I understand I must must also implement onAttach(Context context) into my code.

Q #1 - Does changing to PreferenceFragmentCompat require any other consequential changes?

Q #2 - I see that I must add onAttach to my code - would this go prior to onCreate, or instead ?

Q #3 - Must I migrate all of my Code from onCreate into onAttach ? ..or what's its's purpose?

Ultimately, I need to know what I've done incorrectly, and how to go about easily correcting it.
Keep in mind, I am still fairly new to many of Android Development concepts - but I'm learning .


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

So my post has been Edited above to include my current Code for my PreferenceFragment , along with the questions I have pertaining to changing it to PreferenceFragmentCompat , as well as where, when, and how to go about using onAttach() (as currently things seem to function fairly well, but I've been told I need it).

To initialize preferences (or any other server for that matter) you can give any context to the service, be it your fragment's, activity's or your application context, you can even give a View 's context by View.getContext() ! since all of them resolve to your application context which the preferences/other APIs need.

It is worth to note that you should care about "when" you are getting the context. For example, If your fragment is detached, It does not have a context and therefore will return null to you. Best place would be onViewCreated or onAttached .

The rules provided in the link are "good" as in terms of following guidelines, but they are not complete (and a complete set is not provided by Google, unfortunately). The #5 is the most important one, which is you should not keep static references to your context (or views, fragments, activities) because of memory leak issues.

For adding preference changed listener, you need to register it in onResume and unregister it in onPaused like below:

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

}

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM