How to send object/state to whole application/all fragments? - android

I am making an app, where there is a searchbox in Main Activity and bottom navigation. In searchbox, the user choose te location, then sends the query to the weather API. I want to pass the object, which is the response from the API, to all fragments in my app. What is the easiest way to do that?

You can use a ViewModel to store your data. Also, using MutableLiveData you can dynamically update your UI to the changes of the model.
Use RxJava to create an EventBus object, which can hold an BehaviorSubject with the latest published data. Again, you can subscribe to this data and update your UI automatically.
Use a Room or Realm to store data, if you need the location between multiple app sessions.

You need to send whole object through this in your application and access it anywhere you want to
Step 1:
Store your data in list you want to like:
ArrayList<FeaturedProductDataModel> featuredProductsDataModelArrayList;
///////////get data and store in ArrayList///////////////////
featuredProductsDataModelArrayList = new ArrayList<(listofhome.getFeaturedProducts());
Step 2:
Declare Shared Preference and put data in it to further use in all application
featuretopprefernce = getActivity().getSharedPreferences("homelist", Context.MODE_PRIVATE);
SharedPreferences.Editor prefsEditor = featuretopprefernce.edit();
//Set the values
Gson gson = new Gson();
String listofbusiness = gson.toJson(featuredProductsDataModelArrayList);
prefsEditor.putString("featuredProductsDataModelArrayList", listofbusiness);
prefsEditor.apply();
Step 3:
In recieving activity or fragment create a list and put data in it
ArrayList<FeaturedProductDataModel> dataModelArrayList;
SharedPreferences featuredprefernce;
featuredprefernce = getActivity().getSharedPreferences("homelist", Context.MODE_PRIVATE);
featuredlist = featuredprefernce.getString("featuredProductsDataModelArrayList",null);
Gson gson = new Gson();
Type type = new TypeToken<List<FeaturedProductDataModel>>(){}.getType();
dataModelArrayList = gson.fromJson(featuredlist, type);
You'll get your data in dataModelArrayList now use it as you like.

Actually, you have several options:
To save received data into the local database (you can use Room from Jetpack). And then to load the data from the database to the screen you need separately.
Or you can save the data into memory: it can be something like a DI container.
Also, you can use RxJava caching or Retrofit caching.
The second solution is the simplest for you.

Related

Mutablelivedata variable instance size issue

Let's say we have the stock of items stored in the JSON txt file. To access the data we load JSON file using a stringBuilder class, then populate StokItems into:
List<StockItem> stock;
like this:
stock.clear();
Gson gson = new Gson();
stock = gson.fromJson(stringBuilder.toString(), new TypeToken<List<StockItem>>() {
}.getType());
as we would like to take advantage of the LiveData in Android we introduced:
MutableLiveData<List<StockItem>> stockLiveData = new MutableLiveData<>();
To make it working we have to post data into it:
public LiveData<List<StockItem>> getLiveStockList() {
stockLiveData.postValue(stock);
return stockLiveData;
}
So here is the question, if the line:
stockLiveData.postValue(stock);
consumes memory for creating another copy of
List<StockItem> stock
and if so, could be it's a good idea to keep "original data" inside the
stockLiveData
variable only to reduce the memory impact? (If is it possible ...)
No need to use global variable to hold temporary data. either you can use local variable or directly post to LiveData.
public LiveData<List<StockItem>> getLiveStockList() {
return stockLiveData;
}
And then either
List stock = gson.fromJson(stringBuilder.toString(), new TypeToken<List<StockItem>>() { }.getType());
stockLiveData.postValue(stock);
or
stockLiveData.postValue(gson.fromJson(stringBuilder.toString(), new TypeToken<List<StockItem>>() { }.getType()))
You can also access the list inside LiveData like below:
stockLiveData.getValue();
Which return the original list data.
There are couple of things about your code I want to point out here:
You do not necessarily need to call postValue in your getter function. As far as there are observers observing from your getter function, you can post value from anywhere.
Even if you use mutable live data that does not necessarily mean that you're allocating memory for or creating a copy of List. When you set or post value on your Mutable Live Data, you're basically referencing the existing list on to value in your Mutable Live Data.

