hi am using cursor adapter for my listview, my problems is when i put my application in background ,on retuning my screen is empty, in onresume i have open the database and creating cursor still i have the problem, how can i solve my problem ,pls help me .
searchCursor= dbReaderContact.rawQuery(query, null);
startManagingCursor(searchCursor);
String[] from=new String[] {ALDbAdapter.TITLE,DbAdapter.CATID,DbAdapter.LTID,DbAdapter.RK,DbAdapter.SUBTITLE};
int [] to=new int[] {R.layout.ctllist_item};
catSearchAdapter=new CategorySearchAdapter(context, R.layout.ctllist_item, searchCursor, from, to);
//////////////Adapter calss
public class CategorySearchAdapter extends SimpleCursorAdapter implements Filterable{
private Context context;
private int layout;
private ALDbAdapter dbadapter;
/**
* #param context
* #param layout
* #param c
* #param from
* #param to
*/
public CategorySearchAdapter(Context context, int layout, Cursor c, String[] from, int[] to) {
super(context, layout, c, from, to);
this.layout=layout;
this.context=context;
dbadapter=new ALDbAdapter(context);
try {
dbadapter.openAngiesListDb();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public Cursor runQueryOnBackgroundThread(CharSequence constraint) {
if (getFilterQueryProvider() != null) { return getFilterQueryProvider().runQuery(constraint); }
StringBuilder buffer = null;
String[] args = null;
if (constraint != null) {
buffer = new StringBuilder();
buffer.append("UPPER(");
buffer.append("name");
buffer.append(") GLOB ?");
args = new String[] { constraint.toString().toUpperCase() + "*" };
}
Cursor c=null;
// c=dbadapter.getPartialNamesSearch(constraint.toString());
return c;
}
#Override
public void bindView(View v, Context context, Cursor c) {
TextView subTitle=(TextView)v.findViewById(R.id.ctlName);
TextView title=(TextView)v.findViewById(R.id.cltAssocationName);
ImageView imgIcon=(ImageView)v.findViewById(R.id.ctlLogo);
int subTitInd=c.getColumnIndex(ALDbAdapter.SUBTITLE);
int titInd=c.getColumnIndex(ALDbAdapter.TITLE);
int ltId=c.getColumnIndex(ALDbAdapter.LTID);
int ltype=c.getInt(ltId);
if(!c.getString(subTitInd).equalsIgnoreCase("")){
subTitle.setText(c.getString(subTitInd));
title.setText(c.getString(titInd));
}else{
subTitle.setText(c.getString(titInd));
}
if(ltype==1){
imgIcon.setImageResource(R.drawable.logo1);
}else if(ltype==2){
imgIcon.setImageResource(R.drawable.logo2);
}else{
imgIcon.setImageResource(R.drawable.logo3);
}
}
}
//On post i closed the cursor
///On Resume
searchCursor= dbReaderContact.rawQuery(query, null);
startManagingCursor(searchCursor);
You are talking about ListView and using SimpleCursorAdapter. Don't you think creating your own ArrayAdaptor isn't more efficient : you create a class of your own to hold the data you want from your DB request (iterate over your Cursor), then you populate an ArrayList of that class.
Then you give this ArrayList to a class which extens ArrayAdaptor. You should store the ArrayList in the ArrayAdaptor and override contructor and the public View getView(int position, View convertView, ViewGroup parent) method to create each view of your ListView.
You can google custom ListView (first result : http://www.softwarepassion.com/android-series-custom-listview-items-and-adapters/ ).
Related
Well, I have read almost 50 links related to this question, but my code still not working.
I have a Custom adapter which extends SimpleCursorAdapter class, and I use that adapter to fill the ListView on onCreate method
private void populateListView()
{
String[] from = new String[] { SchemaHelper.TASK_DESCRIPTION, SchemaHelper.TASK_CREATED_ON, SchemaHelper.TASK_ID };
int[] to = new int[] {R.id.lv_row_description, R.id.lv_row_created_on};
tasksCursor = schemaHelper.getTasks();
startManagingCursor(tasksCursor);
tasksAdapter = new TasksAdapter(this, R.layout.tasks_listview_row, tasksCursor, from, to);
setListAdapter(tasksAdapter);
}
The App is a simple task manager, I want to update the ListView contents when the user submits a new task without calling setListAdapter() again.
I have tried notifyDataSetChanged (running on ui thread), invalidate, requery(deprecated)... almost everything.
I'm doing something wrong?
EDIT:
This is the method where I add a new task to the database
private void addTask(String description)
{
String message = "";
schemaHelper.open();
if(schemaHelper.isAlreadyInDatabase(description))
{
message = getString(R.string.task_already_exists);
}
else
{
message = getString(R.string.task_succesfully_added);
schemaHelper.insertTask(description);
populateListView();
newTask.setText("");
}
schemaHelper.close();
Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();
}
ADAPTER CLASS:
private class TasksAdapter extends SimpleCursorAdapter
{
private LayoutInflater layoutInflater;
private Cursor cursor;
public TasksAdapter(Context context, int layout, Cursor c, String[] from, int[] to)
{
super(context, layout, c, from, to);
cursor = c;
cursor.moveToFirst();
layoutInflater = LayoutInflater.from(context);
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
if(cursor.getPosition() < 0)
{
cursor.moveToFirst();
}
else
{
cursor.moveToPosition(position); // Here throws the error
}
View row = layoutInflater.inflate(R.layout.tasks_listview_row, null);
TextView description = (TextView) row.findViewById(R.id.lv_row_description);
TextView createdOn = (TextView) row.findViewById(R.id.lv_row_created_on);
description.setText(cursor.getString(cursor.getColumnIndexOrThrow(SchemaHelper.TASK_DESCRIPTION)));
createdOn.setText(getString(R.string.added_on) + " " + TaskHelper.formatDateWithSuffix(cursor.getString(cursor.getColumnIndexOrThrow(SchemaHelper.TASK_CREATED_ON))));
return row;
}
}
i dont know much of the taskCursor and taskAdapter but i used ArrayAdapter i guess, well have a look in my code and take your own conclusions.
//LISTVIEW database CONTATO
ListView user = (ListView) findViewById(R.id.lvShowContatos);
//String = simple value ||| String[] = multiple values/columns
String[] campos = new String[] {"nome", "telefone"};
list = new ArrayList<String>();
Cursor c = db.query( "contatos", campos, null, null, null, null, "nome" + " ASC ");
c.moveToFirst();
String lista = "";
if(c.getCount() > 0) {
while(true) {
list.add(c.getString(c.getColumnIndex("nome")).toString());
if(!c.moveToNext()) break;
}
}
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, list);
user.setAdapter(adapter);
If you don't want to use requery() you can simply pass a new Cursor with the same query:
tasksCursor.close();
tasksCursor = schemaHelper.getTasks();
startManagingCursor(tasksCursor);
tasksAdapter.changeCursor(tasksCursor);
I assume that when you call addTask() you have already called populateListView() once. Try changing addTask() to this:
private void addTask(String description)
{
String message = "";
schemaHelper.open();
if(schemaHelper.isAlreadyInDatabase(description))
{
message = getString(R.string.task_already_exists);
}
else
{
message = getString(R.string.task_succesfully_added);
schemaHelper.insertTask(description);
// Remove call to populateListView(), just update the Cursor
tasksCursor.close();
tasksCursor = schemaHelper.getTasks();
startManagingCursor(tasksCursor);
tasksAdapter.changeCursor(tasksCursor);
newTask.setText("");
}
schemaHelper.close();
Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();
}
If this "doesn't work", please be more specific. Is it throwing an error, if so what kind?
You are doing a little too much work in your adapter. Please watch Android's Romain Guy at Google Talks discuss adapters and getView(). However since you only want to pass one special string to your createdOn TextView, let's do something very different and override setViewText():
Try this:
public class TasksAdapter extends SimpleCursorAdapter {
String prefix;
public TasksAdapter(Context context, int layout, Cursor cursor, String[] from, int[] to) {
super(context, layout, cursor, from, to);
// This is constant so set it once and consider adding the space to the end of the String in strings.xml
prefix = getString(R.string.added_on) + " ";
}
#Override
public void setViewText(TextView v, String text) {
if(v.getId() == R.id.lv_row_created_on)
v.setText(prefix + TaskHelper.formatDateWithSuffix(text));
else
super.setViewText(v, text);
}
}
The rest of the data is taken care of with SimpleCursorAdapter's existing methods.
I have created a SimpleCursorAdapter. I would like a way to compare two rows.
lets say the columns are called realData pracData. If i want to compare two columns how would I write the statement to achieve this.
Below is my code for my SimpleCursorAdapter
db = new DBAdapter(this);
db.open();
// db.insertContact("how do you print hello world", "print 'hello world';", "print hello", "hello", 1);
// db.insertContact("what is x=2 and y=5", "5", "7", "2", 2);
db.close();
/*
* Open the same SQLite database
* and read all it's content.
*/
db = new DBAdapter(this);
db.open();
Cursor cursor = db.getAllContacts();
startManagingCursor(cursor);
String[] from = new String[]{DBAdapter.question, DBAdapter.possibleAnsOne};
int[] to = new int[]{R.id.label, R.id.TextView01};
SimpleCursorAdapter cursorAdapter =
new SimpleCursorAdapter(this, R.layout.row, cursor, from, to);
listContent.setAdapter(cursorAdapter);
db.close();
This is from the ArrayAdapter
if (s.startsWith("how do you print hello world") || s.startsWith("iPhone")
|| s.startsWith("Solaris")) {
imageView.setImageResource(R.drawable.plus);
I want to do something similar but compare two rows in my database.
public class MyAdapter extends SimpleCursorAdapter {
private Context context;
private int layout;
public MyAdapter(Context context, int layout, Cursor c, String[] from,
int[] to) {
super(context, layout, c, from, to);
this.context = context;
this.layout = layout;
// TODO Auto-generated constructor stub
}
#Override
public void bindView(View v, Context context, Cursor c) {
// do your magic inhere :) the cursor will be at the correct row position
System.out.println("please select a cursor");
// int nameCol = c.getColumnIndex(People.NAME);
// ListView listContent = (ListView)findViewById(R.id.contentlist);
// ImageView imageView = (ImageView)findViewById(R.id.ImageView01);
int nameCol = c.getColumnIndex(DBAdapter.question);
System.out.println("What is the column index" +nameCol);
}
}
Extending the SimpleCursorAdapter and overriding bindView should work. I usually extend CursorAdapter, but try something à la
public class MyAdapter extends SimpleCursorAdapter {
#Override
public void bindView(View view, Context context, Cursor cursor) {
TextView label = view.findViewById(R.id.yourid);
// and then do something with cursor.getString(columnindex);
}
}
I have a listview which populates its content from SQLite Database.
Here's my code:
ListView listView = (ListView) findViewById(R.id.lstText);
listView.setOnItemClickListener(this);
listView.setAdapter(new MySimpleCursorAdapter(this, R.layout.listitems,
managedQuery(Uri.withAppendedPath(Provider.CONTENT_URI,
Database.Project.NAME), new String[] { BaseColumns._ID,
Database.Project.C_PROJECTTITLE,
Database.Project.C_SMALLIMAGE, Database.Project.C_PROJECTDESCRIPTION, Database.Project.C_ORGANIZATIONTITLE}, null, null, null),
new String[] { Database.Project.C_PROJECTTITLE,
Database.Project.C_SMALLIMAGE, Database.Project.C_PROJECTDESCRIPTION, Database.Project.C_ORGANIZATIONTITLE}, new int[] {
R.id.txt_title, R.id.image, R.id.txt_list_desc, R.id.txt_org}));
I want to put an extra String to some TextViews above when its displayed on the list. For example, I want to add a String with the word "from" on R.id.txt_org, before the populated String from the database which is Database.Project.C_ORGANIZATIONTITLE
Let's say the populated String is: New Organisation,
with an extra String "from" what will be displayed is: from New Organisation
Can anybody help me with that? Thank you very much.
EDITED:
FYI, this is my SimpleCursorAdapter method:
class MySimpleCursorAdapter extends SimpleCursorAdapter {
public MySimpleCursorAdapter(Context context, int layout, Cursor c,
String[] from, int[] to) {
super(context, layout, c, from, to);
loader = new ImageLoader(context);
this.context = context;
}
Context context=null;
ImageLoader loader = null;
public void setViewImage(ImageView v, String value) {
v.setTag(value);
loader.DisplayImage(value, context, v);
}
}
Since you're already using a custom adapter, override the adapter's bindView() and newView() methods, rather than getView(). That way you will not have to manually deal with recycling the row's view.
Within these method you can get the data from the resulting Cursor and manipulate it before binding it to your row's view.
GetView Vs. BindView in a custom CursorAdapter?
How to override CursorAdapter bindView
//Edit: some more code below. Note that this is just a rough outline and by no means complete or tested.
class MySimpleCursorAdapter extends SimpleCursorAdapter {
private ImageLoader mLoader = null;
private LayoutInflater mInflater = null;
private int mBusinessNameIndex = -1;
private int mSmallImageIndex = -1;
public MySimpleCursorAdapter(Context context, int layout, Cursor c,
String[] from, int[] to) {
super(context, layout, c, from, to);
mLoader = new ImageLoader(context);
mInflater = getLayoutInflater();
mBusinessNameIndex = c.getColumnIndexOrThrow(Database.Project.NAME);
mSmallImageIndex = c.getColumnIndexOrThrow(Database.Project.C_SMALLIMAGE);
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return mInflater.inflate(R.layout.row, null);
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
// Get your views from 'view'
TextView someTextView = (TextView) view.findViewById(R.id.xxx);
ImageView someImageView = (ImageView) view.findViewById(R.id.yyy);
// Set the data
someTextView.setText("from " + cursor.getString(mBusinessNameIndex));
mLoader.DisplayImage(cursor.getString(mSmallImageIndex ), context, someImageView);
}
}
I'm trying to populate listview from my SQLite database... this is how I get my data from database:
Cursor c = database.rawQuery("SELECT * FROM " + TableName, null);
int Column1 = c.getColumnIndex("uri");
int Column2 = c.getColumnIndex("file");
int Column3 = c.getColumnIndex("id");
c.moveToFirst();
if (c != null) {
do {
String uri = c.getString(Column1);
String file = c.getString(Column2);
int id = c.getInt(Column3);
} while (c.moveToNext());
}
I would normally add an array to listview like that:
ListView my_listview2 = (ListView) findViewById(R.id.listView1);
String my_array[] = {"Android", "iPhone"};
my_listview2.setAdapter(new ArrayAdapter<String>(this, R.layout.row, R.id.my_custom_row, my_array));
How can I make an array to setadapter from my sql query?
The best way to do this is to use a CursorAdapter or a SimpleCursorAdapter. This will give you the best performance and once you figure it out you'll find it's the simplest approach when using a SQLite db.
http://developer.android.com/reference/android/widget/SimpleCursorAdapter.html
Below is a simple CustomCursorAdapter that I use frequently. Just add the CustomCursorAdapter class as an inner class.
protected class CustomCursorAdapter extends SimpleCursorAdapter {
private int layout;
private LayoutInflater inflater;
private Context context;
public CustomCursorAdapter (Context context, int layout, Cursor c, String[] from, int[] to) {
super(context, layout, c, from, to);
this.layout = layout;
this.context = context;
inflater = LayoutInflater.from(context);
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
Log.i("NewView", newViewCount.toString());
View v = inflater.inflate(R.layout.list_cell, parent, false);
return v;
}
#Override
public void bindView(View v, Context context, Cursor c) {
//1 is the column where you're getting your data from
String name = c.getString(1);
/**
* Next set the name of the entry.
*/
TextView name_text = (TextView) v.findViewById(R.id.textView);
if (name_text != null) {
name_text.setText(name);
}
}
Create an instance of the CustomCursorAdapter like so...
You'll need to create your cursor just like you're already doing.
protected String[] from;
protected int[] to;
//From is the column name in your cursor where you're getting the data
//to is the id of the view it will map to
from = new String[]{"name"};
to = new int[]{R.id.textView};
CustomCursorAdapter adapter = new CustomCursorAdapter(this, R.layout.list, cursor, from, to);
listView.setAdapter(adapter);
I found working with the notepad tutorial very useful for learning about this.
It shows you how to implement the listview using the sqlite database in very easy steps.
http://developer.android.com/resources/tutorials/notepad/index.html
i have been having this issue for some time now, and have not gotten an answer for it yet. i have this custom Cursor adapter which i use to populate a list view from an sqlite database. Now my issue is that i want to populate the listview based on certain conditions.An example is if the condition is important, the listview should display only data that fits into that criteria and so on. I already have working methods that query the database accordingly.
now my problem is that, i can't seem to populate the listviews based on those methods and conditions without:
1) creating a copy of the exact same custom cursor adapter and just changing the names variables.
2) creating a copy of the exact xml layout and changing the id's.
As i say, its working this way, but i feel am having unnecessary classes and xml layout since its exactly the same thing. I know am doing something wrong, i just don't know what. Please any help and explanation would be appreciated. here is the necessary part of the code Code for the CustomCursorAdapter:
public class ViewItems extends ListActivity implements OnItemClickListener{
DBAdapter adapter;
Cursor cursor;
ListView list;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.view_list);
adapter = new DBAdapter(this);
adapter.open();
fillData();
list = (ListView)findViewById(android.R.id.list); // default android listView id
list.setOnItemClickListener(this);
}
// Different method calls
protected void fillImportantData() {
Cursor cursor = adapter.retrieveImportant();
startManagingCursor(cursor);
String[] from = new String[]{DBAdapter.NAME, DBAdapter.DATE, DBAdapter.TIME, DBAdapter.PRIORITY};
int[] to = new int[]{R.id.viewNameId, R.id.viewDateId, R.id.viewTimeId};
customCursorAdapter items = new customCursorAdapter(this, R.layout.view_items, cursor, from, to);
setListAdapter(items);
}
public class customCursorAdapter extends SimpleCursorAdapter {
private int layout;
Context context;
public customCursorAdapter(Context context, int layout, Cursor cursor, String[]from, int[] to) {
super(context, layout, cursor, from, to);
this.layout = layout;
this.context = context;
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
ViewHolder holder;
if(view != null){
holder = new ViewHolder();
holder.viewName = (TextView)view.findViewById(R.id.viewNameId);
holder.viewStartDate = (TextView)view.findViewById(R.id.viewDateId);
holder.viewStartTime = (TextView)view.findViewById(R.id.viewTimeId);
view.setTag(holder);
}else{
holder = (ViewHolder)view.getTag();
}
int namecol = cursor.getColumnIndex(DBAdapter.NAME);
String name = cursor.getString(namecol);
if(holder.viewName != null){
holder.viewName.setText(name);
holder.viewName.setTextColor(Color.RED);
}
String startDate = cursor.getString(cursor.getColumnIndex(DBAdapter.DATE));
holder.viewStartDate.setText(startDate);
String startTime = cursor.getString(cursor.getColumnIndex(DBAdapter.TIME));
holder.viewStartTime.setText(startTime);
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
LayoutInflater inflater = LayoutInflater.from(context);
final View view = inflater.inflate(layout, parent, false);
return view;
}
#Override
public long getItemId(int id){
return id;
}
#Override
public Object getItem(int position){
return position;
}
}
static class ViewHolder{
TextView viewName;
TextView viewStartDate;
TextView viewStartTime;
}
}
// methods in database
public Cursor retrieveAll(){
String[] resultColumns = new String[] {KEY_ID, NAME DATE, TIME, PRIORITY};
Cursor cursor = db.query(DATABASE_TABLE, resultColumns, null, , null, null, null);
return cursor;
}
public Cursor retrieveImportant(){
String[] resultColumns = new String[] {KEY_ID, NAME DATE, TIME, PRIORITY};
String[] condition = {"important"};
Cursor cursor = db.query(DATABASE_TABLE, resultColumns, PRIORITY + "=" + "?", condition, null, null, null);
return cursor;
}
If you change the data you wish to display, you will need to run a fresh query on the database and get a Cursor back that reflects that changed data. Depending on the nature of the changes, this may require a fresh CursorAdapter or merely a call to changeCursor(). If the new query returns the same columns and you want them displayed the same way, changeCursor() is probably sufficient. Otherwise, you will need to create a new CursorAdapter and call setAdapter() on your ListView to switch over to it.
You only need a different row layout if you are truly changing the row layout. You do not need to change IDs just for grins. Since you are not doing this in the code you have shown above, I am unclear what specifically you are worried about.