0

I've had trouble finding much documentation on using LinkedHashMap with a ListView for Android, but I was able to get the list to populate correctly with the below.

Unfortunately, when I scroll, the list is scrambled the same as it would be if I was using a regular HashMap. I'm not sure what I'm doing wrong.

MainActivity.java (only a portion):

public class MainActivity extends ListActivity {
    private ListView dataList;
    ArrayList<String> listItems=new ArrayList<String>();
    ListViewAdapter adapter;
    private ArrayList<LinkedHashMap<String, String>> list;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        dataList = (ListView)findViewById(android.R.id.list);

        list=new ArrayList<LinkedHashMap<String,String>>();
        adapter=new ListViewAdapter(this, list);
        dataList.setAdapter(adapter);

        addItems();
    }

    public void addItems() {
        LinkedHashMap<String,String> row = new LinkedHashMap<String, String>();
        row.put(KEY_COLUMN, key);
        row.put(FIRST_COLUMN, dateTime);
        row.put(SECOND_COLUMN, data1);
        row.put(THIRD_COLUMN, data2);
        row.put(FOURTH_COLUMN, data3);
        list.add(row);
        adapter.notifyDataSetChanged();
    }
}

ListViewAdapter Class

public class ListViewAdapter extends BaseAdapter{
    public ArrayList<LinkedHashMap<String, String>> list;
    Activity activity;
    TextView txtKey;
    TextView txtFirst;
    TextView txtSecond;
    TextView txtThird;
    TextView txtFourth;

    public ListViewAdapter(Activity activity,ArrayList<LinkedHashMap<String, String>> list){
        super();
        this.activity = activity;
        this.list = list;
    }

    @Override
    public int getCount() {
        // TODO Auto-generated method stub
        return list.size();
    }

    @Override
    public Object getItem(int position) {
        // TODO Auto-generated method stub
        return list.get(position);
    }

    @Override
    public long getItemId(int position) {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // TODO Auto-generated method stub

        if(convertView == null){
            LayoutInflater inflater = activity.getLayoutInflater();
            convertView = inflater.inflate(R.layout.list_row_columns, null);
            txtKey = (TextView) convertView.findViewById(R.id.row_key);
            txtFirst = (TextView) convertView.findViewById(R.id.date_time);
            txtSecond = (TextView) convertView.findViewById(R.id.data1);
            txtThird = (TextView) convertView.findViewById(R.id.data2);
            txtFourth = (TextView) convertView.findViewById(R.id.data3);
        }

        LinkedHashMap<String, String> map = list.get(position);
        txtKey.setText(map.get(KEY_COLUMN));
        txtFirst.setText(map.get(FIRST_COLUMN));
        txtSecond.setText(map.get(SECOND_COLUMN));
        txtThird.setText(map.get(THIRD_COLUMN));
        txtFourth.setText(map.get(FOURTH_COLUMN));

        return convertView;
    }

}
sean
  • 3,484
  • 5
  • 27
  • 45
  • What do you mean by `the list is scrambled the same as it would be if I was using a regular HashMap`? – Rami Oct 03 '15 at 19:54
  • From what I understand, HashMap (which I originally was using) scrambles the order of the rows when the data is refreshed or the list is scrolled, so LinkedHashMap was created to solve this problem (http://www.tutorialspoint.com/java/java_linkedhashmap_class.htm). This thread also explains the difference: http://stackoverflow.com/questions/2889777/difference-between-hashmap-linkedhashmap-and-treemap – sean Oct 03 '15 at 19:57

1 Answers1

2

The simplest solution would be to use ArrayAdapter rather than rolling your own BaseAdapter subclass. But, assuming that you really want to extend BaseAdapter...

First, get rid of all of the widgets from the class declaration (e.g., TextView txtKey), moving them to be local variables inside of getView().

Then, populate those local variables whether or not you are inflating a new layout.

Other improvements:

  • Never use LayoutInflater.from() when you have an Activity. Call getLayoutInflater() on the Activity, so you get a LayoutInflater that knows about your themes and styles.

  • Use getItem(), instead of list.get(position), in getView(), so getView() and getItem() stay in sync.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • I was able to use your suggestion to go with ArrayAdapter vs. BaseAdapter to find these sources, which solved this issue. Thanks! https://github.com/codepath/android_guides/wiki/Using-an-ArrayAdapter-with-ListView https://github.com/codepath/android-custom-array-adapter-demo – sean Oct 04 '15 at 15:03