Reputation: 473
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
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