java.lang.ArrayIndexOutOfBoundsException after creating list view with >100 items - java

After creating a list view containing over 100 items (111 to be precise) and deploying the app, it runs as expected but as soon as I scroll through my list, the app crashes and an ArrayIndexOutOfBoundsException is returned. I really don't understand why the length and index are returning '19'. Does anyone know why 19 is shown? What needs to be done to resolve this issue?
java.lang.ArrayIndexOutOfBoundsException: length=19; index=19
at com.helloapps.helloworldapp.adapters.OrangeListAdapter.getPositionForSection(OrangeListAdapter.java:160)
XML
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:choiceMode="singleChoice"
android:fastScrollEnabled="true"
android:scrollbarStyle="outsideInset"/>
Java
public class OrangeListAdapter extends BaseAdapter implements Filterable, SectionIndexer {
private List<Orange> mData;
private List<Orange> mFilteredData;
private LayoutInflater mInflater;
private ItemFilter mFilter;
private Object[] mSections;
private int[] mSectionsIndexedByPosition;
private int[] mPositionsIndexedBySection;
public OrangeListAdapter (List<Orange> data, Context context) {
mData = data;
mFilteredData = new ArrayList(mData);
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
setupSections();
}
#Override
public int getCount() {
return mFilteredData.size();
}
#Override
public Orange getItem(int position) {
return mFilteredData.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.list_item_dualline, parent, false);
holder = new ViewHolder();
holder.title = (TextView) convertView.findViewById(R.id.item_name);
holder.description = (TextView) convertView.findViewById(R.id.item_description);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
Orange orange = getItem(position);
holder.title.setText(orange.getName());
holder.description.setText(orange.getDescrption());
if (orange.isSelected()) {
convertView.setBackgroundColor(Color.parseColor("#FF6600"));
holder.title.setTextColor(Color.parseColor("#FFFFFF"));
holder.description.setTextColor(Color.parseColor("#FFFFFF"));
} else {
convertView.setBackgroundColor(Color.TRANSPARENT);
holder.title.setTextColor(Color.parseColor("#FFFFFF"));
holder.description.setTextColor(Color.parseColor("#B5B5B5"));
}
holder.title.setText(mFilteredData.get(position).getStation());
holder.description.setText(mFilteredData.get(position).getZone());
return convertView;
}
#Override
public Filter getFilter() {
if (mFilter == null) {
mFilter = new ItemFilter();
}
return mFilter;
}
/**
* View holder
*/
static class ViewHolder {
private TextView title;
private TextView description;
}
private class ItemFilter extends Filter {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if (TextUtils.isEmpty(constraint)) {
results.count = mData.size();
results.values = new ArrayList(mData);
} else {
//Create a new list to filter on
List<Orange> resultList = new ArrayList<Orange>();
for (Orange str : mData) {
if (str.getStation().toLowerCase().contains(constraint.toString().toLowerCase())) {
resultList.add(str);
}
}
results.count = resultList.size();
results.values = resultList;
}
return results;
}
/**
* Runs on ui thread
* #param constraint the constraint used for the result
* #param results the results to display
*/
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
if (results.count == 0) {
mFilteredData.clear();
notifyDataSetInvalidated();
} else {
mFilteredData = (ArrayList<Orange>)results.values;
notifyDataSetChanged();
}
setupSections();
}
}
#Override
public int getPositionForSection(int section) {
return mPositionsIndexedBySection[section];
}
#Override
public int getSectionForPosition(int position) {
return mSectionsIndexedByPosition[position];
}
#Override
public Object[] getSections() {
return mSections;
}
private void setupSections() {
String initial = "\0";
List<String> sections = new ArrayList<String>();
mSectionsIndexedByPosition = new int[mFilteredData.size()];
mPositionsIndexedBySection = new int[mFilteredData.size()];
int section = 0;
for (int pos = 0; pos < mFilteredData.size(); pos++) {
Orange orange = mFilteredData.get(pos);
if (initial.charAt(0) != orange.getName().charAt(0)) {
initial = orange.getName().substring(0, 1);
section = sections.size();
sections.add(initial);
mPositionsIndexedBySection[section] = pos;
mSectionsIndexedByPosition[pos] = section;
} else {
mSectionsIndexedByPosition[pos] = section;
}
}
mSections = sections.toArray();
mPositionsIndexedBySection = Arrays.copyOf(mPositionsIndexedBySection, mSections.length);
}
}

