extends BaseAdapter results are overwrite previous ArrayList Items - android

i have a DateApapter class like this..
public class DateAdapter extends BaseAdapter
{
...
}
i call this DateApapter in 12 different places from my "mainActivity" by using constructor and store this result in a DateApapter object "mDefaultAdapter " like this..
mDefaultAdapter = new DateAdapter(this,days,sysDate,disablePastDays, selectedDateTypeDf);
and stored this various results of mDefaultAdapter in ArrayList like this..
ArrayList<DateAdapter> mDefaultAdapterList = new ArrayList<DateAdapter>();
mDefaultAdapterList.add(mDefaultAdapter);
now coming to the problem,
In my 1st call DateAdapter constructor , it returns January month
details and I add this result(January) to ArrayList its works fine.
Now the ArrayList has one Item, that is January details.
but when i call 2nd result(February) to arrayList its overwrite 1st
result also. Now the ArrayList has two Items, both of the items
are February details.
That means Last result of DateAdapter is filled the whole ArrayList.
Finally i got December details only from ArrayList.
Why DateAdapter results are overwrite in previous ArrayList Items?
I am not using any Static variables or methods in whole program.
Please help me to fix this problem. Thanks..

I'm not really sure what's happening with your adapter. Maybe you're using the same ArrayList object with all the adapters.
But I think you should reconsider your approach.
Here's what I would do.
1- Store the calendar events in an SQLite database.
2- In your FragmentPagerAdapter, pass the position to your Calendar Fragment.
3- In your Calendar Fragment, retrieve the position ( 0 : January - 11 : December) and query your database to retrieve the events.

It was my mistake.. The problem is Illegal object reference overwrite my previous ArrayList Items.
I saved myself by making a separate object for Date Adapter.

Related

Adapter stuck to an old ArrayList

I am performing some reordering in a couple of array list, I have an adapter called
adapterMeasureEvi
which is set to a static ArrayList called measureEviArray from DataIpat class.
When debugging I can see that the static list is been assigned properly and it follows a notification to the adapter that the list has changed.
DataIpat.measureEviArray = (ArrayList<MeasureEvi>)measureEviArray.clone();
adapterMeasureEvi.notifyDataSetChanged();
Problem is, when getView() method gets called the first item it brings is from the old list, when I look up into the objects their indexes have changed that means I have updated the attributes but why is it still stuck on the old list?
/////EDIT////
I just noticed on the constructor of the adapter class that the list is definitely the old one.
public MeasureTableAdapter(Activity context, ArrayList<MeasureEvi> myMeasureEvi) {
super(context, R.layout.adapter_tablamedida_item, myMeasureEvi);
this.context = context;
this.myMeasureEvi = myMeasureEvi;
}
this constructor is called just once when the object is instantiated, so I suppose it means it will be stuck there, how can I update that list?
I think the problem is that when the data change, you recreate the DataIpat.measureEviArray instead of updating it. Hence your adapter will point to the old array, and the DataIpat.measureEviArray points to the newly upldated array. One way to fix your issue is instead of doing this (create a brand new array):
DataIpat.measureEviArray = (ArrayList<MeasureEvi>)measureEviArray.clone();
You should just update the DataIpad.measureEviArray array so that this array contains your new data (e.g. using clear and addAll to basically get the same effect as creating a new ArrayList).
Just stop cloning the list and work over the original worked, weird.
Deleted this,
DataIpat.measureEviArray = (ArrayList<MeasureEvi>)measureEviArray.clone();
not ideal but a workaround

How does an Android adapter decide what to re-render?

