I need to implement an algorithm that access to the database to check the last elemnt in order to calculate the new one. Of course, the first time it would be impossible because the database is empty and I get
IndexOutOfBoundsException) index 0 requested with a size of 0
To avoid it, I tried to check if cursor.getCount==0, and then I introduce a default first element. The problem is that, even when I have stored it in the database, cursor.getCount keeps being 0. Here is the code of my method:
public Measures getLastMeasure(String date) {
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(TABLE_MEASURES, new String[] { KEY_ID,
KEY_DATE, KEY_TIME_HOUR, KEY_TIME_MINUTE, KEY_BE_INTAKE,
KEY_GLUCOSE, KEY_BOLUS, KEY_BASAL }, KEY_DATE + "=?",
new String[] { date }, null, null, KEY_TIME_HOUR + " DESC, "
+ KEY_TIME_MINUTE + " DESC", "1");
if (cursor.getCount() == 0) {
Measures m = new Measures("nodate", 0, 0, 0, 0, 0, 0);
return m;
} else {
if (cursor != null)
cursor.moveToFirst();
Measures m = new Measures(Long.parseLong(cursor.getString(0)), // id
cursor.getString(1), // date
Integer.parseInt(cursor.getString(2)), // timeHour
Integer.parseInt(cursor.getString(3)), // timeMinute
Double.parseDouble(cursor.getString(4)), // BE intake
Double.parseDouble(cursor.getString(5)), // glucose
Double.parseDouble(cursor.getString(6)), // bolus
Double.parseDouble(cursor.getString(7)) // basal
);
// return m
return m;
}
}
I hope you can help me. Thanks in advance to everyone.
I could be missing something, but that code looks correct to me. Are you certain that the data you're looking for is actually in the database and that the argument you're passing to getLastMeasure() is correct?
Looks like your query returns no data matching your search. If you only want latest data by date, I suggest order by KEY_DATE desc and limit 1, or max(KEY_DATE) instead of KEY_DATE + "=?"
Side note: no need to check if cursor is null (SQLiteDatabase#query never returns a null Cursor), and anyway your check is useless because you're accessing cursor even if it's null. Also you're not closing the Cursor.
Related
My cursor is crashing my application with the android database error.
CursorIndexOutOfBoundsException: Index -1 requested, with a size of 1
I made another much less optimized slider that scans my database and I find the good value.
public Cursor getAllDataTableStaffDatabase(String table_name){
this.open();
Cursor result =this.mDb.rawQuery("SELECT * FROM " + table_name,null);
return result;// fonctionne très bien
}
public String findNameOfStaffBymail(String mail) {
String sql = " SELECT * FROM " + DatabaseStaffHandler.STAFF_TABLE_NAME + " WHERE " + DatabaseStaffHandler.STAFF_MAIL + " = ? ";
Cursor result = super.mDb.rawQuery(sql, new String[]{mail});
Cursor data = super.getAllDataTableStaffDatabase(DatabaseStaffHandler.STAFF_TABLE_NAME);
String test = result.getString(1); //error
while (data.moveToNext()) {
if (data.getString(3).equals(mail)) {
viewAll();
return data.getString(1);
}
}
}
I would like to retrieve the value name that corresponds to the email address.
This usually happens when you do not have the data in your Cursor and you are still trying to access the data. It is similar to the ArrayIndexOutOfBoundsException. I found nothing wrong with your query so far. However, I think you might consider adding null checking in your code which will prevent your application from crashing. Especially in the while loop, you need to put a null check in the condition.
And you need to use the moveToFirst function wherever necessary.
public Cursor getAllDataTableStaffDatabase(String table_name) {
this.open();
Cursor result = this.mDb.rawQuery("SELECT * FROM " + table_name,null);
return result;
}
public String findNameOfStaffBymail(String mail) {
String sql = " SELECT * FROM " + DatabaseStaffHandler.STAFF_TABLE_NAME + " WHERE " + DatabaseStaffHandler.STAFF_MAIL + " = ? ";
Cursor result = super.mDb.rawQuery(sql, new String[]{mail});
Cursor data = super.getAllDataTableStaffDatabase(DatabaseStaffHandler.STAFF_TABLE_NAME);
// Add a null checking here.
if (result != null) {
result.moveToFirst();
String test = result.getString(1);
}
if(data != null) data.moveToFirst();
while (data != null) {
if (data.getString(3).equals(mail)) {
viewAll();
return data.getString(1);
}
data.moveToNext();
}
}
Hope that solves your problem.
Thank you for your reply. I found my problem thanks to you. I wonder if the cursor does not boot at the end. But it is good practice to check if received is not null. Thank you and have a nice day
I am using an Arraylist to fetch all the available contacts in my application. This is not efficient because the Arraylist takes a long time to fetch and populate the Listview as there are almost 600+ contacts.
I'm seeking an alternative approach that would have better performance.
Although I searched for other relevant questions but I was't able to find the convenient one.
Here is my java code:
private List<String> getContactList() {
List<String> stringList=new ArrayList<>();
ContentResolver cr = context.getContentResolver();
Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI,
null, null, null, null);
if ((cur != null ? cur.getCount() : 0) > 0) {
while (cur != null && cur.moveToNext()) {
String id = cur.getString(
cur.getColumnIndex(ContactsContract.Contacts._ID));
String name = cur.getString(cur.getColumnIndex(
ContactsContract.Contacts.DISPLAY_NAME)
);
if (cur.getInt(cur.getColumnIndex(
ContactsContract.Contacts.HAS_PHONE_NUMBER)) > 0) {
Cursor pCur = cr.query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?",
new String[]{id}, null
);
while (pCur.moveToNext()) {
String phoneNo = pCur.getString(pCur.getColumnIndex(
ContactsContract.CommonDataKinds.Phone.NUMBER));
Log.v("Data : ",""+id+" "+name+" "+phoneNo);
stringList.add(id);
stringList.add(name);
stringList.add(phoneNo);
}
pCur.close();
}
}
}
if(cur!=null){
cur.close();
}
return stringList;
}
Your query is inefficient, you're currently doing a query per contact which is very slow, you can get it all with one big query (which is pretty fast):
String[] projection = new String[] { Phone.CONTACT_ID, Phone.DISPLAY_NAME, Phone.NUMBER };
Cursor c = cr.query(Phone.CONTENT_URI, projection, null, null, null);
while (c.moveToNext()) {
long contactId = c.getLong(0);
String name = c.getString(1);
String phone = c.getString(2);
Log.i("Phones", "got contact phone: " + contactId + " - " + name + " - " + phone);
}
c.close();
You could consider using the Paging library: https://developer.android.com/topic/libraries/architecture/paging/
It was designed with the idea that a list only displays a certain number of items, so there's really no need to load way way way more than it can potentially show. For example, a ListView might only show 10 contacts, so there's no need to fetch 600 contacts.
Instead, the Paging library will fetch a smaller amount as the user scrolls, thus erasing the loading time of 600 contacts, the memory for 600 contacts, and etc... thus making it more efficient.
If you're worried of speed, I would try to use a Set, although with 600+ contacts in the ArrayList that shouldn't be a problem. It becomes a problem when the data set is in the millions and more. I would try to looking at any other inefficiencies in your code.
In terms of a Set, the two most common Java data structures are HashSet and TreeSet. TreeSet if you want to the set to be ordered. HashSet is a little bit faster, but you lose out on the ordering. Both of which has O(1) access time.
I have encountered a problem in my Android application. I want to retrieve all values of a column, but I am only getting one of the values. I have tried everything, but I could still not find a solution. Here is my code in my database:
public Cursor returnAllColumns() {
Cursor cursor = mDb.query(FTS_VIRTUAL_TABLE,
new String[] {KEY_ROWID,
KEY_NAME,
KEY_CUSTOMER, PROTEIN, TOTAL_CARB}
, null, null, null, null, null);
if (cursor != null) {
cursor.moveToNext();
}
return cursor;
}
Here is my code in another class where it shows a toast with all the values.
mDbHelper = new DBAdapter(DatabaseFiller.this);
mDbHelper.open();
Cursor c = mDbHelper.returnAllColumns();
String protein = c.getString(c.getColumnIndexOrThrow("protein"));
Toast.makeText(getApplicationContext(), protein, Toast.LENGTH_SHORT).show();
All I am getting is Protein = 0. What I should be getting is 0, 0, 0, 0, 0, 0,.... I don't know what I am doing wrong here. In my ListView, I got it right. It worked perfectly there. Here is my ListView code:
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// Get the cursor, positioned to the corresponding row in the result set
cursor = (Cursor) mListView.getItemAtPosition(position);
//mListView.setItemChecked(position, true);
// Get the state's capital from this row in the database.
String name = cursor.getString(cursor.getColumnIndexOrThrow("customer"));
String caloriescursor = cursor.getString(cursor.getColumnIndexOrThrow("name"));
String totalfat = cursor.getString(cursor.getColumnIndexOrThrow("address"));
String satfatcursor = cursor.getString(cursor.getColumnIndexOrThrow("city"));
String state = cursor.getString(cursor.getColumnIndexOrThrow("state"));
String zipCode = cursor.getString(cursor.getColumnIndexOrThrow("zipCode"));
And that returns a Toast with a bunch of values. Any help regarding this problem would be appreciated.
In getAllColumns(), your query statement is correct. It does in fact fetch all columns. The if statement that follows simply points it to the first result. Then you are returning the cursor while it is pointed to the first result. You should take out the if statement because it doesn't do anything useful.
When trying to show the toast, you want something like this:
Cursor c = mDbHelper.returnAllColumns();
ArrayList<String> protein = new ArrayList<>();
while (c.moveToNext()) {
protein.add(c.getString(c.getColumnIndexOrThrow("protein")));
}
Toast.makeText(getApplicationContext(), TextUtils.join(", ", protein), Toast.LENGTH_SHORT).show();
You need to loop over the cursor if the cursor is returning more than one row, and build your output in the loop.
Keep calling c.moveToNext() until it returns false.
I had the same problem until I did this:
if (!cursor.moveToFirst()) {
Log.d(LOG_TAG, "=== cursor not moveToFirst() ===");
return null;
}
Log.d(LOG_TAG, "=== reading cursor of getAll() ===");
Log.d(LOG_TAG, String.valueOf(cursor));
List<Trip> trips = new ArrayList<>();
while (!cursor.isAfterLast()) {
trips.add(cursorToTrip(cursor));
cursor.moveToNext();
}
The cursor.moveToNext() will never check the first element. So I check in the course is not in the last one and then I add the object and move to the next one.
That's it! :)
I am developing an Android application where I search for records which are created after a given date. My code is some thing like this
public List<NPRMember> IncrementalData(String LastDtTime) {
List<NPRMember> results = new ArrayList<NPRMember>();
SQLiteDatabase db=getMyReadableDatabase();
String lastdt="datetime("+LastDtTime+")";
Cursor cursor = null;
try{
cursor = db.query(TABLE_NAME_NPR, new String[] { KEY_FULLNAME, KEY_FATHERNAME,
KEY_RCRD_SOURCE,KEY_RCRD_CRN_DATE},KEY_RCRD_CRN_DATE + ">? AND "+KEY_RCRD_SOURCE+">?",
new String[]{lastdt, "0"}, null, null, null);
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
NPRMember nprmem = cursorToMemberDetails(cursor);
results.add(nprmem);
cursor.moveToNext();
}
}catch(Exception e){
Log.e(APP_NAME, "An error occurred while searching for "+LastDtTime+": "+e.toString(), e);
}finally{
if(cursor!=null && !cursor.isClosed()){
cursor.close();
}
}
return results;
}
The query does not return any value, although I have at least one record with KEY_RCRD_CRN_DATE 2013-07-25 18:59:19
The LastDtTime passed as parameter has value 2013-07-25 14:46:03.
One interesting thing is if I run the query at SQLite command prompt it returns the deisred record.
SELECT fullname, fathername, .... rcrdsource, rcrdcrtndate FROM nprmembers WHERE rcrdcrtndate>'2013-07-25
14:46:03' AND rcrdsource>0;
Any help would be appreciated.
Thanks
The parameter value (in lastdt) is wrong.
What you want is the string 2013-07-25 18:59:19, but you are actually using the string datetime(2013-07-25 18:59:19).
The letter d comes after 2, so no record matches.
Change the initialization of lastdt to:
String lastdt=LastDtTime;
I now sure what i'm doing wrong because java and SQLite for me new. So I need to make check when user is entering new data to DB if data with such "day" and "week_type" exists it need to be updated , else create new row.
public long creatEntry(int day2, int week_type2,
String desc2, String place2, String lessnum2) {
// TODO Auto-generated method stub
ContentValues cv = new ContentValues() ;
String update = "SELECT * FROM info WHERE day="+day2+" AND week_type="+week_type;
Cursor cr = ourDatabase.rawQuery(update, null);
if(cr!= null){
cv.put(day, day2);
cv.put(week_type, week_type2);
cv.put(desc, desc2);
cv.put(place, place2);
cv.put(lessnum, lessnum2);
return ourDatabase.update(DATABASE_TABLE,cv, day+ "=" +day2+ " AND "+week_type+ "=" +week_type2, null);
}
else{
cv.put(day, day2);
cv.put(week_type, week_type2);
cv.put(desc, desc2);
cv.put(place, place2);
cv.put(lessnum, lessnum2);
return ourDatabase.insert(DATABASE_TABLE, null, cv);
}
}
Use replace. It'll try to insert first, and if it happens to conflict due to a key constraint, it'll delete and insert those values. In your case, these two columns must be unique. Check it out:
http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html#replace(java.lang.String, java.lang.String, android.content.ContentValues)