Your array declared to have only 19 places, that means you can access maximum index of 18 as in arrays index starts with 0, but in above code you are accessing 19th index, then it will complain that your index is out of bound that is 18.
This line looks problematic to me:
mPositionsIndexedBySection = Arrays.copyOf(mPositionsIndexedBySection, mSections.length);
**To solve the problem**: Ensure that you are putting things in an array based on its size. If arrays has size n i.e. 19 then you are supposed to put element only till n-1 index i.e. 18.

Fast Scroller only read your sections from SectionIndexer.getSections() once, and will not change afterwards.
So the problem seems to occur when your first list contains over 19 sections, and afterwards reload a list where you want to reduce the number of sections to less than 19, which reduce the size of mPositionsIndexedBySection as well.
Because the Fast Scroller still remember the old sections, and try to get the position of the 19th section, error occurs.
To solve the problem, have fixed number of sections containing all posible section, only change the mPositionsIndexedBySection and mSectionsIndexedByPosition on data change.
Edit:
Check the link below on how to properly implements SectionIndexer
http://androidopentutorials.com/android-listview-fastscroll/
http://responsiveandroid.com/2013/04/13/android-sectionindexer-with-alphabet.html

Related

NotifyDataSetChanged() isn't showing the updated list

I get correct objects in filtered list in publishResults() function but the filtered list is not displayed on the screen after filtering.
Following is the code for CityAdapter class inhereted from ArrayAdapter class.
IT seems like notifyDataSetChanged() isn't working?
Please inform why list is not displaying.What's wrong in the code.
import...
public class CityListAdapter extends ArrayAdapter<City> implements Filterable {
private ArrayList<City> cities;
private ArrayList<City> filtered_list;
public CityListAdapter(Context context, int resource, ArrayList<City>cities) {
super(context, resource, cities);
this.cities = cities;
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, ViewGroup parent) {
Holder holder = new Holder();
if(convertView == null) {
LayoutInflater inflator = LayoutInflater.from(getContext());
convertView = inflator.inflate(R.layout.adapter_view,parent,false);
holder.box = (CheckBox) convertView.findViewById(R.id.checkBox);
holder.name = (TextView) convertView.findViewById(R.id.textView);
convertView.setTag(holder);
}
else {
holder = (Holder) convertView.getTag();
}
City city = getItem(position) ;
holder.name.setText(city.getName());
return convertView;
}
private class Holder {
CheckBox box;
TextView name;
}
#NonNull
#Override
public Filter getFilter() {
return new CityFilter();
}
private class CityFilter extends Filter {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
filtered_list = new ArrayList<>();
if (constraint != null && constraint.length()!= 0) {
for (int i = 0; i < cities.size(); i++) {
if (cities.get(i).getName().contains(constraint)) {
filtered_list.add(cities.get(i));
showMessage(cities.get(i).getName() + "added");
}
}
}
results.values = filtered_list;
results.count = filtered_list.size();
return results;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
filtered_list = (ArrayList<City>) results.values;
int size =filtered_list.size();
showMessage("Data set changed"+String.format("%d", size));
notifyDataSetChanged();
}
}
public void showMessage(String message) {
Toast toast = Toast.makeText(getContext(), message, Toast.LENGTH_LONG);
toast.show();
}
}
You need to have a full list of items in the very beginning (i.e. in the constructor) assigned to the filtered list; so that they can have the entire list when there is no filtering of results (empty search) and that occurs whenever you instantiate the adapter.
public CityListAdapter(Context context, int resource, ArrayList<City>cities) {
super(context, resource, cities);
this.cities = cities;
this.filtered_list = cities; // <<<<< Change here
}
Side Note
Also override getCount() to avoid IndexOutOfBoundsException when reaching the end of the list on scroll whenever the original list size not equal to the filtered list size.
As the original list is cities, when you make filtering, its size will shrink down, so you need only to get the filtered list size not the original list size to avoid IndexOutOfBoundsException.
So add this to the adapter:
#Override
public int getCount() {
return filtered_list.size();
}

