I am having problems storing a List in an Application class across activities.
In my Splash screen, I am loading data into a List from a MySQL database.
The List is in a class called Rateit that extends Application. I do this in it as a class variable:
public static List<String> masterCats;
In the Splash Screen Activity/Class, I do this:
in onCreate:
Rateit.masterCats = new ArrayList<String>();
Inside my AsyncTask loop where loading data I do this:
Rateit.masterCats.add(cat);
cat being the list item that comes from the database. I have Log.d the data (cat) as well as the ListPosition to check if it is being added to the List and it is.
However, I need to grab that same info in the next Activity and put it into an adapter. It comes back with 0 length.
I simply do this: adapter = new MasterCatAdapter(getActivity(), Rateit.masterCats, tf);
How come the list doesn't maintain data across activies? Is this because its static? something else?
(Note: I will add getter and setter methods here soon!)
As #A--C mentioned in his comment, avoid the model you have now with the static variable. Instead, I would do something like this:
private void yourMethodWhereYouGetYourData(){
//get your data
ArrayList<String> masterCats = new ArrayList<String>();
masterCats.add(cat);
//Assuming you're doing this synchronously, once you've gotten your data just do:
Intent i = new Intent(this, YourActivity.class);
i.putStringArrayListExtra("MasterCats", masterCats);
startActivity(i);
}
Then, in your new Activity's onCreate() or wherever, just access the list by doing:
getIntent().getStringArrayListExtra("MasterCats");
#KickingLettuce also mentioned in the comments about keeping this accessible if the user navigates away from the Activity. So, in whichever Activity you want to save the ArrayList, just convert it to a comma-separated String and save it in SharedPreferences like so:
private void saveCats(){
//get your ArrayList from wherever (either as a global variable or pass it into the
//method.
StringBuilder sb = new StringBuilder();
for(int i = 0; i < masterCats.size(); i++){
if(i == masterCats.size() - 1)
sb.append(masterCats.get(i));
else
sb.append(masterCats.get(i)+",");
}
SharedPreferences.Editor prefsEditor =
PreferenceManager.getDefaultSharedPreferences(this).edit();
prefsEditor.putString("MasterCats", sb.toString()).commit();
//Note: in API 11 and beyond you can store a Set of Strings in SharedPreferences, so
//if you are only targeting API 11+ you could do:
Set<String> masterCatsSet = new LinkedHashSet<String>(); //<--using LinkedHashSet to preserve order
masterCatsSet.addAll(masterCats);
prefsEditor.putStringSet("MasterCats",masterCatsSet).commit();
}
Then access this SharedPreference in your onCreate or something if you wish to persist the list across the Activity lifecycle.
saving the List in a Application extended class is good idea you can achieve it by following
Declare List as follows in your App class like
public static List<String> masterCats;
and declare setter and getter methods for above variable
public List getMasterCatsList()
{
return masteCats;
}
public Void setMasterCatsList(List list)
{
masteCats=list;
}
get the application object as follows in your Loader class as follows
Application application = (YOurClassName That Extends Application class) getApplication();
and set the list as follows
application.setMasterCatsList(List list);
now you can access this list from any activity as follows
Application application = (YOurClassName That Extends Application class) getApplication();
List l = application.getMasterCatsList();
hope it will be helpful to you
Related
i am building an app in Android Studio using kotlin,
the app is a quiz app with a text in the end depending on the result.
I want to know, what is the smoothest way to move a value(i am guessing intent) from the first activity to the last, adjusting it on the way. And how do i use this value to adjust the string showed on the result activity?
I was thinking of creating strings for all results and name them result100, result200, result300 etc. then have a variable that changes according to the answers such as:
buttonParty.setOnClickListener{
desNumber = 100
val intent = Intent(this, ResultPageActivity::class.java)
intent.putExtra("EXTRA_DES", desNumber)
startActivity(intent)
}
retreive it with:
val desNumber = intent.getIntExtra("EXTRA_DES", 100)
than on the last activity:
resultText.setText = findViewById(R.string.result$desNumber)
But this doesnt seem to work unfortunately.
Thanks in advance for any help!
You can do this with something called ViewModel
So you would do something like this:
-On your parent activity (the first), create your ViewModel that will hold your data, and the functions that will alter (or retrieve) that data:
class GameActivity : AppCompatActivity() {
class GameData: ViewModel(){
//Creates the variables that hold the data, with a type that allows them to change over time,
//and to be "observed", but not be useful to this specific example, but this is what I usually use
private val _Result1 : MutableLiveData<String> by lazy {
MutableLiveData<String>().apply { value = "You got a Low Score" }
}
private val _Result2 : MutableLiveData<String> by lazy {
MutableLiveData<String>().apply { value = "You got a High Score" }
}
//Publishes the values of the strings without letting them being altered directly
val Result1 : LiveData<String>
get() = _Result1
val Result2 : LiveData<String>
get() = _Result2
}
}
-On the activity that you want to retrieve the data, do this:
//Declare the variable that will give access to the variables
private val dataModel : GameActivity.GameData by activityViewModels()
//Acess the variables
if(dataModel.Result1.value === "...")
While this answer shows how you can create a model to hold your data in one activity, and access in others, I think the way you are doing it (saving different messages to show) might be done better in a different way. Shouldn't you just save the "points" value in the data model, and use conditions to show the different messages?
You can save the points in this data model the same way it's done with the strings above, but with "Int" instead of "String" in the data types.
Im using REST in my webservice. This is the example payload/parameter i sent when i test my webservice using advance rest client, with form content type (this is the RAW type):
child_id%5B%5D=1&user_id=15&group_id=1&custom=&time=17%3A17%3A00&date=&child_id%5B%5D=2
Where child_id%5B%5D in RAW means child_id[] in the form, so i send an array of child_id (left most and right most in above form). Things are fine here.
The problem occured when i tried to implement this to the Android apps, where i POST those payload/parameter using a HashMap. HashMap cant store two values under the same key, so i cant do something like :
map.put("child_id[]", 1);
map.put("child_id[]", 2);
The latest put will overwrite the earlier put, so the Android apps will only send 2 as value of the child_id.
What should i do? Thanks for your help
You Could add index to the array as follows.
map.put("child_id[0]", 1);
map.put("child_id[1]", 2);
You have a few options for solving this. The easiest would be to create a class to act as a container for your parameters, and store those in an ArrayList
public class Parameter {
private String key;
private String value;
// Getters, setters, other stuff.
}
Which you would then store in an ArrayList
You could also make a class to act as a parameter builder of sorts. You might do something like this:
public class Parameters {
private ArrayList<String> keys = new ArrayList<>();
private ArrayList<String> values = new ArrayList<>();
public void add(String key, String value) { ... }
public ArrayList<String> getKeys() { ... }
public ArrayList<String> getValues() { ... }
}
The second option requires a bit more code but adds some extra flexibility and should make for a cleaner API.
Alternatively, as you mentioned in your own comment, you have the option of using a Map<String, ArrayList<String>>. Which would also work very well in place of the ArrayLists in the above example.
I have value strUser and KEY ,I want to send this value to multiple different classes because this value will be used in 5 classes for url, I know the way to send value to one class only using Intent.putExtra as bellow :
Intent policy= new Intent(LoginActivity.this,EpolicyListPolis.class);
policy.putExtra("etUser",strUser);
policy.putExtra("key",KEY);
startActivity(policy);
How can I send this value to multiple different classes at a time? can i use SharedPrefences..? how the way i write sharedPrefences in class and my destination class?
You can use SharedPreferences.
For storing values into SharedPreferences:
SharedPreferences settings = getSharedPreferences("PREFS_NAME", 0);
SharedPreferences.Editor editor = settings.edit();
editor.putString("etUser", strUser);
editor.putString("key",KEY);
editor.commit();
Just paste these lines before calling startActivity(policy);
And get values from SharedPreferences
SharedPreferences settings = getSharedPreferences("PREFS_NAME", 0);
String etUser1 = settings.getString("etUser", null);
String key1 = settings.getString("key", null);
And paste these lines at where you want etUser1 and key1. You can access this SharedPreferences value in any Activity. If you cant please take a look on here. It may help you.
I hope this will help you.
Try this...
send value from this class with Intent....
Intent policy= new Intent(LoginActivity.this,EpolicyListPolis.class);
policy.putExtra("key",strUser);
startActivity(policy);
this works like: KEY-"key" and VALUE-strUser.
and you get this value from another class using KEY.
Get value like this.
String user = getIntent().getExtras().getString("key",null);
in user you get strUser value. and if strUser not pass any value than default null(right side of "key") asign for user....
same you use from all class you need... but remember all works with KEY...
because KEY(one type of ID) is only which is works to Put and Get particular value.....
If you are using dependency injection create a Model which hold your states in value objects.
Then inject this model in your activities.
Or simply create a Singleton State object which can be referenced from anywhere.
You have to just get these things in the other activity--
Bundle bundle = getIntent().getExtras();
String user = bundle.getString("etUser");
String key = bundle.getString("key");
Or,
you can set these values in a class and get from them whereever you need.
First, get the intent which has started your activity using the getIntent() method:
Intent intent = getIntent();
If your extra data is represented as strings, then you can use intent.getStringExtra() method.
String etUser = intent.getStringExtra("etUser");
String key = intent.getStringExtra("key");
Refer this for more details.
I would like to tell you to use Application class. The better idea to get the reference from the following link
maintain the state of all the variables from the Application class
Bettter to go for this Application b'coz you can access all the variables in every class with out sending from intent.
This will help you.
Application Object are some way, i would go for EventBus (like OTTO from Square or Greenrobot).
Do everting on Application Context tend to create the "GOD Object" problem after quite some time. You should avoid this. SharedPreferences are also some good option.
you can use Bundle for pasing data form one Activity class to other Activity class Like this
Bundle bundle = new Bundle();
bundle.putString("Id", videoChannelId);
bundle.putString("C/V", "C");
bundle.putString("mode", "ch");
bundle.putString("code", "LiveTV");
bundle.putString("urlcount", "2");
Intent intent = new Intent(First.this,Second.class);
intent.putExtras(bundle);
startActivity(intent);
Get the data in the second class like this by giving the bundle id
Bundle getBundle = this.getIntent().getExtras();
name = getBundle.getString("Url")
etc......
I'm not really sure what you want to do, but IMO, if i will use a variable from one class to another, i will make the variable static and "get" the value of that variable from the class..
for example in one class i have a variable:
public class Login extends Activity {
static String username;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.login_layout);
username = "Your Name";
}
and in another class, i would get that value like this;
String var;
var = Login.username;
but as i've read, this is not the best practice. Sometimes it just sufficient.
i have this problem, i have
private ArrayList<CustomItem> items;
private ArrayAdapter<CustomItem> arrayAdapter;
i show the data present in items, this data i see in listview, now i want to update data and see this new data
if (!items.isEmpty()) {
items.clear(); // i clear all data
arrayAdapter.notifyDataSetChanged(); // first change
items = getNewData();// insert new data and work well
arrayAdapter.notifyDataSetChanged(); // second change
}
in the first change i see the data are cleaned, but in second change i don't see the new data in listview, i check and the item don't empty
i don't know where is the error, can you help me?
best regads
Antonio
This is how I update the Adapter with new data:
if (arrayAdapter == null) {
arrayAdapter = new CustomArrayAdapter(getActivity(), data);
listview.setAdapter(userAutoCompleteAdapter);
} else {
arrayAdapter.clear();
arrayAdapter.addAll(newData);
arrayAdapter.notifyDataSetChanged();
}
Assuming the getNewData() function returns ArrayList<CustomItem>, can you change the line:
items=getNewData();
to
items.addAll(getNewData());
and see if that works?
The ArrayList you created in Activity class is an reference variable, which is holding the same reference to the ArrayList in your Adapter class by passing through the constructor (when you initialize the Adapter object).
However, by executing items = getNewData(), you're assigning a new reference to the items in your Activity class, the reference in your Adapter class remains the same, thus you see no changes on the screen.
It's like this:
personA: the ArrayList object in Activity class
personB: the ArrayList object in Adapter class
PersonA and personB they are both holding a map of USA (separately), and the screen shows personB's map. Then someone replaces the map of personA with another coutry's map. Guess what, the screen still shows USA map.
Instead of changing the reference of items, you should use add(), remove(), clear() or addAll() to modify the items's data then call notifyDataSetChanged().
In my android application I want to be able to add a string value to a static arraylist I have declared on my main android activity. The logic goes like this:
1) When you click a button and an activity starts. On the oncreate method I want to save the name of the class that is the current activity to a string value. For example:
String className = "com.lunchlist.demo";
After this value is assigned I want to immediately add this string value to a Static ArrayList I have declared in my main android activity (meaning first android activity that starts) After adding the value
I did something like this:
static String List<String> members = new ArrayList<String>();
This is declared in my main activity. Now when I click a button to start another activity I use this to add the string classname for that current activity to my arraylist in my oncreate method:
String className = "com.lunchlist.demo"
members.add(className);
My question is now, would this add the string value to my arraylist and save it for later use? For example If I click three different buttons this will add three different className values to the arraylist. Would this then store a string value that would hold three different string values for my members arraylist? How would I check each item in my arraylist to see if the values are being added when a new activity is started?
I'm asking this because I will need to retrieve this and store these values using shared preferences and later retrieve them and starting an intent using the string value which is the class to start the activity. I got the activity to start with a string value of a class name I'm just having trouble storing them.
Answering to all of your questions:
would this add the string value to my arraylist and save it for later
use?
Yes. Your code seems perfect to do it with no problems.
For example If I click three different buttons this will add three
different className values to the arraylist. Would this then store a
string value that would hold three different string values for my
members arraylist?
If you tell to your button's onClickListener to add a string to the members ArrayList then it will be done and no matter if you already had previously added that member to the ArrayList because array lists don't care if there is duplicated data or not.
How would I check each item in my arraylist to see if the values are
being added when a new activity is started?
You have to iterate your array list with a for or a for-each cicle and then print that member name as a log entry.
For-each cicle
for (String member : members){
Log.i("Member name: ", member);
}
Simple For cicle
int listSize = members.size();
for (int i = 0; i<listSize; i++){
Log.i("Member name: ", members.get(i));
}
If you try to print/ log a value which index is out of range, i.e., i < 0 || i >= listSize then a IndexOutOfBoundsException will be thrown and crash your app.
Iterate using For-Each introduced in Java from Java 1.5 :
for (String s : members){
Log.d("My array list content: ", s);
}
See this link for further details:
http://docs.oracle.com/javase/1.5.0/docs/guide/language/foreach.html
Try this:)
We can implement by these two way
foreach
for loop
String type arraylist
ArrayList<String> limits = new ArrayList<String>(); // String arrayList
Using foreach
for (String str_Agil : limits) // using foreach
{
Log.e("Agil_Limits - " , str_Agil);
}
Using forloop
for(int agil=0; agil<=limits.size(); agil++) // using for loop
{
Log.e("Agil_Limits - " , limits.get(agil).toString());
}