Say I have a List<User>. Now I can wrap this list in an ArrayAdapter.
List<User> users = Users.getAll();
ArrayAdapter<User> = new ArrayAdapter<User>(this, android.R.layout.simple_list_item_1, users);
I then bind the adapter to a listview to display the list of Users.
Users.getAll() uses Sugar ORM to query the database and return a list of users. Items can be added to the user list from the activity that displays the user list. I am wondering how do I keep the listview updated.
Option 1
One way is to manually update the users as a I add to the database and then call adapter.notifyDataSetChanged(). This works, but it doesn't feel right because I am maintaining a "fake" list that represents what is in the database.
Option 2
I am wondering how bad is it if I just clear the items in users, update it with the results of a new database query and then call adapter.notifyDataSetChanged()?
Will all the child views be thrown away and be re-rendered? Or does it call the equals() method to see if the models bound to each child is the same and then update only what is new?
Other Info
Since I am using SugarORM, I don't think I can get access to the Cursor to do something more efficient. However if there is a better way to keep the list synced with SugarORM, I am happy to hear that as well.
In answer to your option 2: No, it doesnt call equals, because the adapter works in conjunction with the widget to re-use the views, it doens't create a new view foreach item in the list, it create a view foreach visible item and as you scroll re-uses view that left the screen.
The best option here is to create your own adapter, creating a class extending BaseAdapter and creating your own logic inside it requerying the database and notifying the change to the listview (or gridview)..
On the other hand doing what you said here:
I am wondering how bad is it if I just clear the items in users, update it with the results of a new database query and then call adapter.notifyDataSetChanged()?
isn't bad either.
Create a DAO class that extends Observable, then have your Adapter implement Observer. Now every time you add or remove a SugarRecord, do through the DAO class and whoever is register as the Observer will get notified through the following method:
#Override
public void update(Observable observable, Object o)
You can more about Observable/Observer pattern here. This is just one of the many examples and tutorials out there.

Save ListView content

I have a Google's NavigationDrawer which adds/replaces fragments. One of fragments has a listView filled with custom BaseAdapter by network request (asyncTask, takes times). What i want is to save listView contents somewhere so if user navigates to another fragment through navigationDrawer and then or later navigates back to the fragment containing listView - i want a listView to be populated immediately with saved old content before asyncTask finished loading new content. Minimum API is 10.
What did i try.
onSaveInstanceState - serialize Parcelable ArrayList<CustomObject>. Somehow i didn't get it working. Also, that isn't solving my problem however, because onSaveInstaceState doesn't triggers on navigating through navigationDrawer.
Setting new fragment's InitialState(setInitialSavedState) then saving(saveFragmentInstanceSate)/loading it. That works for simple Views like EditTexts and TextView, but didn't get it working for the listView.
What is a best way to save listView contents? Please help me.
First get all items of list view.
CustomListViewAdapter listadapter = (CustomListViewAdapter) listview.getAdapter();
ArrayList<CustomObject> object=new ArrayList<CustomObject>();
for(int position=0;position<listadapter.getCount();position++)
object.add(videoadapter.getItem(position));
Now Use the object to store the items of the listview
Then use shared preferences to save the object.
Android ArrayList of custom objects - Save to SharedPreferences - Serializable?
The proper way to do this is to save your network query results in a database (sqlite), and use data from that db to display items in your list (CursorAdapter works best for this).
These tutorials nicely explain how to make your own Content Provider using Sqlite, and use a CursorAdapter to display your data on a list.
http://docs.xamarin.com/guides/android/user_interface/working_with_listviews_and_adapters/part_4_-_using_cursoradapters/
http://www.vogella.com/tutorials/AndroidSQLite/article.html
I found a good way.
String list_items = ""; // all your items are here, but separate it with a comma (,)
String[] list = list_items.separate(",");
And save the list_items in a shared preference. To retrieve just use getString() and use the code above

How do I refresh a ListFragment efficiently?