Android ListView not updating with filter

I've got a list view that I'm trying to filter depending on which button the user clicks.
The filter is working, I'm getting the results I expect inside the publishResults method but the list is then never updating. I've got notifyDataSetChanged() but this doesn't seem to do anything.
Min SDK level 21 and compiled 26.
mAdapter = new QuakeAdapter(this, new ArrayList<QuakeItem>());
ListView earthquakeListView = (ListView) findViewById(R.id.list);
earthquakeListView.setAdapter(mAdapter);
Setting the filter
public void filterList(View view){
mAdapter.resetData();
Log.d(LOG_TAG, "FILTER Tsunami" + mAdapter.quakeList);
mAdapter.getFilter().filter("tsunamiOnly");
}
public void filterListEarthquake(View view){
mAdapter.resetData();
Log.d(LOG_TAG, "FILTER earthquake" + mAdapter.quakeList);
mAdapter.getFilter().filter("earthquakeOnly");
}
Custom Adapter
public class QuakeAdapter extends ArrayAdapter<QuakeItem> implements Filterable {
public ArrayList<QuakeItem> origQuakeList;
public ArrayList<QuakeItem> quakeList;
private Filter quakeFilter;
private Context mContext;
public static final String LOG_TAG = QuakeAdapter.class.getName();
public QuakeAdapter(Activity context, ArrayList<QuakeItem> quakeItems){
super(context, 0, quakeItems);
origQuakeList = quakeItems;
quakeList = quakeItems;
mContext = context;
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent){
View listItemView = convertView;
if(listItemView == null){
listItemView = LayoutInflater.from(getContext()).inflate(
R.layout.list_item, parent, false
);
}
QuakeItem currentItem = getItem(position);
double mag = currentItem.getMagnitude();
TextView magnitudeTextView = (TextView) listItemView.findViewById(R.id.magnitudeView);
magnitudeTextView.setText(formatMagnitude(mag));
GradientDrawable magnitudeCircle = (GradientDrawable) magnitudeTextView.getBackground();
int magnitudeColour = getMagnitudeColour(mag);
magnitudeCircle.setColor(magnitudeColour);
int isTsunami = currentItem.getTsunami();
int strokeColor = magnitudeColour;
if (isTsunami==1){
strokeColor = Color.BLACK;
}
magnitudeCircle.setStroke(6, strokeColor);
String[] formattedString = formatLocation(currentItem.getLocation());
TextView locationOffsetTextView = (TextView) listItemView.findViewById(R.id.locationOffsetView);
locationOffsetTextView.setText(formattedString[0]);
TextView locationTextView = (TextView) listItemView.findViewById(R.id.locationView);
locationTextView.setText(formattedString[1]);
Long timeInMilliseconds = currentItem.getTime();
TextView timeTextView = (TextView) listItemView.findViewById(R.id.timeView);
timeTextView.setText(formatTime(timeInMilliseconds));
TextView dateTextView = (TextView) listItemView.findViewById(R.id.dateView);
dateTextView.setText(formatDate(timeInMilliseconds));
return listItemView;
}
public void resetData() {
quakeList = origQuakeList;
}
#Override
public Filter getFilter() {
if (quakeFilter == null)
quakeFilter = new QuakeFilter();
return quakeFilter;
}
private class QuakeFilter extends Filter{
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if (constraint == null || constraint.length() == 0){
// No filter found, return original list
results.values = origQuakeList;
results.count = origQuakeList.size();
} else {
// Perform filter
ArrayList<QuakeItem> nQuakeList = new ArrayList<QuakeItem>();
switch (constraint.toString()){
case "tsunamiOnly":
for (QuakeItem q : quakeList){
if (q.getTsunami() == 1){
nQuakeList.add(q);
}
}
break;
case "earthquakeOnly":
for (QuakeItem q : quakeList){
if (q.getTsunami() == 0){
nQuakeList.add(q);
}
}
break;
}
results.values = nQuakeList;
results.count = nQuakeList.size();
}
return results;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults filterResults) {
if (filterResults.count == 0){
notifyDataSetInvalidated();
} else {
quakeList = (ArrayList<QuakeItem>) filterResults.values;
Log.d(LOG_TAG, "FILTER " + quakeList);
notifyDataSetChanged();
}
}
}
}
Solved my own problem. As expected it was something stupid.
I was missing getCount, getItem and getItemId in my adapter.
public int getCount() {
return quakeList.size();
}
public QuakeItem getItem(int position) {
return quakeList.get(position);
}
public long getItemId(int position) {
return quakeList.get(position).hashCode();
}

