I am still a newbie in android developing and have a problem with my ToDo application.
At the moment my listview displaying all saved ToDo's is only sorted by the first two digits (the days!) of the date but the date is stored in this format: "dd.mm.yyyy"
My target is to sort my listview in ascending order by date (ToDoTable.COLUMN_TODO_START) and time (ToDoTable.COLUMN_TIME_START).
I use the following code at the moment:
public void fillData() {
String[] from = new String[] { ToDoTable.COLUMN_TODO_NAME, ToDoTable.COLUMN_TODO_PLACE, ToDoTable.COLUMN_TODO_START, ToDoTable.COLUMN_TODO_END };
int[] to = new int[] { R.id.todo_name, R.id.todo_place, R.id.todo_start };
getLoaderManager().initLoader(0, null, this);
adapter = new SimpleCursorAdapter(this, R.layout.todo_row_test2, null, from,
to, 0);
setListAdapter(adapter);
}
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
String[] projection = { ToDoTable.COLUMN_ID, ToDoTable.COLUMN_TODO_NAME, ToDoTable.COLUMN_TODO_PLACE, ToDoTable.COLUMN_TODO_START, ToDoTable.COLUMN_TIME_START, ToDoTable.COLUMN_TODO_END, };
CursorLoader cursorLoader = new CursorLoader(this,
DataContentProvider.CONTENT_URI, projection, null, null, ToDoTable.COLUMN_TODO_START + " ASC" );
return cursorLoader;
}
I would be very grateful if someone can help me with this issue especially in the point to sort the list by both criteria (date and time).
Thanks in advance.
Best solution would be a database: For lots of data, feel free to use mysql, e.g. sqlite3. Import the library, put all data in the table and run a query:
reslt =mydatabase.find("select name,todo,time_start,time_end from todo_list order by time_start")
In mysql, the data and time is just one field. Use the TIMESTAMP in sql.
SQLite does not have a storage class set aside for storing dates and times. You can use Date And Time Functions.
So raw query can look like:
SELECT * FROM Table ORDER BY datetime(dateColumn) DESC Limit 1
Related
I have two tables atm, users and notes. I am trying to retrieve data that belongs to the user. So all data to list must be owned by the original user and shown only to him. I have made my table in Databasehelper.
I have made a new class that controls the notes table. In listNotes() I want to loop through the cursor row and get all data owned by the user. Am I quering it correctly?
// Listing all notes
public Cursor listNotes() {
Cursor c = db.query(help.NOTE_TABLE, new String[]{help.COLUMN_TITLE,help.COLUMN_BODY, help.COLUMN_DATE}, null, null, null, null, null);
if (c != null) {
c.moveToFirst();
}
db.close();
return c;
}
I then want to display the cursor data collected in a listview
public void populateList(){
Cursor cursor = control.listNotes();
getActivity().startManagingCursor(cursor);
//Mapping the fields cursor to text views
String[] fields = new String[]{help.COLUMN_TITLE,help.COLUMN_BODY, help.COLUMN_DATE};
int [] text = new int[] {R.id.item_title,R.id.item_body, R.id.item_date};
adapter = new SimpleCursorAdapter(getActivity(),R.layout.list_layout,cursor, fields, text,0);
//Calling list object instance
listView = (ListView) getView().findViewById(android.R.id.list);
adapter.notifyDataSetChanged();
listView.setAdapter(adapter);
}
You aren't creating the NOTE_TABLE right.
You miss a space and a comma here
+ COLUMN_DATE + "DATETIME DEFAULT CURRENT_TIMESTAMP"
It has to be
+ COLUMN_DATE + " DATETIME DEFAULT CURRENT_TIMESTAMP,"
There are two issues here:
One is you have missed a comma (after the Timestamp as specified in an earlier answer).
The other error you have is when using a SimpleCursorAdapter, you need to ensure that the Projection string array includes something to index the rows uniquely and this must be an integer column named as "_id". SQLite already has a feature built in for this and provides a column named "_id" for this purpose (however you can have your own integer column which you can rename to _id). To solve this, change your projection string array to something like:
new String[] {"ROW_ID AS _id", help.COLUMN_TITLE,help.COLUMN_BODY, help.COLUMN_DATE}
I guess the NullPointerException stems from this (but without the stacktrace I don't know for sure).
I use CursorLoader to query a result, which is not the order that I want to show in the ListFramgenet. How to sort it ?
I use this to set the adapter:
mAdapter = new SimpleCursorAdapter(getActivity(),
android.R.layout.simple_list_item_2, null,
new String[] { "name", "distance"},
new int[] { android.R.id.text1, android.R.id.text2 }, 0);
setListAdapter(mAdapter);
// Start out with a progress indicator.
setListShown(false);
// Prepare the loader. Either re-connect with an existing one,
// or start a new one.
getLoaderManager().initLoader(0, null, this);
Create loader :
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
return new CursorLoader(getActivity(),
Uri.withAppendedPath(TraceTable.CONTENT_URI, "latest"),
MEMBERS_PROJECTION,
null,
null,
null);
}
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
mAdapter.changeCursor(data);
// The list should now be shown.
if (isResumed()) {
setListShown(true);
} else {
setListShownNoAnimation(true);
}
}
Well, there are latitude and longitude the queried results. I want to calculate the distance between my location and these results. and sort by distance asc.
How to sort it? Any answer will be appricated
It's actually quite easy:
from this:
new CursorLoader(getActivity(),
Uri.withAppendedPath(TraceTable.CONTENT_URI, "latest"),
MEMBERS_PROJECTION,
null,
null,
null);
to this:
// You could have them calculated in the projection like this:
String[] projection = { COLUMN1 + " * " + COLUMN2 + " as data", // Whatever your calculations are
COLUMN1, COLUMN2, COLUMN3, etc.. };
new CursorLoader(getActivity(),
Uri.withAppendedPath(TraceTable.CONTENT_URI, "latest"),
projection,
null,
null,
"data ASC");
Remember that if you have some method in your provider that does a check to the
projection and rise an exception, you would have to comment it out for the moment you are doing the test or add the new column (the one you do the calculation with) to your official projection array.
What you're looking for is supplying a sortOrder argument something like the following:
(the ORDER BY at the start of this is implicait and you do not include it, simply included here for clarity)
ORDER BY 6366000*acos(cos(lat_a / (180/3.14169))*cos(lng_a / (180/3.14169))*cos(lat_b / (180/3.14169))*cos(lng_b / (180/3.14169)) + t2 + t3) ASC
(for this I took the answer here and inlined it - except I didn't bother with t2 and t3, because it's not going to work anyway)
Unfortunately, this is impossible in standard SQLite - there are no operators sin, or cos - or even a square root or power operator (after seeing your comment about only requiring a more simple calculation).
You can add your own functions, but that's a somewhat more complicated route.
Depending on how many rows you have, you might be alright to just read them all and then sort them yourself.
Provide the column names you want to sort on as the last parameter of the CursorLoader() constructor as a string. If you have more than one column to sort by, separate with a comma. If you want ascending as opposed to descending, add DESC after the column name. So pretty much what you would add after 'ORDER BY' in regular SQL syntax.
EDIT: To answer your comment below.
Yes and no. I believe you could use that as your sort order but SQLite does not have a sqrt or power function. However you can define your own SQLite functions or use a 3rd party extension. If you don't want to go that route, you'll have to use your own custom adapter instead of SimpleCursorAdapter, e.g. you would get the cursor results and then sort them in code into another data stucture which would become the datasource of your adapter.
Just add ContactsContract.Contacts.SORT_KEY_PRIMARY.
How can I merge cursor loader in the following case to get one Cursor loader. I am calling content provider more than one to create my database adapter to use with simple cursor adapter. Please look my code below.
#Override
public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) {
productIdCursor.moveToFirst();
CursorLoader cursorLoader;
// CursorLoader cursorLoader;
int i = 0;
while (productIdCursor.isLast()) {
String[] Projection = { "p.id as _id", "p.name", "p.subTitle",
"p.textColour", "pi.thumb" };
String userSelectionCritera = "p.id = pp.prod_id and pp.imag_id = pi.id and p.id= ? and p.id = pc. prod_id and pc.coun_id = ?";
String[] selecttionArgs = new String[] {
productIdCursor.getString(productIdCursor
.getColumnIndex("prod_id")),
String.valueOf(countryId) };
cursorLoader = new CursorLoader(getActivity(),
DatabaseContentProvider.CONTENT_URI_PRODUCTCATEGORY,
Projection, userSelectionCritera, selecttionArgs, null);
productIdCursor.moveToNext();
}
return cursorLoader;
You can't really merge cursor loaders but you can try a few different things. Your best option would probably be to change your SQL selection statement from p.id = ? to p.id in (...id list here...). You can create a string for the id list by having a look at this answer.
You could also create your own custom loader that accepts an array of product ids and loads them all individually in the background, merging them in a MergeCursor object. This would give you a single loader and a cursor with all the data you need. IMO this second approach is really messy. If this is the only working solution then you probably should go back and review your database table schemas.
I m fetching data from a table in SQLite.
This is my code
String[] sColoumns = { "_id", "userloginid", "password", "firstname", "lastname", "email", "address"};
Cursor cursor = db.query("users", sColoumns, null,null,null,null,null);
The query returns all rows of the table in the cursor.
Now i want to pull the rows one by one from the cursor or load them into a data table and then pull them one by one(like in visual studio).
Is there anything available or anything i can do to achieve this?
thanks in advance.
There are two ways to answer your question.
1) You can simply iterate over the cursor and do whatever you want with the row data:
String[] sColoumns = { "_id", "userloginid", "password", "firstname", "lastname", "email", "address"};
Cursor cursor = db.query("users", sColoumns, null,null,null,null,null);
try {
int firstNameColIndex = cursor.getColumnIndex("firstname");
int lastNameColIndex = cursor.getColumnIndex("lastname");
while (cursor.moveToNext()) {
String fullName = cursor.getString(firstNameColIndex) + cursor.getString(lastNameColIndex);
}
} finally {
cursor.close();
}
2) A common use case is to display data in a list view. Since Android 3.0 Honeycomb (and the Android Support/Compatiblity lib for earlier versions) the best practice is to use a Loader for taking care of managing the cursor. For example it will take care of updating the list view if data is updated in a content provider. I recommend reading http://developer.android.com/guide/topics/fundamentals/loaders.html (see links to samples at the bottom) to understand this topic.
I have a database with 10,000 entries. The database is not updated regularly, but I need to fetch data from it frequently.
One of the options I give to choose a row is a ListView with text filtering.
But the ListView takes a few seconds to load. This time is taken to query the database and put the results from the Cursor into a List. So I decided to create the List whenever the database is updated and use it everytime I want to make the ListView.
I need pointers on how I can store the List so that I can retrieve it immediately and show the ListView.
Any alternatives you can provide would also be appreciated.
UPDATE:
My initial code:
public List<String> fetchNames() {
String[] columns={NAME_KEY};
List<String> names = new ArrayList<String>();
Cursor namesCursor=mydb.query(TABLE_NAME, columns, null, null, null, null, NAME_KEY, null);
Log.w("1", "Got query result");
namesCursor.moveToFirst();
while(!namesCursor.isAfterLast()){
names.add(namesCursor.getString(0));
namesCursor.moveToNext();
}
Log.w("1", "List created");
return names;
}
It takes about 5 seconds between the time "Got query result" and "List created" is logged.
I modified the code to use CursorAdapter
public SimpleCursorAdapter fetchNames() {
String[] columns={"_id", NAME_KEY};
String[] from={NAME_KEY};
int[] to={R.id.list_item_1};
Cursor namesCursor=mydb.query(TABLE_NAME, columns, null, null, null, null, NAME_KEY, null);
Log.w("1", "Got query result");
SimpleCursorAdapter names = new SimpleCursorAdapter(dbContext, R.layout.list_item, namesCursor, from, to);
Log.w("1", "Returning CursorAdapter");
return names;
}
The activity still takes 5 sec to load, but only after "Returning CursorAdapter" is logged.
I feel that the delay is in fetching from the cursor, which is why I wanted to store it as a quickly fetchable resource. Do correct me if I am wrong in thinking that as a string array in resources, it would load faster.
Why not use a CursorAdapter that you attach to your ListView rather than extracting your data into a List? It will automatically update when the database changes, and will be much more efficient.