Reading SharedPreferences stored by Activity in a Service?

I am using a class to create a background service which runs all the time. When using the Android app the user can enter data which are stored via SharedPreferences. The storing works well and the stored data are available in the activity which stores it. I am using SharedPreferences like this:
SharedPreferences mPrefs = getSharedPreferences("Identifier",Context.MODE_PRIVATE);
In the service I am trying to access to this values that are stored in the activity. Therefore I am using the SharedPreferences the same way:
SharedPreferences mPrefs = getSharedPreferences("Identifier",Context.MODE_PRIVATE);
I am storing an object this way in the activity:
Gson gson = new Gson();
SharedPreferences.Editor prefsEditor = mPrefs.edit();
String json = gson.toJson(myObject);
prefsEditor.putString("value",json);
prefsEditor.commit();
And try to read it this way, but json returns null:
Gson gson = new Gson();
String json = mPrefs.getString("value",null);
Any idea what might be wrong? Is the context wrong? But how should it be?
Try to use a default shared preferences instance, which is shared across all your Activity and Service classes, use below method.
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this/*context*/);
This is the best way for storing primitives datatype(like booleans) or serializable objects. However, if you're capturing a lot of JSON data, you might consider using an SQLite database instead.
The problem was that the service is running in a different process. Therefore I used tray which works perfectly for multiple processes: https://github.com/grandcentrix/tray.

Reading from SharedPreferences vs. keeping an instance of the object

