Problem: I have two TableLayouts
that have delete row buttons in each TableRow
. When the deleteTableRows()
method is called, it has no issue deleting rows for the FILES table, but it fails with a null
object error on the AUTHOR table. I've been debugging for hours and can't identify the null
causing the issue? I was hoping someone may see what I can't.
What I have done: I've had this working for months but I felt it necessary to split a setupDeleteRowButton
method into two separate methods because I needed independent control of layoutParam
adjustments for each TableLayout
. I figured I could refactor later. Otherwise, the two methods are virutally identical.
I have a deleteTableRow()
method that deletes rows from TableLayouts
called by the OnClickListener
. The two methods that created the TableRows
dynamically for the TableLayouts
add a tag
based identifier for each row created, so when the deleteTableRows()
method is called, the correct row is deleted based upon the tag
identifier.
What is happening: I'm not seeing any null
s debugging? When I delete a File table row, using the tag as you see in the deleteTableRows()
method below - no issue! When I do with the Author table, I get a 'java.lang.String java.lang.Object.toString()' on a null object reference -- but I'm not seeing it? Confused? I've check for null on the table
, tblRow
and tag
variables and nothing is null.
**I've included the working "File" version to compare to the "Author" version of code. I'm still learning Android, so my methods may be a bit clumsy. The TableLayouts are created at the XML activity and all rows added dynamically... including headers.
The delete method it fails here on the if
statement this method is called by the setup[table]DeleteRowButton()
methods
public static void deleteTableRows(TableLayout table, String tag){
for (int i=1; i < table.getChildCount(); i++){
TableRow tblRow = (TableRow) table.getChildAt(i);
if(tblRow.getTag().toString().equals(tag)) {
table.removeView(tblRow);
break;
}
}
}
I'm seeing and receiving these on the if
statement above This is row 187 in the error below and row 167 in the method call by the OnClickListener
in the code below
The two setup[table]DeleteRowButton
methods (the OnClickListeners are setup the same, passing a unique tag) - called by the setup[table]TableRow()
methods
I'm not sure I have an issue with either of these but the "File" version's call to the deleteTableRows()
has not issue, the call from the "Author" version apparently does? They both pass String
tags, and so the .toString()
is used.
public static Button setupFileDeleteRowButton(Context context, TableLayout table, String tag){
Button btnDelete = new Button(context);
TableRow.LayoutParams trLayoutParams = new TableRow.LayoutParams(0, TableRow.LayoutParams.WRAP_CONTENT);
trLayoutParams.setMargins(3,3,3,3);
trLayoutParams.weight = 1;
trLayoutParams.height =75;
btnDelete.setLayoutParams(trLayoutParams);
btnDelete.setBackgroundColor(Color.WHITE);
btnDelete.setText("-");
btnDelete.setTypeface(Typeface.DEFAULT,Typeface.BOLD);
btnDelete.setTextSize(14);
btnDelete.setGravity(Gravity.CENTER);
btnDelete.setPadding(5,5,5,5);
btnDelete.setTag(tag);
btnDelete.setOnClickListener(v -> {
String btnTag = btnDelete.getTag().toString();
deleteTableRows(table, btnTag);
});
return btnDelete;
}
public static Button setupAuthorDeleteRowButton(Context context, TableLayout table, String tag){
Button btnDelete = new Button(context);
TableRow.LayoutParams trLayoutParams = new TableRow.LayoutParams(0, TableRow.LayoutParams.WRAP_CONTENT);
trLayoutParams.setMargins(3,3,3,3);
trLayoutParams.weight = 0.05f;
trLayoutParams.height =75;
btnDelete.setLayoutParams(trLayoutParams);
btnDelete.setBackgroundColor(Color.WHITE);
btnDelete.setText("-");
btnDelete.setTypeface(Typeface.DEFAULT,Typeface.BOLD);
btnDelete.setTextSize(14);
btnDelete.setGravity(Gravity.CENTER);
btnDelete.setPadding(5,5,5,5);
btnDelete.setTag(tag);
btnDelete.setOnClickListener(v -> {
String btnTag = btnDelete.getTag().toString();
deleteTableRows(table, btnTag);
});
return btnDelete;
}
The two methods that create and pass the table and the specific tags info (Again, no issues with the "Files", just "Author"
row.addView(setupFileDeleteRowButton(context, table, fileName));
for(int r=1; r < 2; r++){
row.setTag(fileName);
row.addView(addRowTextViewToTable(context, fileName, false));
row.setClickable(true);
}
row.addView(setupAuthorDeleteRowButton(context, table, DateTimestampManager.currentTimestamp()));
for(int r=1; r<5;r++) {
row.addView(addEditTextToTable(context, ""));
row.setClickable(true);
Log.e("BuildTableLayout", "addEditTextToTable");
}
I found my fix. I'm still at a loss as to why the previous setup worked with "FILE" version but not the "AUTHOR", but this fix works for both. That being said, it does make sense to look at the getChildAt(0)
position since that is always the button position and receives the setTag
. Anyhow, here is the fix. I had to include the .getChildAt(0)
on the tblRow
then get the tag and check.
public static void deleteTableRows(TableLayout table, String tag){
for (int i=1; i < table.getChildCount(); i++){
TableRow tblRow = (TableRow) table.getChildAt(i);
if(tblRow.getChildAt(0).getTag().toString().equals(tag)) {
table.removeView(tblRow);
break;
}
}
}