Listview custom adapter notify parent activity - android

I have created a listview that sits inside a larger activity (the list view fills half the screen, with inputs/buttons above it). This listview uses a custom adapter to draw the row views.
Inside the row view is a button, which when clicked/tapped i want the activity to handle, and not the adapter. However i don't know how inside the adapter class, i can tell it to use the activity. Since it's OOP, im assuming i have to pass some sort of reference to the activity when setting up the adapter (rather than hardcoding the parent activity into the adapter).
I had a simlier issue with sharing a dataset between the activity and adapter (i wanted the adapter to use an arraylist from the activity), however i couldn't solve that one either so i ended up passing the arraylist through as a duplicate into the adapter. So i would hope working out the click listener, will also mean i can get rid of that duplicate data having to be created?
All the code is pretty simple, but here's a rough outline:
Setting the list adapter & declaring dataset (this is the activity dataset, not the adapter)
numbersListAdapter = new NumberListAdapter(this);
numbersList.setAdapter(numbersListAdapter);
this.selectedContacts = new HashMap<Long, HashMap<String, String>>();
Adding entry into activity data set and adding to the adapter dataset
HashMap<String, String> tempa = new HashMap<String,String>();
tempa.put("name", name);
tempa.put("number", number);
this.selectedContacts.put(contactID, tempa);
this.numbersListAdapter.addEntry(contactID, tempa);
The adapters add entry
public void addEntry(Long id, HashMap<String, String> entry) {
entry.put("contactID", id.toString());
this.selectedNumbers.add(entry);
this.notifyDataSetChanged();
}
The adapters constructor
public NumberListAdapter(Context context) {
selectedNumbers = new ArrayList<HashMap<String, String>>();
mInflater = LayoutInflater.from(context);
}
Please note: this is my first attempt at this stuff. I've never done android, java and very, very little OO programming. So i already know the code is most likely inefficient and quite terrible. But i've got to learn somehow :)
EDIT
Ok so i realised ive been a little silly and i just needed to use the context passed into the adapter to reference the parent activity. However i still ain't getting it. Heres the code:
The constructor for the adapter
numbersListAdapter = new NumberListAdapter(this);
The variable declaration and constructor method
public class NumberListAdapter extends BaseAdapter {
private LayoutInflater mInflater;
private ArrayList<HashMap<String, String>> selectedNumbers;
private Context parentActivity;
public NumberListAdapter(Context context) {
parentActivity = (Context) context;
selectedNumbers = new ArrayList<HashMap<String, String>>();
mInflater = LayoutInflater.from(context);
}
The listener
Button theBtn = (Button)rowView.findViewById(R.id.actionRowBtn);
theBtn.setOnClickListener(this.parentActivity);
I get two messages from eclipse, the first occurs when i comment out the listener and i get
The value of the field NumberListAdapter.parentActivity is not used
Once i add the listener in i get
The method setOnClickListener(View.OnClickListener) in the type View is not applicable for the arguments (Context)
Obviously im doing something wrong. Probably quite a silly mistake again too

If you need to get callback when row of the listview is clicked you can use
numbersListAdapter.setOnitemitemClickLiistener
But if you need a button inside each row to be clicked you will have to override the
getView function of your adapter and then set the onclicklistener of the button individually
Edit:
Typecast the Context to Activity
theBtn.setOnClickListener((YourActivity)this.parentActivity);

Related

Replace ArrayAdapter's dataset

In Android, you can provide an ArrayList when creating an ArrayAdapter for a ListView. I need to update a number of items in the ArrayList.
The ususal way is to just call notifyDatasetChanged. What I prefer to do is reload the entire data into a new ArrayList from my database and then apply this new ArrayList to the existing ArrayAdapter but without creating a new adapter. Creating a new adapter will cause the ListView to go blank and start with position zero. This would also be obvious if the user were scrolling and I suddenly recreated a new adapter.
Is it possible to apply a completely new ArrayList to the existing adapter? The primary reason I want to do this is because it is very fast to just reload a new ArrayList with all the data than having to go through an existing ArrayList and inserting, deleting or updating existing items.
1) First of all. You need to use custom ArrayAdapter (or SimpleAdapter or RecycleViewAdapter)
2) Than create function in your custom adapter :
// Initialize your list;
private ArrayList<Model> arrayList;
.....
//Create constructor and past starting ArrayList
public MyAdapter (ArrayList<Model> array) {
this.arrayList = array;
}
......
public void updateMyData (ArrayList array) {
clear();
// Or you can use arrayList.addAll(array); - just add new items
this.arrayList = array;
notifyDataSetChange();
}
.....
3) In your Activity (or where you initialize adapter)
just use code like this:
MyAdapter myAdapter = new MyAdapter(startArratListData);
// And Than for updating data:
myAdapter.updateMyData(newArrayListData);

