How Do I inflate a ListFragment with a custom ArrayAdapter? I have two classes “Owner and Car”. The user will search for an owner, and it will display one or owners using ListFragments. In addition, if the user were to click on an owner, it should display a detail list of cars that the owner owns. I’ve created the following classes/helper classes (CarDetail and OwnerDetail – these two classes extends ListFragment, People Extends FragmentActivity, CarAdapter and OwnerAdapter custom adapter, CarAsyncTask and OwnerAsyncTask AsyncTasks, and Login that extend activity). The login class allows a user to login and search for an owner. When the user logs in and do a search, one or more owners should display on the upper section of the layout. However, I have not been able to get it to display. Here are my codes:
//Updated on 07/30 @10:50 AM I updated the OwnerDetail onActivityCreated to use the OwnerActivityAdapter. However, It's throwing an exception in the when setting the TextView for the holder. See exception at the bottom.
For simplicity reason, I will only display partial part of the text.
//Car Class
public class Car {
private String _make;
private String _model;
private String _year;
public Car(String make, String model, String year)
{
this._make = make;
this._model = model;
this._year = year;
}
}
//Owner Class
public class Owner {
private String _firstName;
private String _lastName;
private String _carId;
private Car _car;
public Owner(String lName, String fName, String cId, Car car)
{
this._lastName = lName;
this._firstName = fName;
this._carId = cId;
this._car = car;
}
}
package com.mb.carlovers;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
//Car Detail
public class CarDetail extends ListFragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.customize_layout,container,false);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
String[] myCars = {};
super.onActivityCreated(savedInstanceState);
ArrayAdapter<String> carAdapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_activated_1, myCars);
setListAdapter(carAdapter);
}
}
//OnwerDetail class
public class OwnerDetail extends ListFragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.customize_layout,container, false);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
//Updated on 07/30 @10:50 AM
//Change this class to use the OwnerAsyncTask()
OnwerAsyncTask asynTask = new OnwerAsyncTask();
List<Owner> lt = null;
try {
lt = asynTask.execute("").get();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Owner myOwners[] = lt.toArray(new Owner[lt.size()]);
super.onActivityCreated(savedInstanceState);
OwnerAdapter ownerAdapter = new OwnerAdapter(getActivity(),android.R.layout.simple_list_item_activated_1 , myOwners);
setListAdapter(ownerAdapter);
}
//People where the new Fragment should be created
public class People extends FragmentActivity implements OnClickListener, OnItemSelectedListener {
private Button search;
private EditText etSearchBy, etSearchByID;
private Spinner spOption;
private String selectedOption = null;
private TextView tvErrorMessage;
@Override
protected void onCreate(Bundle arg0) {
super.onCreate(arg0);
setContentView(R.layout.people);
InitializeVariables();
}
private void InitializeVariables()
{
etSearchBy = (EditText) this.findViewById(R.id.etByLastName);
etSearchByID = (EditText) this.findViewById(R.id.etCarID);
spOption = (Spinner) this.findViewById(R.id.spOption);
search = (Button) this.findViewById(R.id.bSearch);
search.setOnClickListener(this);
tvErrorMessage = (TextView) this.findViewById(R.id.tvErrorMessage);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,R.array.spOptions, android.R.layout.simple_spinner_dropdown_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spOption.setAdapter(adapter);
spOption.setOnItemSelectedListener(this);
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
@Override
protected void onPause() {
super.onPause();
}
@Override
public void onClick(View v) {
String searchByName = etSearchBy.getText().toString();
String searchById = etSearchByID.getText().toString();
if(selectedOption == null || selectedOption == "All")
{
if(searchByName.matches("") || searchById.matches(""))
{
tvErrorMessage.setText("You must select a last name and car id");
} else
{
}
} else if(selectedOption == "Name")
{
if(!searchByName.matches(""))
{
try
{
**//Here is the List of information that I need to inflate the fragment with.**
OnwerAsyncTask ownerAsyncTask = new OnwerAsyncTask();
List<Owner> owner = ownerAsyncTask.execute("").get();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else
{
tvErrorMessage.setText("You must enter the last name of the owner.");
}
} else if (selectedOption == "ID")
{
if(!searchById.matches(""))
{
String st = null;
String d = st;
} else
{
tvErrorMessage.setText("You must enter the car id that you'd like to search.");
}
}
}
//Owner Adapter – (The Car Adapter looks similar to this except the variables name are different.)
public class OwnerAdapter extends ArrayAdapter<Owner> {
private Context context;
private int layoutResourceId;
private Owner data[] = null;
public OwnerAdapter(Context context, int resource, int textViewResourceId,Owner[] data) {
super(context, resource, textViewResourceId, data);
this.context = context;
this.layoutResourceId = resource;
this.data = data;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
OwnerHolder holder = null;
if(row == null)
{
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
holder = new OwnerHolder();
holder.tvFirstName = (TextView) row.findViewById(R.id.tvFirstName);
holder.tvLastName = (TextView) row.findViewById(R.id.tvLastName);
holder.tvCarId = (TextView) row.findViewById(R.id.tvCarID);
row.setTag(holder);
} else
{
holder = (OwnerHolder) row.getTag();
}
Owner item = data[position];
**//Updated on 07/30 @10:50 AM
// Below is where I am getting the exception**
holder.tvFirstName.setText(item.getFirstName().toString());
holder.tvLastName.setText(item.getLastName().toString());
holder.tvCarId.setText(item.getCarId().toString());
return row;
}
static class OwnerHolder
{
TextView tvFirstName;
TextView tvLastName;
TextView tvCarId;
}
}
//Owner AsyncTask –(CarAsyncTask is also similar)
public class OnwerAsyncTask extends AsyncTask<String, Void, List<Owner>> {
private List<Owner> items = null;
@Override
protected List<Owner> doInBackground(String... params) {
try
{
items = new ArrayList<Owner>();
items.add(new Owner("John", "Smith", "1"));
items.add(new Owner("Samantha", "Right", "2"));
items.add(new Owner("Regie", "Miller", "3"));
items.add(new Owner("Mark", "Adam", "4"));
} catch(Exception ex)
{
ex.toString();
}
return items;
}
@Override
protected void onPostExecute(List<Owner> result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
}
}
//My customize Layout for the listfragment
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ListView
android:id="@id/android:list"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
<TextView
android:id="@id/android:empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="No record to be displayed." />
</LinearLayout>
//Updated on 07/30 @10:50 AM //Here is the Exception
07-30 14:18:15.155: E/AndroidRuntime(864): FATAL EXCEPTION: main 07-30 14:18:15.155: E/AndroidRuntime(864): java.lang.NullPointerException 07-30 14:18:15.155: E/AndroidRuntime(864): at com.mb.carlovers.adapter.OwnerAdapter.getView(OwnerAdapter.java:48) 07-30 14:18:15.155: E/AndroidRuntime(864): at android.widget.AbsListView.obtainView(AbsListView.java:2033) 07-30 14:18:15.155: E/AndroidRuntime(864): at android.widget.ListView.onMeasure(ListView.java:1127) 07-30 14:18:15.155: E/AndroidRuntime(864): at android.view.View.measure(View.java:12603) 07-30 14:18:15.155: E/AndroidRuntime(864): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4677) 07-30 14:18:15.155: E/AndroidRuntime(864): at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1369) 07-30 14:18:15.155: E/AndroidRuntime(864): at android.widget.LinearLayout.measureVertical(LinearLayout.java:660) 07-30 14:18:15.155: E/AndroidRuntime(864): at android.widget.LinearLayout.onMeasure(LinearLayout.java:553) 07-30 14:18:15.155: E/AndroidRuntime(864): at android.view.View.measure(View.java:12603) 07-30 14:18:15.155: E/AndroidRuntime(864): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4677) 07-30 14:18:15.155: E/AndroidRuntime(864): at android.widget.FrameLayout.onMeasure(FrameLayout.java:293) 07-30 14:18:15.155: E/AndroidRuntime(864): at android.view.View.measure(View.java:12603) 07-30 14:18:15.155: E/AndroidRuntime(864): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4677) 07-30 14:18:15.155: E/AndroidRuntime(864): at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1369)
@btse is spot on! You could simply send an empty items
list to the custom adapter, then call notifyDataSetChanged()
on the onPostExecute
of your AsyncTask
. Android handles populating your ListFragment
after this call.
You could even place a "Please search owner" type message when the adapter is empty (reference here) in your xml:
<TextView android:id="@id/android:empty"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FF0000"
android:text="Please search owner"/>
if you didn't want to leave it blank.
Good luck!