I'm writing an app that parses both current and planned roadworks info from the web and displays them in a list format. I've created a custom adapter to create and add the list items to the ListView. When I run the app I get a runtime error:
Java.lang.RuntimeException: Unable to start activity ComponentInfo{labstuff.gcu.me.org.roadworksscotland/labstuff.gcu.me.org.roadworksscotland.MainActivity}: android.view.InflateException: Binary XML file line #54: addView(View, LayoutParams) is not supported in AdapterView
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2665)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
Caused by: android.view.InflateException: Binary XML file line #54: addView(View, LayoutParams) is not supported in AdapterView
Caused by: java.lang.UnsupportedOperationException: addView(View, LayoutParams) is not supported in AdapterView
at android.widget.AdapterView.addView(AdapterView.java:495)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:862)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:821)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:861)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:821)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:861)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:821)
at android.view.LayoutInflater.inflate(LayoutInflater.java:518)
at android.view.LayoutInflater.inflate(LayoutInflater.java:426)
at android.view.LayoutInflater.inflate(LayoutInflater.java:377)
at android.support.v7.app.AppCompatDelegateImplV9.setContentView(AppCompatDelegateImplV9.java:292)
at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:140)
at labstuff.gcu.me.org.roadworksscotland.MainActivity.onCreate(MainActivity.java:33)
at android.app.Activity.performCreate(Activity.java:6679)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2618)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
Here is my MainActivity class it uses an Async Task to fetch the web info and that's what creates and attached the adapters to the ListViews by calling the attachAdapters() method when complete.
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private int currentRoadworksCount;
private int plannedRoadworksCount;
private LinkedList<CurrentRoadwork> currentRoadworks;
private LinkedList<PlannedRoadwork> plannedRoadworks;
private Button currentRoadworksButton;
private Button plannedRoadworksButton;
private ViewSwitcher viewSwitcher;
private ListView currentRoadworksList;
private ListView plannedRoadworkdsList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.currentRoadworksButton = (Button)findViewById(R.id.currentRoadworksButton);
currentRoadworksButton.setOnClickListener(this);
this.plannedRoadworksButton = (Button)findViewById(R.id.plannedRoadworksButton);
plannedRoadworksButton.setOnClickListener(this);
this.viewSwitcher = (ViewSwitcher)findViewById(R.id.viewSwitcher);
this.currentRoadworksList = (ListView)findViewById(R.id.currentRoadworksList);
this.plannedRoadworkdsList = (ListView)findViewById(R.id.plannedRoadworksList);
new NetworkAsyncTask().execute();
}
private class NetworkAsyncTask extends AsyncTask<Void, Void, Void>
{
ApiReader reader;
@Override
protected void onPreExecute()
{
reader = new ApiReader();
currentRoadworks = new LinkedList<CurrentRoadwork>();
plannedRoadworks = new LinkedList<PlannedRoadwork>();
}
@Override
protected Void doInBackground(Void... params)
{
currentRoadworks = reader.parseCurrentRoadworks();
Log.e("Progress update", "Current roadworks loaded");
plannedRoadworks = reader.parsePlannedRoadworks();
Log.e("Progress update", "Planned roadworks loaded");
return null;
}
@Override
protected void onPostExecute(Void result)
{
super.onPostExecute(result);
currentRoadworksCount = currentRoadworks.size();
plannedRoadworksCount = plannedRoadworks.size();
currentRoadworksButton.setText(currentRoadworksButton.getText().toString()
+ "\n(" + currentRoadworksCount + " Events)");
plannedRoadworksButton.setText(plannedRoadworksButton.getText().toString()
+ "\n(" + plannedRoadworksCount + " Events)");
attachAdapters();
}
}
public void attachAdapters()
{
RoadworkAdapter currentRoadworkAdapter = new RoadworkAdapter(this, currentRoadworks);
currentRoadworksList.setAdapter(currentRoadworkAdapter);
RoadworkAdapter plannedRoadworkAdapter = new RoadworkAdapter(this, plannedRoadworks, "planned");
plannedRoadworkdsList.setAdapter(plannedRoadworkAdapter);
}
@Override
public void onClick(View v)
{
if (v == currentRoadworksButton)
{
currentRoadworksButton.setEnabled(false);
plannedRoadworksButton.setEnabled(true);
viewSwitcher.showNext();
}
else if (v == plannedRoadworksButton)
{
currentRoadworksButton.setEnabled(true);
plannedRoadworksButton.setEnabled(false);
viewSwitcher.showPrevious();
}
}
}
Here is my adapter class:
public class RoadworkAdapter extends BaseAdapter {
private Context mContext;
private LayoutInflater mInflater;
private LinkedList<CurrentRoadwork> currentRoadworksSource;
private LinkedList<PlannedRoadwork> plannedRoadworksSource;
private boolean current;
private boolean grey;
public RoadworkAdapter(Context context, LinkedList<CurrentRoadwork> currentRoadworks)
{
current = true;
mContext = context;
currentRoadworksSource = currentRoadworks;
plannedRoadworksSource = null;
mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public RoadworkAdapter (Context context, LinkedList<PlannedRoadwork> plannedRoadworks, String planned)
{
current = false;
mContext = context;
plannedRoadworksSource = plannedRoadworks;
currentRoadworksSource = null;
mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public int getCount()
{
if (current) return currentRoadworksSource.size();
else return plannedRoadworksSource.size();
}
@Override
public Object getItem(int position)
{
if (current) return currentRoadworksSource.get(position);
else return plannedRoadworksSource.get(position);
}
@Override
public long getItemId(int position)
{
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
View rowView = convertView;
if (rowView == null){ rowView = mInflater.inflate(R.layout.current_roadwork, parent,false);}
if (current)
{
if (rowView == null){ rowView = mInflater.inflate(R.layout.current_roadwork, parent,false);}
TextView titleView = (TextView) rowView.findViewById(R.id.row_title);
TextView date = (TextView) rowView.findViewById(R.id.row_date);
TextView description = (TextView) rowView.findViewById(R.id.row_description);
CurrentRoadwork roadwork = (CurrentRoadwork) getItem(position);
titleView.setText(roadwork.getTitle());
date.setText(roadwork.getStartDate().toString()
+ " to " + roadwork.getEndDate().toString());
description.setText(roadwork.getDescription());
if (grey)
{
rowView.setBackgroundColor(mContext.getResources().getColor(R.color.GhostWhite));
grey = false;
}
else
{
grey = true;
}
return rowView;
}
else
{
if (rowView == null){ rowView = mInflater.inflate(R.layout.planned_roadwork, parent,false);}
TextView titleView = (TextView) rowView.findViewById(R.id.row_title_planned);
TextView date = (TextView) rowView.findViewById(R.id.row_date_planned);
TextView description = (TextView) rowView.findViewById(R.id.row_description_planned);
PlannedRoadwork roadwork = (PlannedRoadwork) getItem(position);
titleView.setText(roadwork.getTitle());
date.setText(roadwork.getStartDate().toString()
+ " to " + roadwork.getEndDate().toString());
String descriptionString = roadwork.getDescription();
if (roadwork.getTrafficManagement() != null) descriptionString += " " + roadwork.getTrafficManagement();
if (roadwork.getDiversionInfo() != null) descriptionString += " " + roadwork.getDiversionInfo();
if (roadwork.getWorksInfo() != null) descriptionString += " " + roadwork.getWorksInfo();
description.setText(roadwork.getDescription());
if (grey)
{
rowView.setBackgroundColor(mContext.getResources().getColor(R.color.GhostWhite));
grey = false;
}
else
{
grey = true;
}
return rowView;
}
}
}
This class can be used for either planned or current roadworks which are slightly different and which one is determined by the boolean "current". Two instances of it are created for each ListView in ActivityMain. In all other occurrences of this error on SO I can find seem to be because the list item is inflated like
rowView = mInflater.inflate(R.layout.planned_roadwork, parent)
But mines seem to be coded correctly as
rowView = mInflater.inflate(R.layout.planned_roadwork, parent,false)
Any ideas what is going wrong here?