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().
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.
I have a Course class which has a method to add Items, which can be a note, an assignment, a URL, or just a generic item. All Items are kept in an ArrayList which the Course that created the list keeps up with. My question is from an item inside this ArrayList, how do I get the printLogger that I have attached to the course object in order to attach it to an item when the Item is created?
this from my Course:
public class Course {
private ArrayList<Item> items;
public PrintLogger p1 = null;
public Course(String code, String name) {
this.code = code;
this.name = name;
items = new ArrayList<>();
}
void add(Item item) {
items.add(item);
if (hasPrintLogger() == true) {
log(PrintLogger.INFORMATIONAL, "Adding " + item.toString());
}
}
And Im trying to have in the code that the assignment constructor runs a way to attach the same printLogger that is already on the course.
You could store a reference to the proper Course object in each of the items in the List.
You could also wrap the ArrayList class in your own class and add a field that points to the Course it belongs to if you need it to be a relationship between the List and the Course instead of between the items in the List and the Course.
You could also search each Course object in your system and check if it contains the List in question. However, this solution would scale badly.
For the following class I want to access an object if the name equals to something, let's say "you". Otherwise I want to create it.
I want to check if an object exists that has the name as 'you' and then add entries to the ArrayList contInstances. If such an instance doesn't already exist I want to create it. Next time I might have to use the same object so that I can add some more entries to the ArrayList.
public class Values {
String name;
ArrayList<anotherClass> classInstances = new ArrayList<anotherClass>();
}
This happens to be in a loop. How can I do that?
Edit: I'll quote an example here:
if (an object exists that contains field 'name' == 'YOU'){
add entries to the array list directly using the available object
}
else {
create a new object and set the 'name' = 'YOU';
add entries to the array list;
}
It sounds kind of like you want to have a cache by name. Instead of an ArrayList, consider using a Map<String, AnotherClass> to keep track of Name->Object mappings.
You can then use this approach:
Map<String, AnotherClass> instances = new LinkedHashMap<String, AnotherClass>();
for (...) {
String name = getNextName();
AnotherClass instance = instances.get(name);
if (instance == null) {
instance = makeInstance(name);
instances.put(name, instance);
}
useInstance(name, instance);
}
After that loop is finished, if you still want a List<AnotherClass>, you can use return new ArrayList<AnotherClass>(instances.values());
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
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());
}