I have a custom ListView and used CursorAdapter to expose data from a Cursor. One challenge I got was to add Serial number in each List Items. I know there has to be a column named "_id" and It's a primary field.
What I could do is add Serial number by grabbing up the value of "_id" column, But It was not possible because I showed all data in descending order.
Another way I tried was by declaring a variable and added 1 each time the item is created.
My Adapter class which extends CursorAdapter simply looks like this
public class BalanceInfoAdapter extends CursorAdapter {
Context context;
List<Balance> listOfBalance;
int serialNo = 0; //Declared as field
//Some constructers to initialise fields
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
serialNo+=1; //Added +1 to the variable
return LayoutInflater.from(context).inflate(
R.layout.myLayout, parent, false);
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
mySerialNumberTextView.setText(String.valueOf(serialNo)); //Shown Serial Number in a TextView of List Item
}
Problem
It worked fine till List Items fills the screen at first time. But as I scroll down and up, the way I mentioned above failed, because CursorAdapter recycles it's List Items as it is scrolled and Serial Number of first item became most higher.
Question
Is there any other way to add S/N in recycling List Items ? OR I can prevent this from happening in the same Adapter class.
You can use the public abstract int getPosition () method of Cursor.
For more reference click here
eg: int rowNum = cursor.getPosition();
Note: in public abstract void bindView (View view, Context context, Cursor cursor) method of CursorAdapter, cursor automatically moves to the current row.
So using cursor we can get the current row position in .
Picking up from the documentation http://developer.android.com/reference/android/widget/CursorAdapter.html#newView%28android.content.Context,%20android.database.Cursor,%20android.view.ViewGroup%29
public abstract View newView (Context context, Cursor cursor, ViewGroup parent)
cursor - The cursor from which to get the data. The cursor is already moved to the correct position.
So here cursor is already at its correct position. So you can use cursor.getPosition() method to get the correct serial number.
Related
I have one EditText which is used for the purpose of taking user input. Once the user enters certain data, the text changing listener associated with the EditText calls for a refreshed cursor and tries to update the result which is being displayed in the ListView, placed just below.
Everything is fine. But whenever any change in the search query occurs, the resulting cursor and ListView update takes some time, say around n seconds. During this span of n second, the UI stops (halts/hangs whatever you may call) and does not respond until a refreshed cursor is available and the entire ListView is populated.
When I tried to put the updating of the cursor in a different thread, it did not allow the same to be reflected in the UI as the UI-thread does not allow being commanded by other threads in action. Any UI activity such as the list update has to be implemented through runOnUiThread in the MainActivity class.
Kindly suggest ways by which I can allow the EditText to be modified by the user as well as the updated cursor refreshing the ListView happen without affecting the former.
Basically, you are trying the wrong approach. When we want the data for the list to be sourced directly from an SQLite database query, we can use a CursorAdapter.
Create an adapter
public class MyCursorAdapter extends CursorAdapter {
// Default constructor
public MyCursorAdapter(Context context, Cursor cursor, int flags) {
...
}
public void bindView(View view, Context context, Cursor cursor) {
...
}
public View newView(Context context, Cursor cursor, ViewGroup parent) {
...
return null;
}
}
Get Values from database
Cursor todoCursor = db.rawQuery("SELECT * FROM todo_items", null);
Now, we can use the CursorAdapter in the Activity to display an array of items into the ListView:
// Find ListView to populate
ListView lvItems = (ListView) findViewById(R.id.lvItems);
// Setup cursor adapter using cursor from last step
TodoCursorAdapter todoAdapter = new TodoCursorAdapter(this, todoCursor);
// Attach cursor adapter to the ListView
lvItems.setAdapter(todoAdapter);
This will then trigger the CursorAdapter iterating through the result set and populating the list. We can change the cursor to update the adapter at any time with:
// Switch to new cursor and update contents of ListView
todoAdapter.changeCursor(newCursor);
Running into the situation that the listView's row will need to display different number of the record data from the cursor (i.e. one listView's row could contain multiple record rows from the cursor).
Or that the cursor.getCount() is not same as the listView expected list data count.
For example, cursor has 100 record rows, the listView needs to show in such a way the first 10 listView rows are each with 3 cursor records and rest will show 2 cursor records in the lisView's row. So the listView expects to have total 10 + 35 = 45 rows (10x3 + 35x2 =100) although the cursor has 100 records.
Seems bindView() and newView() are given the cursor corresponding to the viewList's row position.
How to group the cursor records into either a three or two for one listView row?
#Override
public void bindView(View v, Context context, Cursor c) {
...
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
...
}
I am not sure whether the question title is proper or not, but after searching a lot I am asking this.
In my SQLite table, I have the columns
1: _id 2: position 3: path
position: the position of the gridView where the Image is to set
path: the path of the SDCard having corresponding image
How would I get the image from the path and set into the GridView
GridView grid = (GridView) findViewById(R.id.play_grid_view);
DBAdapter adapter = new DBAdapter(this); //My costum adapter for databse operation
adapter.open();
Cursor cusor = adapter.getAllImages(); //returns cursor with 3 columns mentioned above
startManagingCursor(cusor);
After this what should I do?
If your position column means the position of image in grid, you can just sort your query with this column, then cursorAdapter will fill your grid according to positions set in your DB.
This is not usable, if you will skip some of gridview cells (suppose you have following positions in your database: 1,2,4 - then your this adapter will fill positions 1,2,3 as there is actually no position checking)
public class ImageCursorAdapter extends CursorAdapter {
public ImageCursorAdapter(Context context, Cursor c) {
super(context, c);
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
String pos = cursor.getString(positionColumnIndex);
String path = cursor.getString(pathColumnIndex);
ImageView image = (ImageView)view;
image.setImageDrawable(Drawable.createFromPath(path));
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
View v = new ImageView(context);
bindView(v, context, cursor);
return v;
}
}
You are looking for the SimpleCursorAdapter. You need to customize the bindView() method by overriding to show what you want.
You could also try the CursorAdapter itself. Here is a tutorial..
I have a activity displaying call logs in a ListView. The adapter used here to populate listview extends CursorAdapter. Listview is set to onItemClickListener(..). My Question is whenever an item is clicked how does cursor get the data? how does cursor know which position is clicked and need to get data from clicked position only? I have provided a code snippnet.
public class CallLog extends Activity
{
ListView mListView;
Cursor cursor;
//other variables
public void OnCreate()
{
setContentView(R.layout.calllog);
//SQLiteDatabaseInstance db
cursor = db.query(...parameters to get all call logs...);
mListView.setOnItemClickListener(this);
}
public void OnItemClick( // all arguments... )
{
//there is a column name 'NAME' in call log table in database
String name = cursor.getString(cursor.getColumnIndex(Database.NAME))
//here name is obtained of the clicked item.
}
Cursor is a result set. how does the cursor know which item is clicked? What can be the methods implicitly called by cursor that gives it position of clicked item?
If there are any links of similar question then pls provide.
I hope I am able to make you understand the question. Thank you
Try this:
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//move cursor to clicked row
cursor.moveToPosition(position);
}
Specifically it is NOT the Cursor that knows who clicked on what. This is actually handled by the Adapter. The adapter is used to group elements together and allow abstraction as such that they can be handled in a uniform way.
Any form of list, always has an adapter, and this is exactly why the adapter works so well. If you look at a Custom Listview with a Custom Adapter, you'll see exactly how this is done.
Example:
http://android.vexedlogic.com/2011/04/02/android-lists-listactivity-and-listview-ii-%E2%80%93-custom-adapter-and-list-item-view/
You should use cursor.moveToposition(position) inside function to get to the position of that clicked item. After that you apply this and when you will click on any item, the cursor will be set on that item and then you can use that particular item for your operation.
mListView..setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0,
View view, int position, long id) {
// here position gives the which item is clicked..
}
});
Additionally check this link for ListView ListView and ListActivity
It may help you..
I'm trying to implement a CursorAdapter in my Android App. I read different tutorials and tried out different things but it won't work!
I found one question here very similar to mine but I didn't get the idea out of it.
Here's the thing:
I got a Database with multiple tables and foreign keys and so on. I wrote a (tested and working) Database including an
extension of the SQLiteHelper class to work properly. The DB-Class containts a lot of methods to get various operations
on that DB like: insert, update, delete, alter and some special needs....
My Problem is the following:
I have written a method which returns all Data containing (all rows) in the Database which i want to present
in a ListView. The returning object is a wrapped ArrayList> . I got the thing working all fine
with an ListViewAdapter but then i came to my problem which now almost drives me crazy:
The User shall click a random item in that specific list (which contains all rows from the DB) and then i want to
update that specific row in the DB with some new data the user put into a EditText box. Pretty simple task actually but I think I just don't understand the usage of the CursorAdapter.
My questions now:
What does my DB-Method have to return (or look alike) that the CursorAdapter can handle it....
How do I have to implement the Adapter that it just fulfill this one task (retrieving the correct rowID of the DB entry in the list)
Here is my method retrieving the data from the DB
public ArrayList<ArrayList<Object>> getAll()
{
ArrayList<ArrayList<Object>> allRows = new ArrayList<ArrayList<Object>>();
//Cursorobjekt haelt die Daten einer Zeile und dient dazu in diesen zu iterieren
Cursor myCursor1,myCursor2,myCursor3;
myCursor1 = db.query
( "Faecher",
new String[] { "id" , FACH_NAME, FACH_ART },
null, null, null, null, null
);
// Den Pointer an die erste Stelle ruecken
myCursor1.moveToFirst();
myCursor2 = db.query
(
"Ort",
new String[]{"id" , ORT_RAUM , ORT_GEBAEUDE},
null,null,null,null,null,null
);
myCursor2.moveToFirst();
myCursor3 = db.query
(
"Profs",
new String[]{"id", PROFS_NAME, PROFS_SNAME, FKEY_GENDER_ID},
null,null,null,null,null,null
);
myCursor3.moveToFirst();
for(int i=0; i < myCursor1.getCount(); i++)
{
ArrayList<Object> row1 = new ArrayList<Object>();
row1.add(myCursor1.getLong(0));
row1.add(myCursor1.getString(1));
row1.add(myCursor1.getString(2));
row1.add(myCursor2.getLong(0));
row1.add(myCursor2.getString(1));
row1.add(myCursor2.getString(2));
row1.add(myCursor3.getLong(0));
row1.add(myCursor3.getString(1));
row1.add(myCursor3.getString(2));
row1.add(myCursor3.getLong(3));
allRows.add(row1);
myCursor1.moveToNext();
myCursor2.moveToNext();
myCursor3.moveToNext();
}
myCursor1.close();
myCursor2.close();
myCursor3.close();
return allRows;
}
The Adapter is empty right now because my code was real crap and now looks like this hull:
public class SubjectListAdapter extends CursorAdapter
{
private LayoutInflater myInflater;
public SubjectListAdapter(Context context, Cursor c)
{
super(context, c);
}
#Override
public View newView(Context context, Cursor myCursor, ViewGroup parent)
{
return null;
}
#Override
public void bindView(View parent, Context context, Cursor myCursor)
{
}
}
I hope someone can help me out with my problem or give me a hint where I have to go to get this working.
If I understand your question correctly, it seems like your primary issue is determining which element has been clicked on within the adapter. You may need to switch from bindview and newview to just using getview. If you do, you can just add an onClicklistener to the view before getView returns it. This way, each row in the list has its own listener and can update the correct row in the db. Any particular information that the onClickListener needs to run the correct database update method (ie the rowId) can also be passed into the listener with a Tag on the view. Hope that helps.
You have to create one big query from DB and get one Cursor. You can use even ordinary sql selection like
String selectQuery = "SELECT id, " FACH_NAME", "+ FACH_NAME ", " + FACH_ART .... +" FROM Faecher INNER JOIN ....";
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
to get requared cursor. Than create custom CursorAdapter with getted cursor
public class ExampleCursorAdapter extends CursorAdapter {
public ExampleCursorAdapter(Context context, Cursor c) {
super(context, c);
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
TextView something1 = (TextView)view.findViewById(R.id.something1);
something1.setText(cusror.getString(0));
TextView something2 = (TextView)view.findViewById(R.id.something2);
something1.setText(cusror.getString(1));
.......
viev.addOnClickListener(new OnClickListener{
public void onClick(...){
}
});
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
LayoutInflater inflater = LayoutInflater.from(context);
View v = inflater.inflate(R.layout.item, parent, false);
return v;
}
}
Method bindView(....) will be called for each raw of Cursor but it will be setted to the different position, you souldnt change it inside this method. Than just bind this adapter to your ListView by setAdapter(....) method.