HashMap to ListView
Make simple adapter class:
MyAdapter.java
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.Map;
public class MyAdapter extends BaseAdapter {
private final ArrayList mData;
public MyAdapter(Map<String, String> map) {
mData = new ArrayList();
mData.addAll(map.entrySet());
}
@Override
public int getCount() {
return mData.size();
}
@Override
public Map.Entry<String, String> getItem(int position) {
return (Map.Entry) mData.get(position);
}
@Override
public long getItemId(int position) {
// TODO implement you own logic with ID
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final View result;
if (convertView == null) {
result = LayoutInflater.from(parent.getContext()).inflate(R.layout.my_adapter_item, parent, false);
} else {
result = convertView;
}
Map.Entry<String, String> item = getItem(position);
// TODO replace findViewById by ViewHolder
((TextView) result.findViewById(android.R.id.text1)).setText(item.getKey());
((TextView) result.findViewById(android.R.id.text2)).setText(item.getValue());
return result;
}
}
layout/my_adapter_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<TextView
android:id="@android:id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<TextView
android:id="@android:id/text2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
Your code:
public void showCinemas(HashMap<String, String> cinemas) {
MyAdapter adapter = new MyAdapter(cinemas);
list.setAdapter(adapter);
}
HashMap is made of 2 Collection (or better 1 Collection and 1 Set), so it is not really possible by extending ArrayAdapter; but you can easily get a Collection (or better a Set) of Map.Entry, and convert it to a List:
From:
Map<String, Object> map = new HashMap<String, Object>();
to:
List<Map.Entry<String, Object>> list = new ArrayList(map.entrySet());
So I use a derived ArrayAdapter like this one:
class HashMapArrayAdapter extends ArrayAdapter {
private static class ViewHolder {
TextView tV1;
TextView tV2;
}
public HashMapArrayAdapter(Context context, int textViewResourceId, List<Map.Entry<String, Object>> objects) {
super(context, textViewResourceId, objects);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(android.R.layout.simple_list_item_2, parent, false);
viewHolder = new ViewHolder();
viewHolder.tV1 = (TextView) convertView.findViewById(android.R.id.text1);
viewHolder.tV2 = (TextView) convertView.findViewById(android.R.id.text2);
convertView.setTag(viewHolder);
} else
viewHolder = (ViewHolder) convertView.getTag();
Map.Entry<String, Object> entry = (Map.Entry<String, Object>) this.getItem(position);
viewHolder.tV1.setText(entry.getKey());
viewHolder.tV2.setText(entry.getValue().toString());
return convertView;
}
And then to create the adapter:
ArrayAdapter adapter = new HashMapArrayAdapter(this.getActivity(), android.R.layout.simple_list_item_2, new ArrayList(map.entrySet()));
This has some similarities to Zanna's answer above, but is somewhat cleaner, improved and more comprehensive. I think this is about as simple as it gets.
Adapter:
public class MapEntryListAdapter extends ArrayAdapter<Map.Entry<String, Object>>
{
public MapEntryListAdapter (Context context, List<Map.Entry<String, Object>> entryList)
{
super (context, android.R.layout.simple_list_item_2, entryList);
}
@NonNull @Override
public View getView (int position, View convertView, ViewGroup parent)
{
View currentItemView = convertView != null ? convertView :
LayoutInflater.from (getContext ()).inflate (
android.R.layout.simple_list_item_2, parent, false);
Map.Entry<String, Object> currentEntry = this.getItem (position);
TextView textViewKey = currentItemView.findViewById (android.R.id.text1);
TextView textViewValue = currentItemView.findViewById (android.R.id.text2);
textViewKey.setText (currentEntry.getKey ());
textViewValue.setText (currentEntry.getValue ().toString ());
return currentItemView;
}
}
MainActivity - fields:
private Map<String, Object> mMapItems; // original data source of all items
private List<Map.Entry<String, Object>> mListOfMapEntries; // list of entries from mMapItems
private MapEntryListAdapter mMapEntryListAdapter;
MainActivity - onCreate method: (relevant portion)
mMapItems = new LinkedHashMap<> ();
mMapItems.put ("Test Key", "Test Value"); // put in sample item #1
mMapItems.put ("Sample Key", "Sample Value"); // put in sample item #2
mListOfMapEntries = new ArrayList<> (mMapItems.entrySet ()); // create the list
mMapEntryListAdapter = new MapEntryListAdapter (this, mListOfMapEntries);
ListView listView = findViewById (R.id.list_view);
listView.setAdapter (mMapEntryListAdapter);
Note: By design, the data source of this adapter does not duplicate the incoming entryList but rather points to the same actual list. This enables you to easily modify the Adapter's data in MainActivity or wherever else you have the reference to an Adapter of this object. You would then need to call the adapter's notifyDataSetChanged() method to let it know that the list has changed so that it updates the ListView to reflect these changes.
If the contents of your Map object changes later on, you could do the following to bring those updates into your list and then into your ListView:
mListOfMapEntries.clear ();
mListOfMapEntries.addAll (mMapItems.entrySet ());
mMapEntryListAdapter.notifyDataSetChanged ();
This clears the list of all existing items then adds the items from the Map to the list and then, very importantly, tells the adapter to update the ListView.
(Note: Do NOT create a new List object here (as opposed to clearing and adding shown here) because then you will not anymore be modifying the Adapter's data source which will still be pointing to the original list.)