I'm trying to take data from a backend(I'm using parse.com), put it into an array and use it to populate a ListView via an adapter. I parse multiple objects into a list and then put "names" and "ids" into two separate string arrays.
Now, my problem is that data disappears as soon as I add the next position to the array. I've spent quite a while figuring this out with debug logs, and it appears as if names[0] is displayed in the log properly when requested right after I write it. If I try to access names[0] after writing names[1] I get a null pointer exception - println needs a message, and the app crashes. When not trying to access the data via debug log, the listview is populated by a proper number of entries, yet the data that should've come from names[] and ids[] is empty. Here's the code where everything goes horribly wrong:
names = new String[2];
ids = new String[2];
ParseQuery<ParseObject> query = ParseQuery.getQuery("TestItem");
query.findInBackground(new FindCallback<ParseObject>() {
public void done(List<ParseObject> objects, ParseException e) {
if (e == null) {
int size = objects.size();
int i = 0;
ParseObject obj;
while (i < size) {
obj = objects.get(i);
names[i] = obj.getString("name");
ids[i] = obj.getString("objectId");
i++;
}
/*The following code is fairly irrelevant(I think?) since the error appears
to be somewhere in the previous lines.*/
Bundle bundel = new Bundle();
bundel.putStringArray("names", names);
bundel.putStringArray("ids", ids);
ft = getSupportFragmentManager().beginTransaction();
screen = new Feed().newInstance(bundel);
ft.add(R.id.holder_frame, screen);
ft.commit();
} else {
}
}
});
I feel like it's something basic about managing arrays, but I can't seem to understand it. Please help :(
The following line seems to be fishy:
new Feed().newInstance(bundel);
newInstance method should be static method.
Make sure that you are adding the appropriate instance of fragment with the bundle information. If you don't figure it out, provide code in the Fragment.
Consider code below:
ParseQuery<ParseObject> query = ParseQuery.getQuery("TestItem");
query.findInBackground(new FindCallback<ParseObject>() {
public void done(List<ParseObject> objects, ParseException e) {
if (e == null) {
int size = objects.size();
String[] names = new String[size];
String[] ids = new String[size];
for (int i = 0; i < size; i++) {
ParseObject elem = objects.get(i);
names[i] = elem.getString("name");
ids[i] = elem.getObjectId();
}
/*The following code is fairly irrelevant(I think?) since the error appears
to be somewhere in the previous lines.*/
Bundle params = new Bundle();
params.putStringArray("names", names);
params.putStringArray("ids", ids);
ft = getSupportFragmentManager().beginTransaction();
screen = new Feed();
screen.setArguments(params);
ft.add(R.id.holder_frame, screen);
ft.commit();
} else {
Toast.make(<Current>Activity.this, "Error", ...).show();
}
}
});
I think this might be the problem:
int size = objects.size();
int i = 0;
ParseObject obj;
while (i < size) {
obj = objects.get(i);
names[i] = obj.getString("name");
ids[i] = obj.getString("objectId");
i++;
}
names and ids are initialised as
names = new String[2];
ids = new String[2];
You are looping over all of the elements in objects so if it has any more than two elements you will be writing outside the bounds of the names and ids arrays.
Related
I'm learning to program in Java for Android Studio. I'm working with a Parse.com query downloading information. I store the information inside an array of a costume object called MyData. When I'm storing the information I can log the content of the array and it has the correct info. But latter when I try to use the same array, if I use the .length function it says it's null. And if I try to retrieve any of the information, it's empty.
This I my object:
public class MyData {
Integer gluc;
Integer insulinaV;
Date fec;
Integer alimento;
String comentarios;
public MyData(Integer gluc, Integer insulinaV, Date fec, Integer alimento, String comentarios) {
this.gluc = gluc;
this.insulinaV = insulinaV;
this.fec = fec;
this.alimento = alimento;
this.comentarios = comentarios;
}
public Integer getGluc() {
return gluc;
}
public Integer getInsulinaV() {
return insulinaV;
}
public Date getFec() {
return fec;
}
public Integer getAlimento() {
return alimento;
}
public String getComentarios() {
return comentarios;
}
}
So, to retrieve the information I use array[I].getWhatever(), this is how I store the information:
public void downloadInformation() {
user = ParseUser.getCurrentUser();
ParseQuery<ParseObject> query = ParseQuery.getQuery("Glucosa");
query.whereEqualTo("usuario", user);
query.orderByDescending("createdAt");
query.findInBackground(new FindCallback<ParseObject>() {
#Override
public void done(List<ParseObject> objects, ParseException e) {
if (e == null && objects.size() > 0) {
Log.d("score!", "Objects Retrived");
Log.d("size", String.valueOf(objects.size()));
int i = 0;
indexsize = 0;
for (ParseObject object : objects) {
dataArray = new MyData[objects.size()];
dataArray[i] = new MyData(object.getInt("glucosa"), object.getInt("insulina"), object.getDate("fecha"), object.getInt("Alimentos"), object.getString("Comentarios"));
String alimentosexiste = dataArray[i].getAlimento().toString();
Log.i("Is Empty or Not=", alimentosexiste);
indexsize = indexsize+1;
i++;
}
} else {
Log.d("failed", "error");
}
}
});
}
In my logcat I'm getting "Score! Objects retrieved" and "Size: 22", also I get a list with all 22 elements of the "Is Empty or Not" Log. So far so good.
Then, In my attempt to move from this activity to another, I try to save the dataArray with:
public void saveInformation() {
int j = indexsize;
Log.i("size of index?", String.valueOf(indexsize));
for (int i=0; i<=j; i++) {
Log.i("index", String.valueOf(i));
alimentosVal = dataArray[i].getAlimento();
comentariosVal = dataArray[i].getComentarios();
glucVal = dataArray[i].getGluc();
insulinaVal = dataArray[i].getInsulinaV();
fecVal = dataArray[i].getFec();
}
SQLiteDatabase myGlucosebase = this.openOrCreateDatabase("GlucoseEvents", MODE_PRIVATE, null);
myGlucosebase.execSQL("CREATE TABLE IF NOT EXISTS glucoseevents (alimentos INT(2), comentarios VARCHAR, gluc INT(4), insulinv INT(4), fec DATETIME)");
myGlucosebase.execSQL("INSERT INTO glucoseevents (alimentos, comentarios, gluc, insulinv, fec) VALUES (alimentosVal, comentariosVal, glucVal, insulinaVal, fecVal) ");
}
And even do I printed before the content of the array with index [0] (so I'm sure the information got stored in the array), I get the following error:
Attempt to invoke virtual method 'java.lang.Integer com.parse.starter.MyData.getAlimento()' on a null object reference
I've seen that the problem is that I'm pointing to an empty element, but it was working before, how can I do this?
(Data array is declared at the beginning, below the class name as: MyData[] dataArray;)
Thanks!
dataArray = new MyData[objects.size()]; should be outside the for loop
Your class MyData does not have a "dataArray". At least not in the example code you give above.
I currently face the following issue:
I am trying to refactor a recursive algorithm to an iterative one. What this recursive algorithm does is this:
method1 is passed some initial parameters. Based on a processing that takes place at the beginning of method1, method2 is invoked with these parameters. Now method2 uses some conditions and based on the one that is satisfied method1 is invoked again with the appropriate parameters.
Now, based on the answer on the link I've provided above I did the same thing. But I have to pass parameters around so I did this:
Stack<ArrayList<Object>> stack (the stack for the ArrayList<Object> objects)
ArrayList<Object> parametersForSync = new ArrayList<Object>();
ArrayList<Object> paramForHandle = new ArrayList<Object>();
(Each array list of objects is a list of the parameters to be passed to both the methods. The first array list is for the first method and the second for the second method.)
Assuming I pop and push array lists down the stack correctly I face the following issue which is my main problem and the reason of this question:
Within method2 I have to check whether the object (that was on the array list and is passed to the method) is an instanceof another class of mine. Now I have some conditions there which do not get satisfied when in fact they should.
Is this because of java's type erasure?
Is there anyway to overcome this?
If am not clear at a certain point in my explanations please ask me to clarify.
Edit:
What follows is the code that replaces the recursion that goes like this:
syncWithServer(parameter set x){
handleResultArray(parameter set y);
};
handleResultArray(parameter set ){
syncWithServer(parameter set w)
}
===========================================================
Stack<ArrayList<Object>> stack = new Stack<ArrayList<Object>>();
ArrayList<Object> paramList = new ArrayList<Object>();
paramList.add(oeHelper);
paramList.add(false);
paramList.add(domain);
paramList.add(null);
paramList.add(true);
paramList.add(10000);
paramList.add(true);
stack.push(paramList);
int counter = 0;
ArrayList<Object> parametersForSync = new ArrayList<Object>();
ArrayList<Object> paramForHandle = new ArrayList<Object>();
while (!stack.isEmpty()) {
Log.d(TAG, "Loop: " + counter);
parametersForSync = stack.pop();
paramForHandle = ((OEHelper) parametersForSync.get(0))
.syncWithServer(
// why error here?
(boolean) parametersForSync.get(1),
(OEDomain) parametersForSync.get(2),
(List<Object>) parametersForSync.get(3),
(boolean) parametersForSync.get(4),
(int) parametersForSync.get(5),
(boolean) parametersForSync.get(6));
parametersForSync = ((OEHelper) paramForHandle.get(3))
.handleResultArray(
(OEFieldsHelper) paramForHandle.get(0),
(JSONArray) paramForHandle.get(1),
(boolean) paramForHandle.get(2));
if (parametersForSync.size() != 0) {
stack.push(parametersForSync);
}
counter++;
Now the first method:
public ArrayList<Object> syncWithServer(boolean twoWay, OEDomain domain,
List<Object> ids, boolean limitedData, int limits,
boolean removeLocalIfNotExists) {
Log.d(TAG, "syncWithServer");
List<OEColumn> dbCols = mDatabase.getDatabaseColumns();
List<OEColumn> dbFinalList = new ArrayList<OEColumn>();
ArrayList<Object> parametersList = new ArrayList<Object>();
Log.d(TAG, "Columns & finalList created");
for (OEColumn col : dbCols) {
if (!mOne2ManyCols.contains(col.getName())) {
dbFinalList.add(col);
}
}
OEFieldsHelper fields = new OEFieldsHelper(dbFinalList);
try {
if (domain == null) {
domain = new OEDomain();
}
if (ids != null) {
domain.add("id", "in", ids);
}
if (limitedData) {
mPref = new PreferenceManager(mContext);
int data_limit = mPref.getInt("sync_data_limit", 60);
domain.add("create_date", ">=",
OEDate.getDateBefore(data_limit));
}
if (limits == -1) {
limits = 50;
}
Log.d(TAG, "*****.search_read() started");
JSONObject result = *****.search_read(mDatabase.getModelName(),
fields.get(), domain.get(), 0, limits, null, null);
Log.d(TAG, "***.search_read() returned");
mAffectedRows = result.getJSONArray("records").length();
parametersList.add(fields);
parametersList.add(result.getJSONArray("records"));
parametersList.add(removeLocalIfNotExists);
parametersList.add(OEHelper.this);
//This parametersList contains the parameters that must be used to invoke the next method
Now the second method:
=================================================
public ArrayList<Object> handleResultArray(
OEFieldsHelper fields, JSONArray results,
boolean removeLocalIfNotExists) {
Log.d(TAG, "handleResultArray");
ArrayList<Object> parametersList = new ArrayList<Object>();
// ArrayList<Object> parameterStack = new ArrayList<Object>();
try {
fields.addAll(results);
List<OERelationData> rel_models = fields.getRelationData();
Log.d(TAG, "rel_models: "+rel_models.size());
for (OERelationData rel : rel_models) {
// Handling many2many records
if (rel.getDb().getClass()==OEManyToMany.class
/*instanceof OEManyToMany*/) {//TODO type erasure?
Log.v(TAG, "Syncing ManyToMany Records");
OEManyToMany m2mObj = (OEManyToMany) rel.getDb();
OEHelper oe = ((OEDatabase) m2mObj.getDBHelper())
.getOEInstance();
parametersList.add(oe);
parametersList.add(false);
parametersList.add(null);
parametersList.add(rel.getIds());
parametersList.add(false);
parametersList.add(0);
parametersList.add(false);
return parametersList;
} else if (rel.getDb().getClass()==OEManyToOne.class
/*instanceof OEManyToOne*/) {
// Handling many2One records
Log.v(TAG, "Syncing ManyToOne Records");
// M2OCounter++;
OEManyToOne m2oObj = (OEManyToOne) rel.getDb();
OEHelper oe = ((OEDatabase) m2oObj.getDBHelper())
.getOEInstance();
parametersList.add(oe);
parametersList.add(false);
parametersList.add(null);
parametersList.add(rel.getIds());
parametersList.add(false);
parametersList.add(0);
parametersList.add(false);
// parametersMap.put(Counter, parametersList);
// parameterStack.add(parametersList);
return parametersList;
} else if (rel.getDb().getClass()==OEOneToMany.class
/*instanceof OEOneToMany*/) {
Log.v(TAG, "Syncing OneToMany Records");
// O2MCounter++;
OEOneToMany o2mObj = (OEOneToMany) rel.getDb();
OEHelper oe = ((OEDatabase) o2mObj.getDBHelper())
.getOEInstance();
oe.setOne2ManyCol(o2mObj.getColumnName());
parametersList.add(oe);
parametersList.add(false);
parametersList.add(null);
parametersList.add(rel.getIds());
parametersList.add(false);
parametersList.add(0);
parametersList.add(false);
// parametersMap.put(Counter, parametersList);
// parameterStack.add(parametersList);
return parametersList;
} else {
Log.v(TAG, "Syncing records with no relations"
+ rel.getDb().getClass().getSimpleName());
OEHelper oe = ((OEDatabase) rel.getDb()).getOEInstance();
parametersList.add(oe);
parametersList.add(false);
parametersList.add(null);
parametersList.add(rel.getIds());
parametersList.add(false);
parametersList.add(0);
parametersList.add(false);
return parametersList;//TODO when nothing matches this returns
}
}
List<Long> result_ids = mDatabase.createORReplace(
fields.getValues(), removeLocalIfNotExists);
mResultIds.addAll(result_ids);
mRemovedRecordss.addAll(mDatabase.getRemovedRecords());
} catch (Exception e) {
e.printStackTrace();
}
return parametersList;
}
The second method is supposed to return from within one of the conditions but none of the conditions is met
No - it is not a type erasure problem. As Oracle says:
Type erasure ensures that no new classes are created for parameterized
types; consequently, generics incur no runtime overhead.
So at runtime your classes are just plain classes and your objects are what they are, but it is not going to remove the base type information.
Why not put a log statement in and print out the class of the object?
I am trying to create a method that will update a list that has already been created. Im not sure why this is not working?
It throws a null pointer exception.
This is my code:
private void UpdateJList(){
String query = "SELECT * FROM names WHERE TYA=?";
String partialSearch = "Sales";
try{
connect.pst = connect.con.prepareStatement(query);
connect.pst.setString(1, partialSearch);
connect.pst.execute();
ArrayList<String> add = new ArrayList<String>();
String[] items = {};
while (connect.rs.next()){
String result = connect.rs.getString("ACNO");
add.add(result);
int length = add.size();
DefaultListModel<String> model;
model = new DefaultListModel<String>();
for (int i=0; i<length; i++){
model.add(i, result);
}
jList1.setModel(model);
jList1.setSelectedIndex(0);
}
}catch(Exception e){
JOptionPane.showMessageDialog(null, e);
}
}
Thank you in advance!!
There are 2 major problems with that code:
In the while loop, you are creating many instances of DefaultListModel. That means, for each entry of the query result, you are restarting the list.
A nullpointer exception is produced by the line: connect.rs.next() because you didn't assign connect.rs with the query's resultset.
I am using Blackberry Plug-in and i am using Rich Lists of blackberry.
I want to make lists appear the same number of times as there are entries in the database table.
I m using the below code but it shows only one name in list view.
I need to show all the entries in database into list view...Kindly help me..
I have already used list.add(); inside the for loop but it is showing Exception: java.lang.IllegalStateException: Field added to a manager while it is already parented.
public static void richlistshow(){
String name = null;
list = new RichList(mainManager, true, 2, 0);
Bitmap logoBitmap = Bitmap.getBitmapResource("delete.png");
delete = new BitmapField(logoBitmap, Field.FIELD_HCENTER);
for (int c = 0; c < target_list.size();c++){
City tar_city = new City();
tar_city = (City)target_list.elementAt(c);
name = tar_city.get_city_name().toString();
}
//adding lists to the screen
list.add(new Object[] {delete,name,"time-date"});
}
You didn't posted full codes you are working with. But following code may help you to get rid of IllegalStateException. You were adding same BitmapField instance for every list entries, which caused the exception.
public static void richlistshow() {
final Bitmap logoBitmap = Bitmap.getBitmapResource("delete.png");
list = new RichList(mainManager, true, 2, 0);
for (int c = 0; c < target_list.size(); c++) {
// create a new BitmapField for every entry.
// An UI Field can't have more than one parent.
final BitmapField delete = new BitmapField(logoBitmap, Field.FIELD_HCENTER);
City tar_city = (City) target_list.elementAt(c);
final String name = tar_city.get_city_name().toString();
// add to list
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
list.add(new Object[] { delete, name, "time-date" });
}
});
}
}
i have a simple doubt in android programming. I am not familiar with java coding.so it might be a simple problem.
In the first two lines I am retrieving an array, which i passed from another activity to this activity...Then i am creating an array list . I am creating an object in the 4th line. Now comes the problem ...
I have to run a for loop to get the url value, which i have to pass it in the BaseFeedParser class. but i cant use the 4th line, i.e creating the object inside the loop because it will create a new object each time... which should not happen ... how can i fix this probelm?
Intent myintent = getIntent();
String[] ActiveURL = myintent.getStringArrayExtra("URL");
List<String> titles = new ArrayList<String>();
BaseFeedParser parser = new BaseFeedParser(url);
// fetching all active URLs
for (int i = 0; i < ActiveURL.length + 1; i++) {
url = ActiveURL[i];
messages.addAll(parser.parse());
}
// now getting the titles out of the messages for display
for (Message msg : messages) {
titles.add(msg.getTitle());
}
Thanks in advance ...
There are some problems in your java code :
Intent myintent = getIntent();
//variables are named in camel case, starting with a lower case letter
String[] activeURL = myintent.getStringArrayExtra("URL");
List<String> titles = new ArrayList<String>();
//we will use parser later, see below
//BaseFeedParser parser = new BaseFeedParser(url);
// fetching all active URLs
//it's very easy to loop through a table in java / C / C++
//learn the pattern, it's the simplest, you got confused with the final index
for (int i = 0; i < activeURL.length ; i++) {
//here you don't change the former object url was referencing,
//you are saying that you give the name url to another object in the array
//it doesn't create any new item, change giving them a name to use them
url = activeURL[i];
//create a new parser for each url, except if they can be recycled
//i.e they have a property setUrl
messages.addAll( new BaseFeedParser(url).parse());
}
// now getting the titles out of the messages for display
for (Message msg : messages) {
titles.add(msg.getTitle());
}
Indeed, you could even shorten the whole thing by
Intent myintent = getIntent();
String[] activeURL = myintent.getStringArrayExtra("URL");
List<String> titles = new ArrayList<String>();
// fetching all active URLs
//use a for each loop
for ( String url : activeURL ) {
//loop through messages parsed from feed to add titles
for (Message msg : new BaseFeedParser(url).parse() ) {
titles.add(msg.getTitle());
}
}
if you don't need the List of Message you called messages.