0

My app consists of a single activity. It has a navigation drawer which changes fragment in the activity. One of the nav drawer item is Settings screen which is androidx preference fragment and inherits PreferenceFragmentCompat. App uses MVVM pattern

In my other fragments view model, I call method of repository which gets data from internet and then saves locally using room db and return LiveData<List<MyData>> which is used to display the UI of fragment.

Now I want this behavior: By default fetch data only from local db and if there is a change in preference then fetch data from internet and save locally also.

so where should I listen from change in pref? I think maybe MainActivity but how will other fragments know about this change?

UPDATE 1 I have four fragments: past, present, future and settings. whenever any of the first three fragments opens, I want to know if preference was changed or not.

Nitin Verma
  • 485
  • 4
  • 19
  • to save and get data from preference you can follow this answer :- https://stackoverflow.com/questions/55753375/shared-preferences-arent-overwriting-with-the-same-key/55756479#55756479 – Sandeep Malik May 08 '19 at 05:46
  • @SandeepMalik I know how to read and write in sharedPref, I am asking how to listen for changes in sharedPref? – Nitin Verma May 08 '19 at 05:51

2 Answers2

1

Update after question update: If user can only update preferences from Settings fragment and then click on say for example future fragment than, in future fragments onStart check if the value is changed or not from previous one. You have to maintain previous value.

Fist way is to implement OnSharedPreferenceChangeListener in your activity/fragment.

@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, 
 String key) {
   if (key.equals(“signature”)) {
    Log.i(TAG, “Preference value was updated to: “ + s 
 haredPreferences.getString(key, ""));
  }
}

Refer this for more https://developer.android.com/guide/topics/ui/settings/use-saved-values#onsharedpreferencechangelistener

Update: For proper lifecycle management in your Activity or Fragment, you should register and unregister this listener in the onResume() and onPause() callbacks, as shown below:

Second way to achieve this is using local broadcasts. Whenever you are updating the shared preferences then post a local broadcast.

Refer this for Broadcasts.

https://developer.android.com/guide/components/broadcasts

TheAnkush
  • 885
  • 7
  • 10
  • alright so activity gets notified of the change in preferences. How will the fragment know about it? – Nitin Verma May 08 '19 at 06:16
  • @NitinVerma - Go through the link, same method can be implemented in Fragment also. I updated the answer for better lifecycle management. – TheAnkush May 08 '19 at 06:18
  • I will register for listening changes and then un-register in onPause of fragment. so when I move from a fragment to settings, fragment onPause method will be called so it will no longer be listening for changes. – Nitin Verma May 08 '19 at 06:23
  • Since you have one activity for all the fragments, I recommend implementing it in activity. And whenever you receive event in Activity pass it on to fragment through an interface. Only trying here can help. Further, Please share code including how many fragments you have and on which fragment you are changing value and where you want to update data? – TheAnkush May 08 '19 at 06:28
  • I have updated the question. and I don't think this approach will solve the problem either. when MainActivity gets a change event, It cannot pass this information through interface because that fragment might not be in the foreground. – Nitin Verma May 08 '19 at 06:38
  • I think that In main activity I should make a boolean variable, when pref changes, make it true and then on create of any other fragment, check this boolean, if it's true detch data from internet. – Nitin Verma May 08 '19 at 06:39
  • @NitinVerma yup, I also updated the same after reading the update on question. Trying it will let us know if it works or not. :) – TheAnkush May 08 '19 at 06:43
0

Create a LiveData field like fromInternet in your MainViewModel,notify it setting changed in your PreferenceFragmentCompat:

fromInternetPreference.setOnPreferenceChangeListener((p,value)->{
    ViewModelProviders.of(getActivity()).get(MainViewModel.class).notifyFromInternet(value);
    return true;
});

In other fragments,just observe the isFromInternet LiveData:

ViewModelProviders.of(getActivity()).get(MainViewModel.class)
        .getFromInternet().observe(this, { value ->
             //do your work,may be currentFragmentViewModel.setFromInternet(value)
        });

I have omitted some code to keep the answer simple.You can easily complete them.

JiajiaGu
  • 1,279
  • 14
  • 10