I need to display in a list view some data about numbers. I get these data from a database that is sqlite.
Im using a simplecursoradapter to fill the listview. The problem is that numbers >= to one million are stored in exponential format. So for example if I insert a number like 1000 000 then it gets stored as 1+06E. The problem is that i need to display it as 1 000 000. But I can't manage to change that format inside the cursor or the simplecursoradapter.
My code for filling the listview is:
Cursor c = admin.obtenerCursorGastosVarFecha(fechaSelUs);
// The desired columns to be bound
String[] columnas = new String[] {"_id", "Descripcion", "Costo", "Fecha_Creado"};
// the XML defined views which the data will be bound to
int[] views = new int[] {R.id.IdGstVar, R.id.DescGstVar, R.id.CostoGstVar, R.id.FechaGstVar };
// create the adapter using the cursor pointing to the desired data
//as well as the layout information
dataAdapter = new SimpleCursorAdapter(this, R.layout.lista_gastos_variables, c, columnas, views, 0);
Im getting here all as a string, but numbers higher or equal to one million show up in exponential numbers
I tried this code, but its not working at all.
It just modifies values lower than ten million and also, it rounds or changes the values, so if insert for example 8 888 888 it displays 8 888 890.
I need to display in natural numbers all the numbers stored in the database.
Also if there is a way to insert rows with numbers into the database without them being changed to exponential format, how is it done? Thank you very much for your help!
dataAdapter.setViewBinder(new SimpleCursorAdapter.ViewBinder() {
#Override
public boolean setViewValue(View view, Cursor cursor, int column) {
if( column == 2 ){ // let's suppose that the column 0 is the date
TextView tv = (TextView) view;
// here you use SimpleDateFormat to bla blah blah
tv.setText(""+Double.parseDouble(cursor.getString(cursor.getColumnIndex("Costo"))));
return true;
}
return false;
}
});
Since you are using datatype as real , and storing it into db as real number. At the time of storing into SqliteDB, it converts it into exponential format. When you are trying to read it from database it gives you the converted exponential format into string. You just change the datatype to varchar for costo. It will solve your problem.
Related
For example, let's say that a local contact have multiple Japanese contacts with the name たなか, つなき, and てるてる. In the local contact these names will be sorted under the section index letter た.
For what I've read, it is possible to sort them via collate, but how do you sort them to index た or even know that they should go to the た index?
Thank you.
The API has a trick for returning that list of alphabet letters, and optionally also including counts per character.
See official docs for EXTRA_ADDRESS_BOOK_INDEX:
https://developer.android.com/reference/android/provider/ContactsContract.Contacts.html#EXTRA_ADDRESS_BOOK_INDEX
Example code:
Uri uri = Contacts.CONTENT_URI.buildUpon()
.appendQueryParameter(Contacts.EXTRA_ADDRESS_BOOK_INDEX, "true")
.build();
Cursor cursor = getContentResolver().query(uri,
new String[] {Contacts.DISPLAY_NAME},
null, null, null);
Bundle bundle = cursor.getExtras();
if (bundle.containsKey(Contacts.EXTRA_ADDRESS_BOOK_INDEX_TITLES) && bundle.containsKey(Contacts.EXTRA_ADDRESS_BOOK_INDEX_COUNTS)) {
String sections[] = bundle.getStringArray(Contacts.EXTRA_ADDRESS_BOOK_INDEX_TITLES);
// sections will now contain an array of characters that represent the first letter of each available contact name
// optionally - if you need counts per letter - int counts[] = bundle.getIntArray(Contacts.EXTRA_ADDRESS_BOOK_INDEX_COUNTS);
}
I have run into that timeless issue of wanting to have an auto-incrementing column (in SQLITE) that remains intact after a record is deleted. I have run into a number of posts about this problem, but none of them explain exactly how to code your own column for this purpose. I need the numbers to be consecutive because I want to be able to display a record number for each item in a ListView which will also serve as a running total of how many records are in the db.
So far, I have been trying to use the VACUUM function because it's my understanding that it will reset the numbers once it's complete, and I thought I would run it every time a record is deleted, but nothing seems to happen when the code is run. I'm not getting any errors, but the VACUUM isn't happening as far as I can tell. Here's the code:
String sql = "VACUUM;" ;
db.execSQL(sql,new String [] {sql});
Maybe nothing is happening because the coding is off? So I guess what I am getting at here is am I on the right track with trying to use VACUUM or should I go with manually setting up an auto-incrementing column? Either way, any advice is greatly appreciated!
Here's the fetch and display portion of the code:
populateListViewFromDB();
}
#SuppressWarnings("deprecation")
private void populateListViewFromDB() {
Cursor cursor = db.getAllRecords();
//Allow activity to manage cursor lifetime
startManagingCursor(cursor);
//Setup mapping from cursor to view fields:
String [] fromFieldNames = new String []
{DBAdapter.KEY_ROWID, DBAdapter.KEY_GENRE, DBAdapter.KEY_TITLE, DBAdapter.KEY_PLATFORM, DBAdapter.KEY_DATE, DBAdapter.KEY_PRICE, DBAdapter.KEY_WHEREBOUGHT};
int [] toViewIDs = new int []
{R.id.RecordNumberEdit, R.id.textView1, R.id.textView2, R.id.textView3, R.id.textView4, R.id.textView5, R.id.textView6};
//Create mapping from cursor to view fields
SimpleCursorAdapter myCursorAdapter = new SimpleCursorAdapter(
this,
R.layout.database_view_layout,
cursor, //Set of DB records
fromFieldNames, //DB field Names
toViewIDs //View IDs in which to put info
);
//Set the adapter for the list view
ListView listViewFromDB = (ListView) findViewById(R.id. listViewFromDB);
listViewFromDB.setAdapter(myCursorAdapter);
I changed the VACCUUM code to the following since the original code was actually passing the query twice :
String sql = "VACUUM;" ;
db.execSQL(sql);
Still, though, nothing seems to be happening.
I FOUND A SOLUTION FOR RESTORING MY VALUES, SEE MY NEW VERSION of populateFields()
Okay so I have been reading through all the Spinner and SQlite posts on here and cannot seem to find a good answer for what I am looking for so I am posting this scenario.
My app has two screens and uses the sqlite database on my device saving a name and weight fields from editTexts as strings like so
String eName = name.getText().toString();
String eWeight = weight.getText().toString();// where name and weight are EditTexts
and I have two spinners as follows
String eReps = spinReps.getSelectedItem().toString();
String eSets = spinSets.getSelectedItem().toString();
Then I call this to add to the database
long id = mDbHelper.createExercise(eName, eWeight, eReps, eSets);
Here is where my issue is, upon someone selecting to create a new exercise my app crashes because it is trying to populate a spinner incorrectly. Here is what I have currently.
private void populateFields(){
if(mRowId != null){ // where mRowId is the selected row from the list
Cursor exercise = mDbHelper.fetchExercise();
name.setText(exercise.getString(exercise.
getColumnIndexOrThrow(ExerciseDbAdapter.KEY_NAME)));
weight.setText(exercise.getString(exercise.
getColumnIndexOrThrow(ExerciseDbAdapter.KEY_WEIGHT)));
// this is the part that i need help with, I do not know how to restore
// the current items spinner value for reps and sets from the database.
spinReps.setSelection(exercise.getString(exercise.
getColumnIndexOrThrow(ExerciseDbAdapter.KEY_REPS)));
spinSets.setSelection(exercise.getString(exercise.
getColumnIndexOrThrow(ExerciseDbAdapter.KEY_SETS)));
}
I assume I need to use some sort of adapter to restore my list items along with the current value from the database, I am just not sure how.
Can someone please help me with this???
** BELOW IS MY SOLUTION**
I had to move my ArrayAdapters repsAdapter, spinAdapter out of my onCreate()
and then implement this new populateFields()
private void populateFields(){
if(mRowId != null){
Cursor exercise = mDbHelper.fetchExercise(mRowId);
// same as before
name.setText(exercise.getString(exercise.
getColumnIndexOrThrow(ExerciseDbAdapter.KEY_NAME)));
// get the string for sReps and sSets from the database
String sReps = exercise.getString(exercise.
getColumnIndexOrThrow(ExerciseDbAdapter.KEY_REPS));
String sSets = exercise.getString(exercise.
getColumnIndexOrThrow(ExerciseDbAdapter.KEY_SETS));
// use the strings to get their position in my adapters
int r = repsAdapter.getPosition(sReps);
int s = setsAdapter.getPosition(sSets);
// set their returned values to the selected spinner Items
spinReps.setSelection(r);
spinSets.setSelection(s);
// same as before
weight.setText(exercise.getString(exercise.
getColumnIndexOrThrow(ExerciseDbAdapter.KEY_WEIGHT)));
}
}
The way to set a Spinner to a value, not a position, depends on what adapter you are using.
ArrayAdapter, this one is easy:
int position = adapter.getPosition(exercise.getString(exercise.
getColumnIndexOrThrow(ExerciseDbAdapter.KEY_REPS)));
spinReps.setSelection(position);
SimpleCursorAdapter, this one is a little harder:
String match = exercise.getString(exercise.getColumnIndexOrThrow(ExerciseDbAdapter.KEY_REPS));
Cursor cursor = adapter.getCursor();
cursor.moveToPosition(-1);
int columnIndex = cursor.getColumnIndexOrThrow(ExerciseDbAdapter.KEY_REPS);
while(cursor.moveToNext()) {
if(cursor.getString(columnIndex).equals(match))
break;
}
spinReps.setSelection(cursor.getPosition());
If you are using a different type of adapter and can't modify the code above to fit it, let me know. Hope that helps!
I get data from my DB using
cursor = db.query("WebLeadMaster", select, "condition1="+conditionVal1+
" and condition2="+ConditionVal2,null, null, null, "RegistrationTime DESC");
I am getting the data in my cursor alright. To display the data, i use the following code:
SimpleCursorAdapter mAdapter = new SimpleCursorAdapter(this,
R.layout.resultleadlookup, cursor, columns, to);
mAdapter.notifyDataSetChanged();
lstResult.setAdapter(mAdapter);
So, I cannot modify the contents of the cursor. The sort query has condition "RegistrationTime" which is a String data type. As you can see in the image below, it is not in a proper sorted format. (not according to date-time).
What changes should i make in my code so that it would sort properly according to date-time?
If i alter my DB query, to look like
cursor = db.query("WebLeadMaster", select, "condition1="+conditionVal1+
" and condition2="+ConditionVal2,null, null, null, null);
it gives an ascending order. All i want it the descending order.
The easiest suggestion would be to save the date in a different format (but still saved as string) into the database. If you would save the data into SQLite’s default date format (YYYY-MM-DD HH:NN:SS), you can easily sort the dates.
To display the date in your format, you would only just need to reformat the date into the correct format.
Well, i changed my table structure. I added another field "_id" to it. Set the property as AUTO INCREMENT to it, and sorted the list with respect to _id field.
If you r using ORM you can sort the data by timestamp.
ORM makes data insertion and data retrieval easier from database.
You have to include jar files to your project to use ORM...
since SQLite has no datetime type, store date type as LONG/INT/NUMERIC in SQLite (EPOCH time) it will be easier to sort
then add ViewBinder to Adapter
/*field in activity/fragment*/
final static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //or other format that you wana to show in ListView
...
mAdapter.setViewBinder(new SimpleCursorAdapter.ViewBinder() {
#Override
public boolean setViewValue(View view, Cursor cursor,
int columnIndex) {
final int id = view.getId();
switch (id) {
case R.id.id_of_textview_with_date_data:
final Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(cursor.getLong(columnIndex));
((TextView) view).setText(sdf.format(cal.getTime()));
return true;
}
return false;
}
});
... or as dennisg pointed store it as STRING/VARCHAR edit: in "yyyy-MM-dd HH:mm:ss" format
Well this is probably a stupid question with a simple answer but when using simple cursor adapter from the notepad example, I get a list of names from my database.
When I try to do it "manually" by moving the cursor over the rows and extracting the names the cursor says there is zero rows returned...
This works as per the example:
Cursor notesCursor = mDbHelper.fetchAllNotes();
startManagingCursor(notesCursor);
// Create an array to specify the fields we want to display in the list (only NAME)
String[] from = new String[]{WeightsDatabase.KEY_NAME};
// and an array of the fields we want to bind those fields to (in this case just text1)
int[] to = new int[]{R.id.weightrows};
// Now create a simple cursor adapter and set it to display
SimpleCursorAdapter notes =
new SimpleCursorAdapter(this, R.layout.weights_row, notesCursor, from, to);
setListAdapter(notes);
Now i'm trying to do this but it's not quite working. Is the simple cursor adapter doing something special i'm not?
//check # of rows, returns 0
int mOne = notesCursor.getCount();
//initial random string array
String[] temp = new String[100];
int i = 0;
notesCursor.moveToFirst();
do{
temp[i]=notesCursor.getString(notesCursor.getColumnIndex(WeightsDatabase.KEY_ROWID)); //crashes here
//index out of bounds
i++;
}while(notesCursor.moveToNext());
I have gotten this to work, but with returning a specific query like return all row with the name "_". What is different about returning all notes?
moveToFirst() actually returns a boolean, so you can prevent the exception from being thrown by checking the value before you attempt to read from the Cursor:
if (notesCursor.moveToFirst()) {
// do loop
}
As for why there are 0 rows, are you attempting to re-use the same cursor that you passed into the SimpleCursorAdapter, or is the code that is failing stand-alone? If you are attempting to re-use it, I would try it using a new Cursor after performing a fresh fetchAllNotes().