Trouble getting results from SearchView with Listview using Custom Adapter

I have a Listview with a Custom BaseAdapter. I have already done the code for my MainActivity.java to apply SearchView. However, I have problem with the performFiltering method in my Adapter class due to the reason that I have a ImageView that would be shown on my ListView. The ImageView is originally in the form of String because I would like to get the image from an url in my Firebase Storage and then convert it to Image by using the Picasso library.
TL:DR. My problem is that everytime I perform a search, the url of the image stored in Firebase is showing up instead of the actual Image. Help is appreciated thanks.
Below is my Adapter Class:
public class GridAdapter extends BaseAdapter implements Filterable {
CustomFilter mCustomFilter;
ArrayList<GridItem> filterList;
private Context mContext;
private ArrayList<GridItem> gtem;
//Constructor
public GridAdapter(Context mContext, ArrayList<GridItem> gtem) {
this.filterList = gtem;
this.mContext = mContext;
this.gtem = gtem;
}
#Override
public int getCount() {
return gtem.size();
}
#Override
public Object getItem(int position) {
return gtem.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = View.inflate(mContext,R.layout.grid_item, null);
ImageView putPic = (ImageView)v.findViewById(R.id.imageHere);
TextView putTitle = (TextView)v.findViewById(R.id.titleHere);
TextView putPrice = (TextView)v.findViewById(R.id.per_price);
TextView putCountry = (TextView)v.findViewById(R.id.countryHere);
//
putCountry.setText("Country: " + gtem.get(position).getCountry());
putTitle.setText(gtem.get(position).getmTitleHere());
putCountry.setText(gtem.get(position).getCountry());
putPrice.setText("Price: " + "$" + gtem.get(position).getmPriceHere());
Picasso.with(mContext).load(gtem.get(position).getmImageView()).resize(450 , 500).into(putPic);
return v;
}
#Override
public Filter getFilter() {
//To-do Auto-generated method stub
if (mCustomFilter == null )
{
mCustomFilter = new CustomFilter();
}
return mCustomFilter;
}
//Inner Class
class CustomFilter extends Filter
{
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if (constraint != null && constraint.length()>0)
{
//Constraint to Upper
constraint = constraint.toString().toUpperCase();
ArrayList<GridItem> filters = new ArrayList<GridItem>();
//to get specific items
for (int i = 0; i<filterList.size(); i++)
{
if (filterList.get(i).getmTitleHere().toUpperCase().contains(constraint))
{
GridItem g = new GridItem(filterList.get(i).getmTitleHere() , filterList.get(i).getmPriceHere(), filterList.get(i).getmImageView()
, filterList.get(i).getCountry());
filters.add(g);
}
}
results.count = filters.size();
results.values = filters;
}else {
results.count = filterList.size();
results.values = filterList;
}
return results;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
gtem = (ArrayList<GridItem>) results.values;
notifyDataSetChanged();
}
}
}

List view not returning to original state after clearing search

