Marco Castanho
Marco Castanho

Reputation: 473

Getting resources from a static context

I've read a few questions about this, but I wasn't happy with the answers, so I decided do ask about my particular example.

I'm developing and Android App that has a Settings screen with a few configurable integer parameters. All these parameters have a maximum and minimum value. Therefore, everytime the user sets a new value for those parameters, I want to validate them. If the new value is out of the defined bounds, I want to show a Toast informing the user of what went wrong.

On the other hand, because in some situations in my App the user can "spam" a button that may show a Toast, in order to avoid having Toast showing repetedly for a while, I created an Application class with a static Toast that is shown everytime I want to show a toast:

public class MyApplication extends Application {
    private static Toast toast;
    public static void showToast(Context context, String string){
       //(...)
    }
}

Back to the Settings page, here's how I implemented it:

public class SettingsActivity extends PreferenceActivity {
    private Context context;
    static SharedPreferences sharedPreferences;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        context = this;
        sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
        getFragmentManager().beginTransaction().replace(android.R.id.content, new SettingsFragment()).commit();
    }

    public static class SettingsFragment extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener {
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            addPreferencesFromResource(R.xml.preferences);
            setListeners();
        }

        public void setListeners() {
            setListenerA();
            //(other listeners to other settings)
        }

        private void setListenerA() {
            findPreference(KEY_PREF_A).setOnPreferenceChangeListener(
                new Preference.OnPreferenceChangeListener() {
                    @Override
                    public boolean onPreferenceChange(Preference preference, Object newValue) {
                        boolean isEmpty = newValue.toString().isEmpty();
                        //(other validations)
                        boolean isValid = !isEmpty; //&& (other validations)
                        if(!isValid){
                            if(isEmpty){
                                MyApplication.showToast(context, MyApplication.getResources().getString(R.string.toastPreferenceNullValue));
                            } else if(isAnotherReasonToFail1){
                                // another Toast
                            } // else if(other reasons to fail)
                        }
                        return isValid;
                    }
                }
            );
        }
    }
}

And here are my problems: MyApplication.getResources() is a non-static method and cannot be called from the static context of class SettingsFragment. Also context is not static (as it should not be) and can't also be referenced there.

I need to show that Toast because otherwise the user wouldn't have a clue why his settings weren't being applied. On the other hand, I need the error message to be stored in the strings.xml file, not only because that's how you do it, but also for future multi-language purposes.

I am not familiar with how Fragments work, and I made the Settings screen like this after reading a few articles (like this one) and some questions here. There might be a different way to make a Settings screen that allows me to do what I want, I just don't know any.

Can someone suggest an approach that fits my problem?

Thanks

EDIT: emerssso solved the resources part. Now the problem is only how to call the Toast without having a context.

Upvotes: 0

Views: 604

Answers (1)

emerssso
emerssso

Reputation: 2386

Fragment has a getResources() method that is equivalent to calling Application::getResources(). The only caveat is that you have to make sure that the fragment is attached to an activity (i.e. getActivity() != null) or you risk throwing an exception.

See: https://developer.android.com/reference/android/app/Fragment.html#getResources()

More generally, getActivity() can be used to get a valid context whenever the fragment is attached to the activity, as Activity is an implementation of Context.

If you want to have a context reference even after a fragment has detached, you can store a reference to getActivity().getApplicationContext() safely in the fragment for later use, but this is probably not ideal.

Upvotes: 5

Related Questions