0

I am making a checklist type app in Android, in which I am populating items in a list view with a check box next to them. when a user clicks on an item I want it to strike out the text and update the entry in the database for the relevant column. For this reason I am storing Name-Value pairs in a TreeMap. Where Name corresponds to the Database Column Name and Value to the value in that Column name. I have achieved this using the following:

if ((c.getString(c.getColumnIndexOrThrow("Field130"))).length() > 3) {
                    String D11 = c.getString(c.getColumnIndexOrThrow("Field130"));
                    map.put("Field130", D11); 
                }

Now I want to display the name in one textview of the corresponding listview and value in the second textview. I tried the following:

ArrayList<TreeMap<String, String>> mylist = new ArrayList<TreeMap<String, String>>();
            mylist.add(map);
            ListView list = (ListView) findViewById(R.id.list);
            ArrayList<String> list1 = new ArrayList<String>(map.values());
            dataAdapter = new ArrayAdapter<String>(this,R.layout.chklistlayout,R.id.textView1, list1);
            list.setAdapter(dataAdapter);

However I am not able to get the desired results, as I get only the Values displayed. Is there no way that I can map my TreeMap directly to the listview? I am open to ideas which are more robust, even if that means reworking my whole code.

Skynet
  • 7,820
  • 5
  • 44
  • 80

1 Answers1

4

I finally made a custom Adapter, took reference from here:

1) What adapter shall I use to use HashMap in a ListView

2) http://www.vogella.com/articles/AndroidListView/article.html.

3) http://www.youtube.com/watch?v=wDBM6wVEO70

4) https://dl.google.com/googleio/2010/android-world-of-listview-android.pdf

Edit: Based on suggestions in the comments, I have invoked a ViewHolder pattern to handle recycling of views and address the concerns of memory management and battery use. The complete code is as follows:

public class TreeMapAdapter extends ArrayAdapter<String> {
    private final Context context;
    private final String[] values;
    String[] mValues;


    private TreeMap<String, String> mData = new TreeMap<String, String>();
    private String[] mKeys;

    public TreeMapAdapter(Context context, String[] mKeys,TreeMap<String, String> data) {
        super(context, R.layout.chklistlayout, mKeys);
        this.context = context;
        this.values = mKeys;
        mData  = data;
        mValues = mData.values().toArray(new String[data.size()]);
    }
    public int getCount() {

        return mData.size();

    }

    public String getItem(int position) {

        return mData.get(mKeys[position]);
    }


    public long getItemId(int arg0) {

        return arg0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {


        if (convertView == null) { 
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(R.layout.chklistlayout, 
                    parent, false);
            holder = new ViewHolder(); 
            holder.textView = (TextView) convertView.findViewById(R.id.textView1); 
            holder.imageview = (TextView) convertView.findViewById(R.id.textView2); 
            holder.CB = (CheckBox) convertView.findViewById(R.id.checkBox1); 

            convertView.setTag(holder); 
        } else { 
            holder = (ViewHolder) convertView.getTag(); 
        }
        holder.textView.setText(values[position]);
        holder.imageview.setText(mValues[position]);


        String s = mValues[position];
        if (s.contains("h")) {
            holder.CB.setChecked(true);
        } else {

        }

        return convertView;
    }
} 

Following is the holder class:

static class ViewHolder {

    TextView textView, imageview;
    CheckBox CB;


}

There are three ways to recycle views, one is called as the Dumb way, the other as the right way and the one used in this example is the fastest way. Users who stumble on this post later, I highly recommend to go through the YouTube video. Its worth it!

In a nutshell ConvertView is responsible for recycling of views, it keeps track of all the views which are moving out of screen focus and returns one view which is recycled and reused.

Lastly Thanks to KMDev, who sparked this thought of researching more and making a template for Holder pattern.

Community
  • 1
  • 1
Skynet
  • 7,820
  • 5
  • 44
  • 80
  • 1
    I would suggest that you implement the [ViewHolder](http://www.jmanzano.es/blog/?p=166) pattern. The performance benefits are well worth it. It's mentioned in a talk by the Android team in one of the earlier Google IO's, but there's plenty of blog posts rehashing the same thing. – KMDev Aug 31 '13 at 08:53
  • Thanks, I was looking at the same. TO re-create views. However my list contains only 130 items at most. So I was contemplating whether to use a holder pattern or not. – Skynet Aug 31 '13 at 10:05
  • 1
    Two things to consider with regards to performance: 1. Scroll jittering - old, underperformant phones might jitter on fling 2. Battery. We have an obligation to code for performance as much as possible. Whether or not this makes a negligable difference or not in your case, I don't know. But, it's a great habit to get in to if you're going to be using ListViews at all. Just make a code template for getView() with the view holder pattern and you don't have to think about it again. :) – KMDev Aug 31 '13 at 10:35
  • Done mate, do check it out :) – Skynet Sep 02 '13 at 08:34
  • as far as i know you have to use `key = getItem(position); value = mdata.get(key)` otherwise the listview is not working correctly – oli Dec 04 '15 at 11:19
  • Hi Oli, its been long, the project has long been decommissioned. However the above was working I last checked. Feel free to modify it according to your needs. – Skynet Dec 04 '15 at 11:24