So, I have scoured the interwebs and I cannot find a solution for this based on other people's experiences, so I am posting this issue. (Please note that this is my 1st android app experience and I am debugging / updating an existing app.)
When I implement my custom NotesListAdapter (extends BaseAdapter) on the ListView, mListNotesView (mListNotesView.setAdapter(this)), and load the data into the ArrayList mNoteList, the getView function is not being called. Also, I found that mListNotesView.setBackgroundResource is not chaning the background of the control, either. I have a similar implementation on a previous activity that works exactly correct. When I copied over the class and changed it to handle my ArrayList, it broke. I have getCount returning the ArrayList size(), which is not 0, and getItemId returns position. I have a feeling it may be my XML or my setup because it's acting like the ListView is not visible. I am perplexed. How do I get the ListView to show? Anything inside of the getView has not been reached so it may be buggy.
ViewTicketOrderActivity (Some parts ommitted for size)
public class ViewTicketOrderActivity extends Activity {
MySQLDatabase myDataBase;
Ticket mTicket;
public ArrayList<Notes> mNotes = new ArrayList<Notes>();
String mErrorString;
Button mAddUpdateButton;
Button mAcceptButton;
//Button mViewNotesButton;
NotesListAdapter mNotesListAdapter;
static final int ERROR_DIALOG = 0;
static final int SUCCESS_DIALOG = 1;
static final int COMPLETED_DIALOG = 2;
static final int RESTART_DIALOG = 3;
static final int LOADING = 0;
static final int LOAD_ERROR = 1;
static final int LOADED = 4;
static final String TICKET_EXTRA = "ticket_extra";
static final String TAG = "ViewTicketOrderActivity";
private static final boolean gDebugLog = false;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.viewticketorder);
Activity context = this;
String theTitle = "Sundance Ticket Order";
theTitle += (MySQLDatabase.TESTING == true) ? " (DEV SERVER)" : " (LIVE)";
setTitle(theTitle);
myDataBase = MySQLDatabase.getMySQLDatabase(this);
if (gDebugLog) {
DebugLogger.logString(TAG, ".onCreate");
}
mNotesListAdapter = new NotesListAdapter(context, R.id.note_list);
Log.d(this.toString(),this.mNotesListAdapter.toString());
}
private class NotesListAdapter extends BaseAdapter {
private LayoutInflater mInflater;
private ArrayList<Notes> mNoteList;
private ListView mListNotesView;
private Activity mActivity;
int mState = LOADING;
String mErrorMessage;
private NotesListAdapter(Activity context, int listViewID) {
mActivity = context;
mNoteList = new ArrayList<Notes>();
mInflater = LayoutInflater.from(context);
mListNotesView = (ListView)context.findViewById(listViewID);
mListNotesView.setBackgroundResource(R.color.emergency_red);
mListNotesView.setAdapter(this);
Log.d(mListNotesView.toString(), String.valueOf(mListNotesView.getCount()));
this.notifyDataSetChanged();
//mListNotesView.setVisibility(View.VISIBLE);
}
void setLoading()
{
mState = LOADING;
this.notifyDataSetChanged();
}
void setLoadError(String errorString)
{
mState = LOAD_ERROR;
mErrorMessage = errorString;
this.notifyDataSetChanged();
}
void setNoteList(ArrayList<Notes> inNotes)
{
mState = LOADED;
mNoteList.clear();
mNoteList.addAll(inNotes);
Log.d("SetNoteList", "TRUE " + inNotes);
//mNoteList = mNotes;
this.notifyDataSetChanged();
}
/**
* Use the array index as a unique id.
*
* @see android.widget.ListAdapter#getItemId(int)
*/
@Override
public long getItemId(int position) {
return position;
}
public int getCount(){
if (mState == LOADED) {
Log.d("getCount",String.valueOf(mNoteList.size()));
return mNoteList.size();
} else {
return 0;
}
}
/**
* Make a view to hold each row.
*
* @see android.widget.ListAdapter#getView(int, android.view.View,
* android.view.ViewGroup)
*/
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// A ViewHolder keeps references to children views to avoid unneccessary calls
// to findViewById() on each row.
Log.d("getView",this.toString());
if (mState == LOADED) {
ViewHolder holder;
// When convertView is not null, we can reuse it directly, there
// is no need
// to reinflate it. We only inflate a new View when the
// convertView supplied
// by ListView is null.
Notes note = this.getItem(position);
if (convertView == null) {
/*if (ticket.emergency())
{
convertView = mInflater.inflate(R.layout.emergency_ticket_list_item_opt,
null);
}
else
{
convertView = mInflater.inflate(R.layout.ticket_list_item,
null);
}*/
convertView = mInflater.inflate(R.layout.noteslist_item,
null);
// Creates a ViewHolder and store references to the two
// children views
// we want to bind data to.
holder = new ViewHolder();
holder.noteText = (TextView) convertView
.findViewById(R.id.text_note);
holder.dateText = (TextView) convertView
.findViewById(R.id.text_note_date);
holder.createByText = (TextView) convertView
.findViewById(R.id.text_note_by);
holder.createByIDText = (TextView) convertView
.findViewById(R.id.text_note_by_id);
convertView.setTag(holder);
} else {
// Get the ViewHolder back to get fast access to the
// TextView
// and the ImageView.
holder = (ViewHolder) convertView.getTag();
}
// Bind the data efficiently with the holder.
holder.noteText.setText(note.note());
holder.dateText.setText(note.date());
holder.createByText.setText(note.createBy());
holder.createByIDText.setText(note.employeeID());
if(!mTicket.employeeID().equals(note.employeeID())){
convertView.setBackgroundResource(R.drawable.solid_purple);
}
} else if (mState == LOADING ) {
if (convertView == null) {
convertView = mInflater.inflate(R.layout.loading_view,
null);
}
TextView messageText = (TextView)convertView.findViewById(R.id.message);
messageText.setText("Loading tickets");
} else if (mState == LOAD_ERROR) {
if (convertView == null) {
convertView = mInflater.inflate(R.layout.load_error_view,
null);
}
TextView messageText = (TextView)convertView.findViewById(R.id.message);
messageText.setText("Error loading tickets");
String errorString = mErrorMessage != null ? mErrorMessage : "";
TextView errorText = (TextView)convertView.findViewById(R.id.errorText);
errorText.setText(errorString);
}
return convertView;
}
class ViewHolder {
TextView noteText;
TextView dateText;
TextView createByText;
TextView createByIDText;
}
//@Override
/*public int getCount() {
*//*if (mState == LOADED) {
*//*
Log.d("getCount mState " + mState,String.valueOf(mNoteList.size())+", "+String.valueOf(mNotes.size()));
return mNoteList.size();
*//*} else {
Log.d("getCount mState " + mState,"0");
return 0;
}*//*
}*/
@Override
public Notes getItem(int position) {
Log.d("getItem",mNoteList.get(position).toString());
return mNoteList.get(position);
}
@Override
public int getItemViewType (int position) {
int result = mState;
Log.d("getItemId",String.valueOf(position));
return result;
}
@Override
public int getViewTypeCount ()
{
return 4;
}
}
protected void onResume() {
super.onResume();
Bundle extras = getIntent().getExtras();
if(extras !=null)
{
mTicket = (Ticket)extras.getSerializable(TICKET_EXTRA);
}
else
{
mTicket = new Ticket();
}
if (mTicket.emergency())
{
setContentView(R.layout.view_emergency_ticketorder);
}
else
{
setContentView(R.layout.viewticketorder);
}
if (gDebugLog)
{
DebugLogger.logString(TAG, ".onResume mTicket " + mTicket);
}
TicketCheckService.clearNotificationForNewTicket(mTicket);
new GetTicketTask().execute();
new GetNotesTask().execute();
updateDisplayedTicket();
}
private void updateDisplayedTicket() {
mAddUpdateButton = (Button)findViewById(R.id.addUpdateButton);
mAcceptButton = (Button)findViewById(R.id.acceptButton);
//mViewNotesButton = (Button)findViewById(R.id.viewNotesButton);
String ticketStatus = myDataBase.getDescriptionStringForStatusString(mTicket.status());
if(ticketStatus == "Job Rejected") {
mAddUpdateButton.setText("Restart Job");
} else {
mAddUpdateButton.setText("Add Update");
}
if(ticketStatus == "Requested") {
mAcceptButton.setText("Accept");
} else if(ticketStatus != "Requested") {
mAcceptButton.setText("Back");
}
//mViewNotesButton.setText(R.string.viewNotes);
TextView idText = (TextView)findViewById(R.id.textTicketID);
idText.setText(mTicket.id());
//TextView descriptionText = (TextView)findViewById(R.id.textDescription);
//descriptionText.setText(mTicket.description());
TextView titleText = (TextView)findViewById(R.id.textTitle);
titleText.setText(mTicket.title());
TextView storeIDText = (TextView)findViewById(R.id.textStoreID);
storeIDText.setText(mTicket.store());
String formatPhone;
TextView storePhoneText = (TextView)findViewById(R.id.textStorePhone);
if(mTicket.phoneNo().isEmpty()){
formatPhone = "NO PHONE NO.";
} else {
storePhoneText = (TextView) findViewById(R.id.textStorePhone);
formatPhone = mTicket.phoneNo().replaceFirst("(\\d{3})(\\d{3})(\\d+)", "($1)$2-$3");
storePhoneText.setOnClickListener(new CallClickListener(mTicket.phoneNo()));
}
storePhoneText.setText(formatPhone);
TextView categoryText = (TextView)findViewById(R.id.textCategory);
String categoryDescription = MySQLDatabase.getDescriptionStringForCategoryString(mTicket.category());
categoryText.setText(categoryDescription);
if(ticketStatus == "Completed Pending") {
showDialog(COMPLETED_DIALOG);
}
}
public void onClickAccept(View v) {
try {
boolean maint = myDataBase.getSystemMaintStatus();
if(maint) {
setLoadError("The phone app is down for maintenance.");
return;
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(mAcceptButton.getText() =="Accept") {
mAddUpdateButton.setEnabled(false);
mAcceptButton.setEnabled(false);
new AcceptTicketTask().execute();
} else {
finish();
}
}
public void onClickAddUpdate(View v) {
try {
boolean maint = myDataBase.getSystemMaintStatus();
if(maint) {
setLoadError("The phone app is down for maintenance.");
return;
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(mAddUpdateButton.getText() =="Add Update") {
Intent i = new Intent(this, UpdateTicketActivity.class);
i.putExtra(UpdateTicketActivity.TICKET_EXTRA, mTicket);
startActivity(i);
} else if(mAddUpdateButton.getText() =="Restart Job") {
mAddUpdateButton.setEnabled(false);
mAcceptButton.setEnabled(false);
new RestartTicketTask().execute();
}
}
private class AcceptTicketTask extends AsyncTask<Void, Integer, String>
{
protected String doInBackground(Void... parent) {
mErrorString = null;
String result = null;
String updateTime = DateFormat.getDateTimeInstance().format(new Date(0));
try {
boolean success = myDataBase.updateTicket(mTicket.id(), mTicket.employeeID(), mTicket.description(), "1", updateTime, null);
if (!success)
{
result = "Could not update Ticket";
}
} catch (IOException e) {
// TODO Auto-generated catch block
result = "Could not update Ticket - " + e.getLocalizedMessage();
e.printStackTrace();
}
return result;
}
protected void onProgressUpdate(Integer... progress) {
}
protected void onPostExecute(String errorString) {
if (null != errorString) {
mErrorString = errorString;
showDialog(ERROR_DIALOG);
} else {
showDialog(SUCCESS_DIALOG);
mAcceptButton.setText("Back");
}
mAddUpdateButton.setEnabled(true);
mAcceptButton.setEnabled(true);
}
}
private class RestartTicketTask extends AsyncTask<Void, Integer, String>
{
protected String doInBackground(Void... parent) {
mErrorString = null;
String result = null;
String updateTime = DateFormat.getDateTimeInstance().format(new Date(0));
try {
boolean success = myDataBase.updateTicket(mTicket.id(), mTicket.employeeID(), mTicket.description(), "7", updateTime, null);
if (!success)
{
result = "Could not update Ticket";
}
} catch (IOException e) {
// TODO Auto-generated catch block
result = "Could not update Ticket - " + e.getLocalizedMessage();
e.printStackTrace();
}
return result;
}
protected void onProgressUpdate(Integer... progress) {
}
protected void onPostExecute(String errorString)
{
if (null != errorString) {
mErrorString = errorString;
showDialog(ERROR_DIALOG);
} else {
showDialog(RESTART_DIALOG);
mAcceptButton.setText("Done");
mAddUpdateButton.setText("Add Update");
}
mAddUpdateButton.setEnabled(true);
mAcceptButton.setEnabled(true);
}
}
private class GetTicketTask extends AsyncTask<Void, Integer, Ticket>
{
String mError = null;
protected Ticket doInBackground(Void... parent) {
Ticket result = null;
try {
result = myDataBase.getTicketWithID(mTicket.id(), mTicket.employeeID());
} catch (IOException e) {
// TODO Auto-generated catch block
mError = e.getLocalizedMessage();
e.printStackTrace();
}
return result;
}
protected void onProgressUpdate(Integer... progress) {
}
protected void onPostExecute(Ticket result)
{
if (null != result) {
mTicket = result;
} else {
setLoadError(mError);
}
}
}
private class GetNotesTask extends AsyncTask<Void, Integer, ArrayList<Notes>> {
String mError = null;
protected ArrayList<Notes> doInBackground(Void... parent) {
ArrayList<Notes> result = new ArrayList<Notes>();
try {
result = myDataBase.getTicketNotes(mTicket.id());
} catch (IOException e) {
// TODO Auto-generated catch block
myDataBase.debugLog("Error caught" + e);
mError = e.getLocalizedMessage();
e.printStackTrace();
}
return result;
}
protected void onProgressUpdate(Integer... progress) {
}
protected void onPostExecute(ArrayList<Notes> result) {
if (null != result) {
Log.d("Result", result.toString());
mNotes = result;
} else {
Log.d("SetNoteList","FALSE");
mNotesListAdapter.setLoadError(mError);
}
}
}
private void updateDisplayedNotes(){
ArrayList<Notes> newNotes = mNotes;
if(newNotes != null) {
mNotesListAdapter.setNoteList(newNotes);
}
}
/*private class updateDisplayedNotes extends AsyncTask<Void, Integer, ArrayList<Notes>> {
public ArrayList<Notes> newNotes = new ArrayList<Notes>();
public updateDisplayedNotes(){
super();
Log.d(this.toString(), "Updating");
}
protected ArrayList<Notes> doInBackground(Void... parent) {
Log.d(this.toString(), "Background Task");
for (Notes note : mNotes) {
Log.d(this.toString(),note.toString());
if(note != null) {
Log.d(this.toString(), "Note Added");
newNotes.add(note);
}
}
return newNotes;
}
protected void onPostExecute(ArrayList<Notes> newNotes)
{
if(newNotes != null) {
mNotes.clear();
mNotes.addAll(newNotes);
mNotesListAdapter.setNoteList(mNotes);
}
}
}*/
void setLoadError(String error) {
setContentView(R.layout.load_error_view);
TextView messageText = (TextView)findViewById(R.id.message);
messageText.setText("Error loading ticket");
String errorString = error != null ? error : "";
TextView errorText = (TextView)findViewById(R.id.errorText);
errorText.setText(errorString);
finish();
}
}
viewticketorder.xml (where note_list is)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/background"
android:orientation="vertical"
tools:context=".ViewTicketOrderActivity"
tools:ignore="HardcodedText" >
<TextView
android:id="@+id/textTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="3dp"
android:paddingLeft="3dp"
android:paddingRight="3dp"
android:text="@string/loadingTicket"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="@color/white_color"
android:textSize="20dp"
android:textIsSelectable="true"
android:background="@drawable/title_transparent_bg"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:id="@+id/TextView01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
android:paddingTop="2dp"
android:paddingLeft="10dp"
android:text="@string/ticketID"
android:textAppearance="?android:attr/textAppearanceSmall"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/textTicketID"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="3dp"
android:textAppearance="?android:attr/textAppearanceSmall"
android:focusable="true"
android:textColor="@color/white_color"
android:textIsSelectable="true"/>
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginTop="3dp"
android:paddingTop="2dp"
android:text="@string/storeID"
android:textAppearance="?android:attr/textAppearanceSmall"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/textStoreID"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="3dp"
android:textAppearance="?android:attr/textAppearanceSmall"
android:focusable="true"
android:textColor="@color/white_color"
android:textIsSelectable="true"/>
<TextView
android:id="@+id/textStorePhone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="3dp"
android:textAppearance="?android:attr/textAppearanceSmall"
android:focusable="true"
android:textColor="@color/white_color"
android:textIsSelectable="true"
/>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:id="@+id/TextView05"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:paddingTop="2dp"
android:text="@string/category"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:id="@+id/textCategory"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:gravity="center_vertical"
android:text=""
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="@color/white_color"
android:focusable="true"
android:textIsSelectable="true"/>
</LinearLayout>
<ListView
android:id="@+id/note_list"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="5"
android:divider="@drawable/ticket_item_divider"
android:dividerHeight="1dp"
tools:ignore="NestedWeights"
android:choiceMode="singleChoice"
android:clickable="true"
android:background="@drawable/title_transparent_bg">
</ListView>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<Button
android:id="@+id/acceptButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="2dp"
android:layout_weight="1"
android:onClick="onClickAccept" />
<Button
android:id="@+id/addUpdateButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="2dp"
android:layout_marginRight="10dp"
android:layout_weight="1"
android:onClick="onClickAddUpdate" />
</LinearLayout>
</LinearLayout>
notelist_item.xml (inflator)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/text_note_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#80FFFFFF"
android:orientation="vertical"
>
<TextView
android:id="@+id/text_note"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:text="@string/filler_string"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@color/text_item_color"
android:textSize="@dimen/big_text_item_size" />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_weight=".70"
>
<TextView
android:id="@+id/text_note_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:text="@string/filler_string"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="@color/text_sub_item_color" />
<TextView
android:id="@+id/text_note_by"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:text="@string/filler_string"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="@color/text_sub_item_color" />
<TextView
android:id="@+id/text_note_by_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:text="@string/filler_string"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="@color/text_sub_item_color" />
</LinearLayout>
</LinearLayout>