I'm developing Excel report with hierarchy data.
Using JETT (java excel template translator) and I'd like to duplicate rows from the main loop when there are collection of collection. Here is a brief example.
public class JettTest {
#Test
public void run() throws IOException {
ClassLoader classLoader = getClass().getClassLoader();
InputStream template = classLoader.getResourceAsStream("template.xlsx");
try (
XSSFWorkbook wb = new XSSFWorkbook(template);
FileOutputStream fos = new FileOutputStream("target/output.xlsx")
) {
Map<String, Object> params = new HashMap<>();
Parent parent1 = new Parent("parent1", Arrays.asList("child1", "child2"));
Parent parent2 = new Parent("parent2", Arrays.asList("childX", "childY"));
List<Parent> parents = Arrays.asList(parent1, parent2);
params.put("parents", parents);
ExcelTransformer transformer = new ExcelTransformer();
transformer.transform(wb, params);
wb.write(fos);
}
}
public class Parent {
private String name;
private List<String> children;
public Parent(String name, List<String> children) {
this.name = name;
this.children = children;
}
public String getName() {
return name;
}
public List<String> getChildren() {
return children;
}
}
}
Excel template is
A1 is
<jt:forEach items="${parents}" var="parent">${parent.name}
B1 is
<jt:forEach items="${parent.children}" var="child">${child}</jt:forEach></jt:forEach>
This gives me
It looks good, however, I need to duplicate parent names and get
Any ideas, please?
You'll need {parent.name} to be within the child forEach tag if you want the parent name to be displayed for each child name.
What happens if you move the child forEach tag from B1 to A1, right after the parent forEach tag?
Related
I have three linked lists called "Titles" (String linked list), "Descriptions" (String linked list), and "Pictures" (Bitmap linked list). I'm 100% sure that they are full of data. I've printed out their data just before the line MyAdapter myAdapter = new MyAdapter(this, Titles, Descriptions, Pictures); and it has exactly the data I expect ("MyAdapter" is a class). However, in the MyAdapter class, all three linked lists are null, as I get the following error:
2022-08-07 19:13:03.009 14983-14983/com.example.usshop E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.usshop, PID: 14983
java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.util.LinkedList.add(java.lang.Object)' on a null object reference
at com.example.usshop.MyAdapter.<init>(MyAdapter.java:30)
at com.example.usshop.Shop.CreateItems(Shop.java:70)
at com.example.usshop.Shop$1.onDataChange(Shop.java:56)
at com.google.firebase.database.core.ValueEventRegistration.fireEvent(ValueEventRegistration.java:75)
at com.google.firebase.database.core.view.DataEvent.fire(DataEvent.java:63)
at com.google.firebase.database.core.view.EventRaiser$1.run(EventRaiser.java:55)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:237)
at android.app.ActivityThread.main(ActivityThread.java:8167)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:496)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1100)
Below is the code of the two classes (Note: for the "Shop" class, the "CreateItems" method mainly matters because it sends the data to the other class. Included the rest in case it somehow affects the issue):
public class Shop extends AppCompatActivity {
RecyclerView rv;
//Below is unimportant; ignore.
/*
String s1[], s2[];
int images[] = {R.drawable.apple, R.drawable.banana, R.drawable.graoe,
R.drawable.orange, R.drawable.pineapple, R.drawable.peach};
*/
LinkedList<String> Titles = new LinkedList<>(), Descriptions = new LinkedList<>();
LinkedList<Integer> Prices = new LinkedList<>();
LinkedList<Bitmap> Pictures = new LinkedList<>();
DatabaseReference ItemsReference = FirebaseDatabase.getInstance().getReference("Items");
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_shop);
//Whenever the value of ItemsReference changes, it is stored
ItemsReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
// Storing all of the data
for (DataSnapshot DS : snapshot.getChildren()) {
BackendDataStorage TempData = DS.getValue(BackendDataStorage.class);
Titles.add(TempData.getTitle());
Descriptions.add(TempData.getDescription());
Prices.add(TempData.getPrice());
Pictures.add(Extras.StringToBitMap(TempData.getPicture()));
}
CreateItems();
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
Log.d("Error", "Failed to read value: " + error.getMessage());
}
});
}
public void CreateItems () {
Log.d("index", Titles.get(0)); // Just making sure Titles isn't null
rv = findViewById(R.id.Recycler_View);
MyAdapter myAdapter = new MyAdapter(this, Titles, Descriptions, Pictures);
rv.setAdapter(myAdapter);
rv.setLayoutManager(new LinearLayoutManager(this));
}
}
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private LinkedList<String> data1, data2;
private LinkedList<Bitmap> images;
private Context context;
public MyAdapter (Context ct, LinkedList<String> s1, LinkedList<String> s2, LinkedList<Bitmap> img) {
context = ct;
// Looping through LinkedList indexes & replacing with new variables
for (int i = 0; i < s1.size(); i++) {
data1.add(s1.get(i));
data2.add(s2.get(i));
images.add(img.get(i));
}
}
}
However, in the MyAdapter class, all three linked lists are null
No, they are not. You have misread the error message. The error is not about any of the arguments you pass to the MyAdapter constructor, but about a member of the MyAdapter class.
Note for instance that there is no error on evaluating s1.size() in the for loop heading, so s1 is not null.
But the error is not about s1, s2 or img. It is about calling the add method on a null reference:
java.lang.NullPointerException: Attempt to invoke virtual method boolean java.util.LinkedList.add(java.lang.Object) on a null object reference
The line where add is called, is here:
data1.add(s1.get(i));
So, data1 is null. And this is indeed the case. Your class has a private instance member called data1 which has not been initialised. You need to do something like:
data1 = new LinkedList<String>();
having this Jaxb Xml definition, i try to remove the Map Elements Wrapper by adding #XmlPath(".") but it cause exception during the unmarchaling
#XmlRootElement
public abstract class ViewElement{
#XmlJavaTypeAdapter(value=EventAdapter.class)
public Map<Event, String> getEvents() {
}
private transient Class entityType;
public Class getEntityType() {
return entityType;
}
}
And the EventAdapter is
public class EventAdapter extends XmlAdapter<EventAdapter.AdaptedMap, Map<Event, String>> {
public static class AdaptedMap {
#XmlVariableNode("key")
List<AdaptedEntry> entries = new ArrayList<AdaptedEntry>();
}
public static class AdaptedEntry {
#XmlTransient
public String key;
#XmlValue
public String value;
}
.....
}
my output was
<element>
<events>
<onCellEdit>do some thing<onCellEdit>
</events>
<entityType>com.agitech.erp.model.erp.ErpFolder</entityType>
<element>
I try to remove the <events> tag by adding #XmlPath(".")
#XmlPath(".")
#XmlJavaTypeAdapter(value=EventAdapter.class)
public Map<Event, String> getEvents() {
}
The output is good
<element>
<onCellEdit>do some thing<onCellEdit>
<entityType>com.agitech.erp.model.erp.ErpFolder</entityType>
<element>
but the unmarchaling faileds
Caused by: Exception [EclipseLink-3002] (Eclipse Persistence Services - 2.6.0.v20140809-296a69f): org.eclipse.persistence.exceptions.ConversionException
Exception Description: The object [], of class [class java.lang.String], from mapping [org.eclipse.persistence.oxm.mappings.XMLDirectMapping[entityType-->view.entityType/text()]] with descriptor [XMLDescriptor(com.agitech.erp.view.BeanView --> [DatabaseTable(view), DatabaseTable(viewFrame), DatabaseTable(viewElement)])], could not be converted to [class java.lang.Class].
Internal Exception: java.lang.ClassNotFoundException:
at org.eclipse.persistence.exceptions.ConversionException.couldNotBeConvertedToClass(ConversionException.java:95)
at org.eclipse.persistence.internal.helper.ConversionManager.convertObjectToClass(ConversionManager.java:446)
Debuging Jaxb bring me to the line
org.eclipse.persistence.internal.oxm.XMLDirectMappingNodeValue
public void endElement(XPathFragment xPathFragment, UnmarshalRecord unmarshalRecord) {
...
line 205 unmarshalRecord.setAttributeValue(convertedValue, xmlDirectMapping);
}
During the unmarchaling of entityType value, the UnmarshalRecordImpl.currentObj contains the EventAdapter instead of the parent element
I modify org.eclipse.persistence.internal.oxm.record.UnmarshalRecordImpl
public XPathNode getNonAttributeXPathNode(String namespaceURI, String localName, String qName, Attributes attributes) {
....
if(null == resultNode && null == nonPredicateNode) {
// ANY MAPPING
resultNode = xPathNode.getAnyNode();
// by default it return the EventAdapter, changing it to NULL fix my problem
}
....
}
Not a safe solution
I have been able to reproduce the issue that you are seeing, but haven't yet worked out the cause. You can use the following bug to track the progress on this issue:
http://bugs.eclipse.org/457169
After trying a lot of things, I was able to find a workaround for this issue. I thought of posting here the same so it can be helpful to someone else in the future. The lead has confirmed the issue around 5 years ago but seems like they have not fixed it and I was facing a similar issue.
Basically, we can use the beforeMarshal and afterUnmarshal methods to change the values in the fields.
You need to create a field List<Object> with #XmlAnyElement(lax=true) along with Map<String,Object>.
Remove the #XmlPath(".") and the XMLAdapter class.
Mark the field Map<String, Object> with #XmlTransient.
Now within the beforeMarshal and afterMarshal fields, you can exchange the data. During the unmarshal in beforeunmarshal, all the unknown field values will be present within the List<Object> loop over it and add it to the Map<String, Object>.
Similarly during the marshaling, you can move the values Map<String, Object> to List<Object> by creating the DOM elements.
Marshaling all values are added to root as DOM Elements are present and during Unmarshaling known values are read first and then-unknown values are stored within List<Object> due to #XmlAnyElement.
I have created an example using the Customer class, you can modify it accordingly for your need.
#JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, visible = true, property = "isA")
#JsonInclude(Include.NON_NULL)
#JsonIgnoreProperties(ignoreUnknown = true)
#XmlRootElement(name = "Customer")
#XmlType(name = "Customer", propOrder = {"name", "age", "otherElements"})
#XmlAccessorType(XmlAccessType.FIELD)
#Getter
#Setter
#AllArgsConstructor
#ToString
#NoArgsConstructor
public class Customer {
#XmlTransient
private String isA;
private String name;
private String age;
#XmlAnyElement(lax = true)
#JsonIgnore
private List<Object> otherElements = new ArrayList<>();
#JsonIgnore
#XmlTransient
private Map<String, Object> userExtensions = new HashMap<>();
#JsonAnyGetter
#JsonSerialize(using = CustomExtensionsSerializer.class)
public Map<String, Object> getUserExtensions() {
return userExtensions;
}
#JsonAnySetter
public void setUserExtensions(String key, Object value) {
userExtensions.put(key, value);
}
private void beforeMarshal(Marshaller m) throws ParserConfigurationException {
System.out.println("Before Marshalling User Extension: " + userExtensions);
ExtensionsModifier extensionsModifier = new ExtensionsModifier();
otherElements = extensionsModifier.Marshalling(userExtensions);
System.out.println("Before Marshalling Final Other Elements " + otherElements);
userExtensions = new HashMap<>();
}
private void afterUnmarshal(Unmarshaller m, Object parent) throws ParserConfigurationException {
System.out.println("After Unmarshalling : " + otherElements);
ExtensionsModifier extensionsModifier = new ExtensionsModifier();
userExtensions = extensionsModifier.Unmarshalling(otherElements);
otherElements = new ArrayList();
}
}
You can refer the creation of DOM ELEMENTS here:https://stackoverflow.com/a/24239105/7584240
You can refer my complete answer here: https://stackoverflow.com/a/67923216/7584240
im stuck into some problem, need guidance !
i have a TableView that has 2 ComboBoxTableCells, my requirement is to update the list in combobox of 2nd cell on change of the first.
i have tried it the following way,no luck so far.
public class Test{
private StringProperty name;
private StringProperty city;
public Test(String name, String city){
this.name = new SimpleStringProperty(name);
this.city = new SimpleStringProperty(city);
}
public String getName() {
return name.get();
}
public void setName(String name) {
this.name.setValue(name);
}
public String getCity() {
return city.get();
}
public void setCity(String city) {
this.city.setValue(city);
}
public StringProperty nameProperty() {return name;}
public StringProperty cityProperty() {return city;}
}
TableView _table= new TableView();
final ObservableList list = FXCollections.observableArrayList();
list.add("name 1");
list.add("name 2");
list.add("name 3");
list.add("name 4");
final ObservableList list2 = FXCollections.observableArrayList();
list2.add("city 1");
list2.add("city 2");
list2.add("city 3");
list2.add("city 4");
TableColumn firstNameCol = new TableColumn("First Name");
firstNameCol.setMinWidth(100);
firstNameCol.setCellValueFactory(new PropertyValueFactory<Test, String>("name"));
firstNameCol.setCellFactory(ComboBoxTableCell.forTableColumn(list));
firstNameCol.setOnEditCommit(
new EventHandler<CellEditEvent<Test, String>>() {
#Override
public void handle(CellEditEvent<Test, String> t) {
((Test) t.getTableView().getItems().get(t.getTablePosition().getRow())).setName(t.getNewValue());
System.out.println(t.getTableColumn().getCellData(t.getTablePosition().getRow()));
i guess have to do something here, tried the following line to see the impact on the respective cell
list2.clear();
it updated data for the whole column i just want it to be updated for the respective cell only.
}
}
);
TableColumn lastNameCol = new TableColumn("City");
lastNameCol.setMinWidth(100);
lastNameCol.setCellValueFactory(
new PropertyValueFactory<Test, String>("city"));
lastNameCol.setCellFactory(ComboBoxTableCell.forTableColumn(list2));
lastNameCol.setOnEditCommit(
new EventHandler<CellEditEvent<Test, String>>() {
#Override
public void handle(CellEditEvent<Test, String> t) {
((Test) t.getTableView().getItems().get(
t.getTablePosition().getRow())
).setName(t.getNewValue());
}
}
);
_table.setEditable(true);
_table.getColumns().addAll(firstNameCol,lastNameCol);
ObservableList listItems = FXCollections.observableArrayList();
listItems.add(new Test("name 4", "city 2"));
listItems.add(new Test("name 2", "city 3"));
table.getTableView().setItems(listItems);
_table.setItems(listItems);
any help will be highly appreciated. thanks
Here's a hacky approach that I haven't tested:
Add a dummy (boolean?) property on the data items that you will use to communicate between firstNameCol and lastNameCol
In the onEditCommit handler for firstNameCol, change the value of the dummy property. Be sure it changes.
Have lastNameCol be a column for the dummy property. Register a cell factory for lastNameCol that returns a TableCell with an overriden updateItem() method (pseudo-code below)
lastNameCol.setCellFactory(new Callback() {
#Override
public TableCell call(TableColumn col) {
return new TableCell() {
#Override
public void updateItem(Boolean item, boolean empty) {
if (!empty) {
// Don't care about the value of item
// Just look up the value of firstNameCol using
// getTablePosition(), then create and populate
// a ComboBox with the appropriate items and set
// it as the graphic for this cell via this.setGraphic()
// Add handler to ComboBox control to update data item when
// selection changes
}
}
};
}
});
Senior Geeks.
I'd like to request a simple but fully working example of how to implement an ExpandableListView while extending from BaseExpandableListAdapter Yet Reading data from an Sqlite Database.
I have researched and experimented on the question (see here), but with minimal success where i was able to display some data in the header, albeit it was same values repeating for all group headers. Also child items don't show.
The reason for extending with BaseExpandableListAdapter is to have a custom layout for the group header. The reason for SQLite access is naturally because thats where my data is stored.
All examples trawled on the net so far use either SimpleCursorTreeAdapter or CursorTreeAdapter as the extender in DB based applications or simply BaseExpandableListAdapter when data used is in ArrayLists.
Below is the Experimentation thus far. (with this code,only the group header is populated with the same figures over and over. Childitems dont appear)
public class ExpandableListViewAdapterCustom extends BaseExpandableListAdapter {
protected Activity currentActivity;
public ExpandableListViewAdapterCustom(Activity callingActivity){
this.currentActivity = callingActivity;
}
private Cursor mGroupsCursorLocal ;
private Cursor mChildCursor;
private Context ctx;
private int groupItem;
private int childItem;
private String[] fieldsToUseFromGroupCursor;
private int[] screenTextsToMapGroupDataTo;
private String[] fieldsToUseFromChildCursor;
private int[] screenTextsToMapChildDataTo;
public ArrayList<String> tempChild;
public LayoutInflater minflater;
public Activity activity;
public int intGroupTotal;
public void setCurrentActivity(Activity activity) {
this.activity = activity;
}
public void setCtx(Context ctx) {
this.ctx = ctx;
}
public void setGroupItem(int groupItem) {
this.groupItem = groupItem;
}
public void setChildItem(int childItem) {
this.childItem = childItem;
}
public Activity getCurrentActivity() {
return currentActivity;
}
public Cursor getmGroupsCursorLocal() {
return mGroupsCursorLocal;
}
public Context getCtx() {
return currentActivity.getBaseContext();
}
public void setmGroupsCursorLocal(Cursor mGroupsCursor) {
this.mGroupsCursorLocal = mGroupsCursor;
}
public ExpandableListViewAdapterCustom(Cursor mGroupsCursor,
Activity activity,
int groupItem,
int childItem,
String[] fieldsToUseFromGroupCursor,
int[] screenTextsToMapGroupDataTo,
String[] fieldsToUseFromChildCursor,
int[] screenTextsToMapChildDataTo) {
DatabaseRoutines db = new DatabaseRoutines(activity);
setmGroupsCursorLocal(mGroupsCursor);
mGroupsCursorLocal = db.fetchGroup();
activity.startManagingCursor (mGroupsCursor);
mGroupsCursorLocal.moveToFirst();
mChildCursor=db.fetchChildren(mGroupsCursorLocal.getColumnIndex("Year"));
mChildCursor.moveToFirst();
activity.startManagingCursor(mChildCursor);
setCtx(activity);
setCurrentActivity(activity);
}
public void setInflater(LayoutInflater mInflater, Activity act) {
this.minflater = mInflater;
activity = act;
}
#Override
public Object getChild(int groupPosition, int childPosition) {
return null;
}
#Override
public long getChildId(int groupPosition, int childPosition) {
return 0;
}
#Override
public View getChildView(int groupPosition,
int childPosition,boolean
isLastChild,
View convertView,
ViewGroup parent) {
View v = convertView;
if (v == null)
{
LayoutInflater inflater =
(LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.exp_listview_childrow, parent, false);
}
TextView txtMonth = (TextView) v.findViewById(R.id.txtMonth);
TextView txtMonthAmountSent = (TextView)
v.findViewById(R.id.txtMonthAmountSentValue);
TextView txtMonthReceived = (TextView)
v.findViewById(R.id.txtMonthAmountReceivedValue);
txtMonth.setText(mChildCursor.getString(mChildCursor.getColumnIndex("Month")));
txtMonthAmountSent.setText
(mChildCursor.getString(mChildCursor.getColumnIndex("TotalSent")));
txtMonthReceived.setText
(mChildCursor.getString(mChildCursor.getColumnIndex("TotalReceived")));
return v;
}
#Override
public int getChildrenCount(int groupPosition) {
return (mChildCursor.getCount());
}
#Override
public Object getGroup(int groupPosition) {
return null;
}
#Override
public int getGroupCount() {
return mGroupsCursorLocal.getCount();
}
#Override
public void onGroupCollapsed(int groupPosition) {
super.onGroupCollapsed(groupPosition);
}
#Override
public void onGroupExpanded(int groupPosition) {
super.onGroupExpanded(groupPosition);
}
#Override
public long getGroupId(int groupPosition) {
return 0;
}
#Override
public View getGroupView(
int groupPosition,
boolean isExpanded,
View convertView,
ViewGroup parent)
{
View v = convertView;
if (v == null) {
LayoutInflater inflater =
(LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.exp_listview_groupheader, parent, false);
}
TextView txtYear = (TextView) v.findViewById(R.id.txtYearValue);
TextView txtAmountSent = (TextView) v.findViewById(R.id.txtAmountSentValue);
TextView txtAmountRecieved = (TextView)
v.findViewById(R.id.txtAmountReceivedValue);
txtYear.setText(mGroupsCursorLocal.getString(
mGroupsCursorLocal.getColumnIndex("Year")));
txtAmountSent.setText(
mGroupsCursorLocal.getString(mGroupsCursorLocal.getColumnIndex("TotalSent")));
txtAmountRecieved.setText(
GroupsCursorLocal.getString(mGroupsCursorLocal.getColumnIndex("TotalReceived")));
return v;
}
#Override
public boolean hasStableIds() {
return true;
}
#Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return false;
}
}
The Database code is like this
public Cursor fetchGroup() {
SQLiteDatabase db = this.getReadableDatabase(); //if memory leaks check here
String query = "SELECT DISTINCT MIN(ID) AS id,
Year, SUM(SentAmount) AS TotalSent, SUM(ReceivedAmount) AS TotalReceived
FROM MyTbl GROUP BY Year ORDER BY Year DESC ";
return db.rawQuery(query, null);}
public Cursor fetchChildren(int Yr) {
SQLiteDatabase db = this.getReadableDatabase(); //if memory leaks check here
String query = "SELECT MIN(ID) AS id,
Year, Month, SUM(SentAmount) AS TotalSent,
SUM(ReceivedAmount) AS TotalReceived
FROM MyTbl Where Year= "+ Yr +" GROUP BY Year,
Month ORDER BY Year DESC, Month DESC";
return db.rawQuery(query, null);
}
The Code is called from main activity using the following
ExpandableListView elv = (ExpandableListView)
findViewById(R.id.expandableListView);
ExpandableListAdapter mAdapter = new
ExpandableListViewAdapterCustom(mGroupsCursor,
MyActivity.this,
R.layout.exp_listview_groupheader,// Your row layout for a group
R.layout.exp_listview_childrow, // Your row layout for a child
new String[] { "Year",
"TotalSent",
"TotalReceived" },// Field(s) to use from group cursor
new int[] {R.id.txtYearValue,
R.id.txtAmountSentValue,
R.id.txtAmountReceivedValue },// Widget ids to put group data
into new String[] { "Year","Month",
"TotalSent",
"TotalReceived" }, // Field(s) to use from child cursors new
int[] {R.id.txtMonthValue,
R.id.txtMonthAmountSentValue,
R.id.txtMonthAmountReceivedValue});// Widget ids to put child d
data into
elv.setClickable(true);
elv.setAdapter(mAdapter); // set the
After almost two weeks and no answer, i decided to simply use an ExpandableListView example using ArrayLists and modified it such that the ArrayLists were populated by data from the DB. Its not what i wanted but it works. I was actually suprised that nowhwere on the web is there an example of using ExpandableListview extended form BaseAdapter but reading from SQlite using say cursorTreeAdapter or SimpleCursorAdapter.
Below is how i did it in case it helps someone in future. the code shown is the bit that populates the ArrayList from DB
public ArrayList<ExpandListGroup> SetStandardGroups() {
ArrayList<ExpandListGroup> list = new ArrayList<ExpandListGroup>();
ArrayList<ExpandListChild> list2 = new ArrayList<ExpandListChild>();
int intMonthNum;
ExpandListGroup grp;
ExpandListChild chld;
//initialize db code here
DatabaseRoutines db = new DatabaseRoutines(this);
//create the Groups retreival cursor;
Cursor mGroupsCursor = db.fetchGroup();
//---the database call is done using this code which is in my
//---custom db class which implements the sqlhelper methods etc
//------start of db code snippet-------------------------------
//---public Cursor fetchGroup() {
//---SQLiteDatabase db = this.getReadableDatabase();
//--- String query = "SELECT DISTINCT MIN(ID) AS id, Year,
//--- SUM(SentAmount) AS TotalSent,
//--- SUM(ReceivedAmount) AS TotalReceived
//--- FROM Tbl GROUP BY Year ORDER BY Year DESC ";
//--- return db.rawQuery(query, null);}
//------end of db code snippet-------------------------------
mGroupsCursor.moveToFirst();
//method is depreciated from api14 but i'm targeting Gingerbread (api10) so i need to use it.
startManagingCursor(mGroupsCursor);
int intYear;
int intHeaderCounter = 0;
int intChildCounter = 0;
int intChildTotalCount = 0;
int intHeaderTotalGroupCount = mGroupsCursor.getCount();
//set the starting Year for the loop, if there is data;
if (intHeaderTotalGroupCount > 0) {
//get the first year
//intYear = mGroupsCursor.getInt(mGroupsCursor.getColumnIndex("Year"));
for (intHeaderCounter = 0; intHeaderCounter < intHeaderTotalGroupCount; intHeaderCounter++) {
grp = new ExpandListGroup();
intYear = mGroupsCursor.getInt(mGroupsCursor.getColumnIndex("Year"));
grp.setYear(intYear);
grp.setYearAmountReceived(mGroupsCursor.getDouble(mGroupsCursor.getColumnIndex("TotalReceived")));
grp.setYearAmountSent(mGroupsCursor.getDouble(mGroupsCursor.getColumnIndex("TotalSent")));
grp.setTag(mGroupsCursor.getString(mGroupsCursor.getColumnIndex("id")));
//Prepare counters for inner loop for child items of each
Cursor mChildCursor = db.fetchChildren(intYear);
mChildCursor.moveToFirst();
intChildTotalCount = mChildCursor.getCount();
//populate child items
for (intChildCounter = 0; intChildCounter < intChildTotalCount; intChildCounter++) {
chld = new ExpandListChild();
intMonthNum = mChildCursor.getInt(mChildCursor.getColumnIndex("Month"));
chld.setMonthNumber(intMonthNum);
chld.setTotalReceivedMonth(mChildCursor.getInt(mChildCursor.getColumnIndex("TotalReceived")));
chld.setTotalSentMonth(mChildCursor.getInt(mChildCursor.getColumnIndex("TotalSent")));
chld.setTag(mGroupsCursor.getString(mGroupsCursor.getColumnIndex("id")).toString());
list2.add(chld);
//grp.setItems(list2);
//move to next child record;
mChildCursor.moveToNext();
}
grp.setItems(list2);
list.add(grp);
list2 = new ArrayList<ExpandListChild>();
//move to next parent record;
mGroupsCursor.moveToNext();
}
} else {
log.d( "yourdebugtag_here", "Sorry, No Transactions Found.");
}
//db.close();
return list;
}
For some reason, I keep receiving the following error:
java.lang.IllegalStateException: the specified child already has a parent. You must call removeView() on the child's parent view
I am using the following code:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.listitem);
//url is fetched from another class
readWebpage(imdbUrl);
}
private class DownloadWebPageTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
}
#Override
protected void onPostExecute(String result) {
//textView.setText(result);
displayMoviesList(result);
}
}
public void readWebpage(String imdbUrl) {
}
public void displayMoviesList(String result) {
JSONObject responseObj = null;
try {
responseObj = new JSONObject(result);
JSONObject Obj = responseObj.getJSONObject("results");
JSONArray moviesListObj = Obj.getJSONArray("result");
for(int i=0 ;i<moviesListObj.length();i++) {
JSONObject e = moviesListObj.getJSONObject(i);
cover[i] = e.getString("cover");
title[i] = e.getString("title");
year[i] = e.getString("year");
director[i] = e.getString("director");
rating[i] = e.getString("rating");
details[i] = e.getString("details");
}
tl = (TableLayout) findViewById(R.id.main_table);
imgView = (ImageView)findViewById(R.id.imageID);
progressbar = (ProgressBar) findViewById(R.id.loadingBar);
//new loadImageTask().execute(cover[i].toString());
new loadImageTask().execute( URL);// it calls another function..
TextView title = (TextView)findViewById(R.id.titleID);
title.setText("TEXT");
TableRow tr = new TableRow(this);
tr.addView(imgView);
tr.addView(title);
tl.addView(tr, new TableLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
} catch(JSONException e) {
//Log.e("log_tag", "Error parsing data " + e.toString());
}
I am not sure why I'm receiving the error, but it appears to be being generated while I am adding it to the view.
Solution is that we either we define the rows in .xml file or in our .java file. I was adding the rows dynamically in my java file and using addView. So in .xml file we cannot add another view (we should not add rows for the same).