I'm trying to get my list to show all my items again whenever I cancel a search from my search view but for some strange reason, the list gets stuck with the results only from the previous search. Does anyone know what is wrong with my code and how to fix this? I believe something is wrong with the filter related code but I don't know what it is.
FilterListFragment.java
public class ItemListAdapter extends BaseAdapter implements Filterable {
private List<Item> mData;
private List<Item> mFilteredData;
private LayoutInflater mInflater;
private ItemFilter mFilter;
public ItemListAdapter (List<Item> data, Context context) {
mData = data;
mFilteredData = data;
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return mFilteredData.size();
}
#Override
public String getItem(int position) {
return mFilteredData.get(position).getItem();
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.item_row, parent, false);
holder = new ViewHolder();
holder.title = (TextView) convertView.findViewById(R.id.item_title);
holder.description = (TextView) convertView.findViewById(R.id.item_description);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.title.setText(mData.get(position).getItem());
holder.description.setText(mData.get(position).getItemDescription());
return convertView;
}
#Override
public Filter getFilter() {
if (mFilter == null) {
mFilter = new ItemFilter();
}
return mFilter;
}
/**
* View holder
*/
static class ViewHolder {
private TextView title;
private TextView description;
}
/**
* Filter for filtering list items
*/
private class ItemFilter extends Filter {
/**
* Invoked on a background thread. This is where all the filter logic should go
* #param constraint the constraint to filter on
* #return the resulting list after applying the constraint
*/
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if (TextUtils.isEmpty(constraint)) {
results.count = mData.size();
results.values = mData;
} else {
//Create a new list to filter on
List<Item> resultList = new ArrayList<Item>();
for (Item str : mData) {
if (str.getItem().toLowerCase().contains(constraint.toString().toLowerCase())) {
resultList.add(str);
}
}
results.count = resultList.size();
results.values = resultList;
}
return results;
}
/**
* Runs on ui thread
* #param constraint the constraint used for the result
* #param results the results to display
*/
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
if (results.count == 0) {
notifyDataSetInvalidated();
} else {
mFilteredData = (ArrayList<Item>)results.values;
notifyDataSetChanged();
}
}
}
}
List in normal state
List in filtered state
You are operating on the original data instead of filtered data. You should maintain a reference to original data and use the filtered data for all other purposes. So that the original data is displayed when search is cleared.
Replace all usages of mData with mFilteredData as below and only use the original data to generate the filtered data:
private List<String> mData;
private List<String> mFilteredData;
private LayoutInflater mInflater;
private ItemFilter mFilter;
public ItemListAdapter (List<String> data, Context context) {
mData = data;
mFilteredData = data;
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return mFilteredData.size();
}
#Override
public String getItem(int position) {
return mFilteredData.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
String strItem = mFilteredData.get(position);
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.item_row, parent, false);
holder = new ViewHolder();
holder.mTvItem = (TextView) convertView.findViewById(R.id.tv_item);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.mTvItem.setText(strItem);
return convertView;
}
#Override
public Filter getFilter() {
if (mFilter == null) {
mFilter = new ItemFilter();
}
return mFilter;
}
/**
* View holder
*/
static class ViewHolder {
private TextView mTvItem;
}
/**
* Filter for filtering list items
*/
private class ItemFilter extends Filter {
/**
* Invoked on a background thread. This is where all the filter logic should go
* #param constraint the constraint to filter on
* #return the resulting list after applying the constraint
*/
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if (TextUtils.isEmpty(constraint)) {
results.count = mData.size();
results.values = mData;
} else {
//Create a new list to filter on
List<String> resultList = new ArrayList<>();
for (String str : mData) {
if (str.toLowerCase().contains(constraint.toString().toLowerCase())) {
resultList.add(str);
}
}
results.count = resultList.size();
results.values = resultList;
}
return results;
}
/**
* Runs on ui thread
* #param constraint the constraint used for the result
* #param results the results to display
*/
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
if (results.count == 0) {
notifyDataSetInvalidated();
} else {
mFilteredData = (ArrayList<String>)results.values;
notifyDataSetChanged();
}
}
}
Add a log statement to onQueryTextChange() so you can see how your filter string is changing. Note that SearchView does not call onQueryTextChange() with an empty string when the search view is closed. You need to decide when you want the search string cleared, perhaps by adding a control for that, and do the clearing yourself.

