androidandroid-fragmentssharedpreferencesadapter

set SharedPreferences name dynamically


I'm using this sequence for designing an app:

(This classes will not change and I'm going to use them for multiple activities)

  1. Custom adapter
  2. Model Class
  3. Shared Preferences

And Activity with tab Layouts(with two Fragments) which contains:

I'm going to name this: (Package #1)

Now I want to duplicate Package #1 and change some contents then name it as Package #2. But I have a problem here.

I'm using one shared preferences for Package #1, Package #2, Package #3..., right? please have a look into my shared preferences class:

public class SharedPreference_light {

    private SharedPreferences settings;
    private SharedPreferences.Editor editor;
    private Gson gson = new Gson();

    private static final String PREFS_NAME = "Light_Products";
    private static final String FAVORITES = "Favorite_Tones_Light";



    public SharedPreference_light(Context context) {
        settings = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
        editor = settings.edit();
    }

    private void saveFavorites(List<ProductLocal> favorites) {
        String jsonFavorites = gson.toJson(favorites);
        editor.putString(FAVORITES, jsonFavorites);
        editor.apply();
    }

    public void addFavorite(ProductLocal product) {
        List <ProductLocal> favorites = getFavorites();
        if (favorites == null)
            favorites = new ArrayList<>();
        favorites.add(product);
        saveFavorites(favorites);
    }

    public void removeFavorite(ProductLocal product) {
        ArrayList <ProductLocal> favorites = getFavorites();
        if (favorites != null) {
            favorites.remove(product);
            saveFavorites(favorites);
        }
    }

    public ArrayList <ProductLocal> getFavorites() {
        List<ProductLocal> favorites;
        if (settings.contains(FAVORITES)) {
            String jsonFavorites = settings.getString(FAVORITES, null);
            ProductLocal[] favoriteItems = gson.fromJson(jsonFavorites, ProductLocal[].class);
            favorites = Arrays.asList(favoriteItems);
            favorites = new ArrayList <> (favorites);
        } else
            return null;

        return (ArrayList <ProductLocal> ) favorites;
    }
}

The problem is if I use these two variables:

private static final String PREFS_NAME = "Light_Products";
private static final String FAVORITES = "Favorite_Tones_Light";

There will be a conflict between those packages. because I'm going to add some list items into shared preferences and use getSharedPreferences. then all those items from multiple packages will be added into one shared preferences, and I don't want that.

Now my real question would be:

How can I set shared preferences names(variables) dynamically?

Note: I have one usage of shared preferences in custom adapter:

private boolean checkFavoriteItem(ProductLocal checkProduct) {
    boolean check = false;
    List<ProductLocal> favorites = sharedPreference.getFavorites();
    if (favorites != null) {
        for (ProductLocal product : favorites) {
            if (product.equals(checkProduct)) {
                check = true;
                break;
            }
        }
    }
    return check;
}

Adapter:

public class LocalAdapter extends RecyclerView.Adapter<LocalAdapter.MyViewHolder>{

private SharedPreference_light sharedPreference;


public LocalAdapter(Activity activity, List<ProductLocal> dataList, RelativeLayout snackLayout) {
    this.snackLayout=snackLayout;
    this.activity = activity;
    this.dataList = dataList ;
    this.dataListFilter = dataList ;
    sharedPreference = new SharedPreference_light(activity);
    methods = new Methods(activity);
}

Solution

  • first you would like to use an interface providing the package name:

    public interface LightPrefs {
    
        String getPackageName();
    }
    

    Secondly, you can reuse your class and make it implementing the previous interface but making it abstract:

    public abstract class SharedPreference_light implements LightPrefs {
    
        private SharedPreferences settings;
        private SharedPreferences.Editor editor;
    
        protected final String PREFS_NAME = "Light_Products_" + getPackageName();
        protected final String FAVORITES = "Favorite_Tones_Light_" + getPackageName();
    
        public SharedPreference_light(Context context) {
            settings = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
            editor = settings.edit();
        }
    
        private void saveFavorites(List<ProductLocal> favorites) {
            String jsonFavorites = gson.toJson(favorites);
            editor.putString(FAVORITES, jsonFavorites);
            editor.apply();
        }
    
        public void addFavorite(ProductLocal product) {
            List <ProductLocal> favorites = getFavorites();
            if (favorites == null)
            favorites = new ArrayList<>();
            favorites.add(product);
            saveFavorites(favorites);
        }
    
        public void removeFavorite(ProductLocal product) {
            ArrayList <ProductLocal> favorites = getFavorites();
            if (favorites != null) {
                favorites.remove(product);
                saveFavorites(favorites);
            }
        }
    
    }
    

    Especially pay attention to some visibility modifiers that have changed. And finally extend this abstract class in your packages:

    public class SharedPreference_package1 extends SharedPreference_light {
    
        private static final String TAG = "SharedPref_package1";
    
        public SharedPreference_package1(Context context) {
            super(context);
            Log.d(TAG, PREFS_NAME);
        }
    
        @Override
        public String getPackageName() {
            return "package#1";
        }
    }
    

    and:

    public class SharedPreference_package2 extends SharedPreference_light {
    
        private static final String TAG = "SharedPref_package2";
    
        public SharedPreference_package2(Context context) {
            super(context);
            Log.d(TAG, PREFS_NAME);
        }
    
        @Override
        public String getPackageName() {
            return "package#2";
        }
    }
    

    Instantiating both of these classes gives you this log:

    D/SharedPref_package1: Light_Products_package#1
    D/SharedPref_package2: Light_Products_package#2
    

    About the adapter, I think you should specify the shared preference object upon construction:

    public class LocalAdapter extends RecyclerView.Adapter<LocalAdapter.MyViewHolder>{
    
    private SharedPreference_light sharedPrefs;
    
    public LocalAdapter(Activity activity, List<ProductLocal> dataList, RelativeLayout snackLayout, SharedPreference_light sharedPrefs) {
        this.snackLayout=snackLayout;
        this.activity = activity;
        this.dataList = dataList ;
        this.dataListFilter = dataList ;
        this.sharedPrefs = sharedPrefs;
        methods = new Methods(activity);
    }
    

    So you can initialise your adapter like this in package #1:

    SharedPreference_package1 sharedPrefs = new SharedPreference_package1();
    
    LocalAdapter adapter = new LocalAdapter(activity, dataList, snackLayout, sharedPrefs);
    

    And you can adapt with SharedPreference_package2 in the second package.

    Hope this will help you.