THE SCENARIO
I have a class that makes use of a request list set by the user. The request list is stored in SharedPreferences. The dilemma I'm facing is to whether to keep an instance of the request list or to read from SharedPreferences every time the request list is needed (which is very frequent).
Also not that Gson is used to deserialize the object.
The code goes like this:
public List<PrayerTimesCalculator.Time> getDefaultRequestList() {
if (mRequestList != null) return mRequestList;
// Try getting request list from preferences;
Gson gson = new Gson();
String json = mSharedPref.getString(KEY_PREF_REQUEST_LIST, null);
Type listType = new TypeToken<List<Time>>() {
}.getType();
mRequestList = gson.fromJson(json, listType);
if (mRequestList != null) return mRequestList;
// Create default list;
mRequestList = Arrays.asList(
Time.DAWN,
Time.MORNING,
Time.AFTERNOON,
Time.EVENING,
Time.MID_NIGHT);
return mRequestList;
}
THE GOAL
My concern is that if I keep around an instance of the request list, and there are multiple instances of this class, an update to the request list in one instance of the class would not be reflected in the rest of the instances until they are recreated.
Thus, I'm leaning towards reading from SharedPreferences unless there is a better way to keep the request list objected updated in all instances.
THE QUESTION
(1) So, how efficient is it to read the same key from SharedPreferences quite frequently by multiple instances of the object? and (2) Is there a better way to keep the request list objected updated in all instances?
So there are a couple of approaches you can take to this.
First, your object is small - re-reading SharedPreferences thousands of times would hardly be noticeable. It's not like SharedPreferences is on a remote drive or has a "bad connection."
Second, if you don't like that answer, then you need a DAO (Data Access Object). SharedPreferences is a form of this already. It provides a means to store and retrieve data with confidence that you have the most recent data available. But, if you feel like you can improve on it's optimization (because it's generic, and this is your app), then you can provide access to you data through a static object that performs both "read" and "write" operations. This will guarantee that access to the object is done with the most recent data. Of course, you will need to be thread aware, etc. (something that is not always guaranteed by SharedPreferences).
Next, you could persist your data in a database and use Cursors or other built-in or custom DAOs. This requires another level of complexity and a lot of overhead, but is useful when several components of your app might need access to the data, provide updates or needs real-time monitoring of changes because background threads or other objects may make modifications that will change your app behavior or result in UI updates.
Last, you could use more complex data stores like a Content Provider. This is really required for cases where you want/need other apps to access data provided by your app (and your app may also consume the data). That's a complex solution and implementation is well outside the scope of this question.
But I mention it because you seem interested in being certain that frequent reads of SharedPreferences is acceptable. It definitely is acceptable - otherwise there would be something else besides it, databases and Content Providers.

Saving an entire Bundle to SharedPreferences

Assuming a method of mine was passed a Bundle already filled with data to be saved, is there a way to save it to SharedPreferences without taking it apart to ints, floats, Strings, etc.?
I prefer the convenience of writing/committing it all in "one fell swoop", so if this isn't possible using SharedPreferences, what other persistent storage approach would you recommend?
SharedPreferences are serialized to XML, which is why you can only use simple types. You'll either have to do your own conversion of the bundle to individual SharePreferences properties or serialize the bundle some other way to disk.
Here's a good reference document discussing the various possibilities of storing data in Android: http://developer.android.com/guide/topics/data/data-storage.html
as far as I know, you can save only primitive data (and their wrappers) to SharedPreferences
why don't you create your own helper method which will iterate through Bundle and save all values from it to SharedPreferences?
Note: If you are using Gson in your project then I think this is a better solution.
I simply used Gson from Google to serialize the specified object into its equivalent JSON representation:
Use this dependency
implementation 'com.google.code.gson:gson:2.8.6'
Code:
Gson gson = new Gson();
String dataToJson = gson.toJson(modelObj);
Then I stored dataToJson as a string in SharedPreferences.Simple!
At the time of string extraction:
String myStoredVal = Value stored in SharedPreference.
GsonBuilder builder = new GsonBuilder();
builder.setPrettyPrinting();
Gson gson = builder.create();
MyModel modelObj = gson.fromJson(prodDataStr, MyModel.class);

How to store data between activities in android?, shopping cart like

I want to make some data available between some activities, just like a shopping cart on a website would do.
This data would probably be a collection of strings maybe a list, a map or something like that. Each item should have associated a id, quantity, type, and a text note (about last one isn't sure yet)
The point is that it doesn't need to be persistent after session ends, and this data will be deleted and recreated completely many times in a whole session.
The question is :
Is the best choice to use a SharedPreferences?, a database?
Thanks!
Even better choice would be some singleton java collection ( map or list ) located via factory object. Just store your cart there and do not bother with database or preferences at all
In case you decide to use preferences, I can recomment my small databinding library:
https://github.com/ko5tik/andject
the simplest way is to use a class with public static variables declared and jus set them from any activity and the retrieve that saved value in any other activity just by calling through a static refrence i.e MyContantsClass.StaticVar1 like
class MySessionVars
{
public static int MyVar1;
}
In first Activity
{
MySessionVars.NyVar1=10;
}
and from any other activity
{
Var = MySessionVars.NyVar1;
}
this is easiest way and will retain vars untill app is closed
You can use Gson (by Google) to send and receive any data btw activities, even class object.
Send: (FirstActivity)
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
Gson gson = new Gson();
intent.putExtra("CustomClassObject", gson.toJson(object));
startActivity(intent);
Receive: (SecondActivity)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
Bundle extras = getIntent().getExtras();
if (extras != null)
{
Gson gson = new Gson();
CustomClass object = gson.fromJson(extras.getString("CustomClassObject"), CustomClass.class);
}
//...
}
SharedPreferences is great for storing simple key/value pairs and small amounts of data, however, I imagine your shopping cart object(s) might be a bit more complicated than that. For that reason I would probably use a SQLite database. If you don't have complicated data though, and you just want to store some simple stuff then Shared Preferences should do.
Use Bundle or Intent.
I wouldn't recommend using database for this purpose. Database needs to be properly opened and closed. Where data is passed around activities, it can get messy which activity should be the last to close the database, and may cause a leak. If you are just passing these data from one Activity to another, create a Bundle, attach it to Intent as you start the next activity.
SharedPreferences are key-value pairs whereas database in Android is SQLite both persists after session. You can do any number of operations on SQLite database and use the same file during next session also.
You can put up comments to my answers if you need more clarifications for your particular use case.
People may talk about making global data or storing values in sharedpreference but according to my experience, the simplest way is to just create a separate class with your variables or arraylists declared as public static then use them throughout your project by just referring to the classname.variable name.
class global
{
public static arrayList<String> my;
}
in any of your activity
global.my
This is the simplest method i found so far!

Categories

Resources