I have a ListFragment with an ArrayAdapter to display a list of objects. I want to refresh the ListFragment's contents. The items themselves change their text a little and also change their order. I have over one hundred items and the only way I've found to do this is clear the list and re-add them, but this feels ineffcient.
For example:
ListFragment display unordered:
Object A
Object D
Object F
Object B
Object E
Object C
ListFragment display ordered:
Object A
Object B
Object C
Object D
Object E
Object F
I set up my ArrayAdapter like this:
mAdapter = new ArrayAdapter<Store>(mContext,
android.R.layout.simple_list_item_1,
OtherClass.list);
mAdapter.setNotifyOnChange(true);
setListAdapter(mAdapter);
"OtherClass" is:
public class OtherClass extends Object {
public ListArray<Object> list;
...
}
The code in question:
mAdapter.clear();
for (Object o : list) {
mAdapter.add(store);
}
I've already read a lot of answers about how it works and how to use mAdapter.notifyDataSetChanged() but none of them solve my problem or answer my question. Is the only way to refresh the list done by adding/removing something from the list?
Whatever you are attaching your adapter to, like say a listView, it can be unattached by setting it to null or to something else.
So instead of the code in question:
1). Sort the list.
2). Then call:
mAdapter = new ArrayAdapter<Store>(mContext,
android.R.layout.simple_list_item_1,
sortedList);
setListAdapter(mAdapter);
I hope this helps, as your question is still a little unclear. Generally if you have a list generated by an adapter, you dont want to be manually digging through the list as it is auto generated for you and doing so takes away from its ease of use.
OP here. My solution is to stick to my original method which is: If you want to modify the list slightly, but have the list refresh so it's updated and also keep the scroll position then the only way to do this is to clear() and refill the list.
Source: http://vikinghammer.com/2011/06/17/android-listview-maintain-your-scroll-position-when-you-refresh/

Getting all of the items from an ArrayAdapter

I have a ListFragment backed by an ArrayAdapter that gets populated by a Loader. When the user clicks on one of the items, I want to pass a reference to the selected item, as well as the rest of the list items to another fragment. My question is how should I get all of the items from the adapter? Here are the possibilities that I see:
1. Keep a reference to the backing List
Create the adapter like so:
List<DomainObject> items = new ArrayList<DomainObject>();
listAdapter = new ArrayAdapter<DomainObject>(getActivity(), R.layout.mine, items);
and then simply pass items or a copy of it to the next activity.
The downside I see of this is that I'm relying on the undocumented fact that the same list that I pass to the constructor contains the items later on.
2. Iterate through the adapter
When an item is clicked, iterate through the adapter and build up the list. This seems like an unnecessary amount of work. The items are contained in a List in the adapter and I'm manually copying each item to a new list.
3. Keep a separate list of items when adding to adapter
Before adding an item to the adapter, add it to a separate list that I maintain in the fragment. This is also wasteful as the list of items is copied in the ArrayAdapter and the fragment.
I'm a little late to the game, but I've run up against a similar issue.
One way to deal with #1 would be to maintain the reference to the list within a subclass of ArrayAdapter, so that your reuse is controlled by the adapter object.
Something like:
public class DomainAdapter extends ArrayAdapter<DomainObject> {
private final List<DomainObject> items;
public DomainAdapter(Context context, List<DomainObject> items) {
super(context, R.layout.mine, items);
this.items = items;
}
public List<DomainObject> getItems() {
return items;
}
}
The solution that I've gone with in the meantime is just to not use ArrayAdapter. In cases where you're fighting against this API, it seems like it's better just to use the less fully-featured (and complex) BaseAdapter. You can read more about the decision to go with BaseAdapter instead of ArrayAdapter in this article: Android Adapter Good Practices.
A quick test says that method 1 works. It seems the quickest and cleanest, but since it is undocumented you may want to test it across the intended platforms and whenever they update in case the underlying structure of ArrayAdapter changes.
I am using compile SDK version 22 and min SDK Version 10.
The best method is to "keep a reference to the List" BUT not passing "items" variable/parameter to the Constructor:
List<DomainObject> items = new ArrayList<DomainObject>();
listAdapter = new ArrayAdapter<DomainObject>(getActivity(), R.layout.mine);
In this way you only instantiate the ArrayList as an empty array and you will have to manage YOUR list by yourself.
I think first method is best way to do this.
I dont think, Data would be original for the Another Activity. because, You would pass items through bundle, so the object is written on bundle first and then in next Activity we read from bundle.
However, if you are using some other way to pass the list, use list.clone() to create new Object, instead of passing original one.

Categories

Resources