How can i hide a listview item in android?

Hi friends i have a listview and the contents are fetched from a webservice call. In that webservice call, there are fields like
"OGType": "ORG" and "OGType": "GROUP"
If click a button, the listview must shows the item having "OGType": "ORG", and hide the item having "OGType": "GROUP". Hope you understand what i meant. Please anyone help me for that. Thanks in Advance.
Try to set new data (only with ORG) to adapter and then call
adapter.notifyDataSetChanged();
You can do it in your getView Method in your Adapter Class. That's the header
public View getView(int pos, View convertView, ViewGroup, parent)
There you can properly hide the element(s) you want, you know, using the method setVisibility()
For more help you can take a look here
You can create a custom adapter and pass data to it in the form of Array or ArrayList (ArrayList is better when dealing with Custom Adapters). Whenever you need to add or remove the data from ListView, just add or remove the item to or from you ArrayList and call notifyDataSetChanged() on your custom adapter and it will update the ListView automatically.
In your case, whenever you click a button, edit you ArrayList and call your custom adapter's method called notifyDataSetChanged() and that's it. You'll see every time you call this method ListView will refresh itself if you have made any changes to the data. Hope it helps.
NOTE - CUSTOM ADAPTER IS NOT COMPULSORY. ANY ADAPTER CAN BE USED e.g SimpleAdapter, ArrayAdapter etc.
You can use a visible list and filters lists. You should use "visible" for complete the BaseAdpter as always, then, you can change the pointer of visible to other list (all, filter...)
Don't worry by the memory, are pointers, you only have each element only once.
public class MyAdapter extends BaseAdapter {
private ArrayList<MyItem> visible;
private ArrayList<MyItem> all;
private ArrayList<MyItem> filter;
public MyAdapter(ArrayList<MyItem> items) {
all = items;
visible = all; //Set all as visible
filter = new ArrayList<Item>();
for (Item i : items)
if (i.getType().equals("ORG"))
filter.add(i);
}
//Complete adapter using "visible"
public void showOnlyOrg() {
visible = filter;
notifydatasetchanged();
}
}
The non hackish way will be to remove the items from your Collection which you use to generate the listview and then call notifyDataSetChanged();

Android ListView adapter data, mantaining consistency

When you create a custom adapter extending ArrayAdapter<T>, it has usually the form:
public class ListAdapter extends ArrayAdapter<Item> {
private List<Item> mData;
public ListAdapter(Context context, int resource, List<Item> data) {
super(context, resource, data);
mData = data;
}
}
The data is initially saved in a private member mData, but also the ArrayAdapter saves the data in its own member mObjects. I am pretty sure those are not actual copies, but references to the same list.
Now, and this is my question, if during the ListView processing, for some reason, you have to replace your own list with a fresh new List, I think you should also do:
mData = new List<Item>();
super.clear();
super.addAll(mData);
otherwise there will be no consistency in ListView, and methods like getFilter().filter() will not work.
Am I correct?
I think, when you say mData = data; it only copies pointer of the data array, because when you execute that;
ListAdapter adapter = new ListAdapter(context, resource, data);
data.clear();
adapter.notifyDataSetChanged();
it changes list. So it keeps pointer of your source array,
Second, I think (not sure) you cannot use filter function of adapter, at least I couldn't use and write my own filter function. I filter elements from sqlite(I take my elements from database). and use notifyDataSetChanged function of adapter.
You are right. Your ListAdapter doesn't make a deep copy of the provided list of Items. This means that changing an Item instance 'outside' the ListAdapter will put the ListAdapter in an invalid state.
However, you can 'fix' this by calling notifyDataSetChanged on the ListAdapter.
List<Item> itemList = ....
....
....
ListAdapter adapter = new ListAdapter(this, R.layout.somelayout, itemList);
....
Now, if you change an item 'outside' the ListAdapter, you can still make your ListAdapter be in sync with the change:
itemList.get(idx).changeSomethingInItem("Hello"); // Changes the Item at index 'idx'.
adapter.notifyDataSetChanged(); // Notify adapter about this change.
you really needn't pretty sure whether it actual copies or not ,just extend BaseAdapter