NotifyDataSetChanged() not refreshing list?

I know this question has been asked thousands of times but I couldn't find an answer for my case for some reason.
What I have is a thread that fetches data from a web services and populates a list with the info. Then I want to press a button and call the same thread to fetch some more data and add it to the list.
But when I call notifyDataSetChanged(), the list for some reason doesn't refresh. The data is in the adapter though...
Here's the code:
#Override
protected void onPostExecute(PropertyNotesParser result) {
this.progressDialog.dismiss();
ArrayList<PropertyNoteHistory> propertyNoteList = result.getAllTheNotes();
addNoteListItems(propertyNoteList);
Collections.sort(getNoteList());
ArrayList<String> titles = new ArrayList<String>();
ArrayList<String> subtitles = new ArrayList<String>();
DateHandler handleDate = new DateHandler();
DataResolve convert = new DataResolve();
for(Iterator<PropertyNoteHistory> i = getNoteList().iterator(); i.hasNext(); ) {
PropertyNoteHistory item = i.next();
PropertyNoteHistory.Note note = item.getNotes();
PropertyNoteHistory.Jobs jobs = item.getJobs();
// Default value is office in case the xml does not have the tag "job" associated with "note".
String service = "Office";
if(jobs != null){
service = convert.getServiceName(jobs.getServiceID());
}
titles.add(note.getTitle() + " (" + service + ")");
subtitles.add(handleDate.formatDate(note.getDate(), "dd MMM yyyy") + " Ref: " + note.getJobID());
}
if(getConnectionCount() == 0){
adapter = new SimpleListAdapter(getActivity(), titles, subtitles);
lv.setAdapter(adapter);
}
else {
adapter.addItem(titles, subtitles);
}
and my adapter:
public class SimpleListAdapter extends BaseAdapter {
private int count = 0;
private static LayoutInflater inflater = null;
private ArrayList<String> titles = new ArrayList<String>();
private ArrayList<String> subtitles = new ArrayList<String>();
private ArrayList<Integer> imageResource = new ArrayList<Integer>();
private boolean hasImage = false;
public SimpleListAdapter(Activity activity, ArrayList<String> titles,
ArrayList<String> subtitles, ArrayList<Integer> imageResource) {
count = titles.size();
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.titles = titles;
this.subtitles = subtitles;
this.imageResource = imageResource;
this.hasImage = true;
}
/**Constructor that creates an adapter with only a title and subtitle.
* #param activity The context.
* #param titles ArrayList with the titles of each list option.
* #param subtitles ArrayList with the subtitles of each list option. */
public SimpleListAdapter(Activity activity, ArrayList<String> titles,
ArrayList<String> subtitles) {
count = titles.size();
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.titles = titles;
this.subtitles = subtitles;
this.hasImage = false;
}
public void addItem(ArrayList<String> title, ArrayList<String> subtitle){
this.titles.addAll(title);
this.subtitles.addAll(subtitle);
notifyDataSetChanged();
}
#Override
public int getCount() {
return count;
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if(v == null)
v = inflater.inflate(R.layout.layout_simple_list, null);
final ImageView icon = (ImageView) v.findViewById(R.id.icon);
final TextView title = (TextView) v.findViewById(R.id.title);
final TextView subtitle = (TextView) v.findViewById(R.id.subtitle);
title.setText(titles.get(position));
subtitle.setText(subtitles.get(position));
if (hasImage) {
icon.setImageResource(imageResource.get(position));
}
else {
icon.setVisibility(ImageView.GONE);
}
return v;
}
}
You will need to update your count variable too in addItem so that the all the rows are created when notifyDataSetChanged is called

Categories

Resources