Strange behavior with ArrayAdapters in Android

I've been playing around with ArrayAdapters and I've reached a point where I'm getting different results from two almost identical ArrayLists + ArrayAdapter combinations.
The first one:
An ArrayList of 'Restaurant' objects, an ArrayAdapter that uses this ArrayList and a ListView that binds this ArrayAdapter.
private ArrayList<Restaurant> model = new ArrayList<Restaurant>();
private ArrayAdapter<Restaurant> restaurantAdapter = null;
...
public void onCreate(Bundle savedInstanceState){
...
restaurantAdapter = ArrayAdapter<Restaurant>(this, android.R.layout.simple_list_item_1, model);
...
listView.setAdapter(restaurantAdapter);
...
}
The second one:
An ArrayList of String objects, an ArrayAdapter that uses this ArrayList and a AutoCompleteTextView that binds this ArrayAdatper.
private ArrayList<String> prevAddressList = new ArrayList<String>();
private ArrayAdapter<String> addListAdapter = null;
...
public void onCreate(Bundle savedInstanceState){
...
addListAdapter = ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, prevAdddressList);
...
autoCompleteField.setAdapter(addListAdapter);
...
}
I have a save button, on click, I'm creating a restaurant object with a name and an address and adding it to the first adapter, additionally, I want to create a list of previously used address so they are "auto completed" next time they are typing it, so I'm taking the text, and adding it to the second adapter.
...onSave = new View.OnClickListener(){
...
restaurantAdapter.add(r); //r is a Restaurant object.
addListAdapter.add(autoCompleteField.getText().toString());
...
}
Now, everything is working properly. I get the Restaurants displayed in a ListView. The AutoComplete is working as expected.... but I noticed something when I was checking the values while debugging:
The actual ArrayLists, model (Restaurant) is getting updated after adding an object to the adapter , but prevAddressList (String) is not.
Unless, I set the AutoCompleteTextField empty.... then, the prevAddressList gets updated after adding something to the second adapter.
Already tried using notifyDataSetChanged(), but it makes no difference (and it is set to true on every adapter by default anyway).
Other behavior that differs between the two adapters is that in the first one (Restaurant), values are going to the mObjects field, while in the second one (String) they are going to mOriginalValues instead.
I'm completely stomped. The only difference between those two adapters is that one is type "Restaurant" and the other is type "String".
Any ideas? Maybe I'm missing something very obvious? Let me know if you need the full code.
thanks
Instead of adding it to the adapter, try adding the object to your list and then calling notifyDataSetChanged on your adapter. The adapter should pick up your changes and your list of course will have the object you just added.
For anyone coming here from google:
Unable to modify ArrayAdapter in ListView: UnsupportedOperationException
This might explain the behavior, although I have to test it myself.

Android: How to add data to an empty listView

I have a problem with listView, I used ArrayList to store data, and a customized Adapter. But, when I remove all the data, and add one item again, it does not display anything in this list. What happens to my List, can anyone help me?
static ArrayList<String> chattingListData=new ArrayList<String>();
static IconicAdapter chattingListDataAdapter;
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
chattingListDataAdapter=new IconicAdapter(this);
setListAdapter(chattingListDataAdapter);
registerForContextMenu(this.getListView());
}
class IconicAdapter extends ArrayAdapter {
Activity context;
IconicAdapter(Activity context) {
super(context, R.layout.chatting_list, chattingListData);
this.context=context;
}
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater=context.getLayoutInflater();
View row=inflater.inflate(R.layout.chatting_list, null);
TextView label=(TextView)row.findViewById(R.id.chattinglist_userName);
label.setText(chattingListData.get(position));
return(row);
}
}
I use static ArrayList to modify data from outside, when I start the ListView activity and add data, it's Ok, but when I remove all data, I can not add anymore to the data list. Please help me.
I use static ArrayList to modify data from outside
Don't do that.
Step #1: Use a non-static ArrayList data member as the basis for your ArrayAdapter.
Step #2: Expose methods on your activity that adds and removes items via the add(), insert(), and remove() methods on ArrayAdapter. By using these methods, your ListView will automatically update when you make the changes.
Step #3: Use the methods you wrote in Step #2 to modify the contents of your ListView, by whoever is doing this (not shown in your code).
You can also use the Adapter's notifyDataSetChanged() method, in order to force it to refresh.

Categories

Resources