retriveing data from exisint sqlite database - android

I wish to store it in arraylist and then display it out in listView. Is there any solution to it ? how do I set the adapter? how can I link this two up and display it into a listview using arrayList?
DBhelper.java
public ArrayList<String> getDataarray(){
SQLiteQueryBuilder querybuilder=new SQLiteQueryBuilder();
querybuilder.setTables(DATABASE_TABLES);
String [] columns= new String[]{ KEY_ROWID,KEY_USERNAME,KEY_AGE,KEY_ClINIC,KEY_PHONE,KEY_EMAIL,KEY_DATESIGNUP
,KEY_CONDITIONID,KEY_DOCTORID,KEY_LOGINID,KEY_ACTIVITYNAME,KEY_NOTIFICATIONNAME,KEY_GROUPNAME,KEY_APPROVED
};
Cursor c= ourdatabase.query(DATABASE_TABLES, columns, null,null, null, null, null);
String result="";
ArrayList<String> resultarray = new ArrayList<String>();
int iRow=c.getColumnIndex(KEY_ROWID);
int iUserName=c.getColumnIndex(KEY_USERNAME);
int iAge=c.getColumnIndex(KEY_AGE);
int iClinic=c.getColumnIndex(KEY_ClINIC);
int iPhone=c.getColumnIndex(KEY_PHONE);
int iEmail=c.getColumnIndex(KEY_EMAIL);
int iDateSignup=c.getColumnIndex(KEY_DATESIGNUP);
int iConditionID=c.getColumnIndex(KEY_CONDITIONID);
int iDoctorID=c.getColumnIndex(KEY_DOCTORID);
int iLoginID=c.getColumnIndex(KEY_LOGINID);
int iActivityName=c.getColumnIndex(KEY_ACTIVITYNAME);
int iNotificationName=c.getColumnIndex(KEY_NOTIFICATIONNAME);
int iGroupName=c.getColumnIndex(KEY_GROUPNAME);
int iApproved=c.getColumnIndex(KEY_APPROVED);
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery("SELECT value FROM " + DATABASE_TABLES, null);
if(cursor.moveToFirst()) {
do {
resultarray.add(cursor.getString(cursor.getColumnIndex("value")));
}while(cursor.moveToNext());
}
cursor.close();
db.close();
return resultarray;
}
ProfileFragment.java this is the page where i want to retrieve out at the listView how can i retrieve it from the database instead of array
public View getView( int position ,View convertView,ViewGroup parent){
LayoutInflater inflater= (LayoutInflater) context.getSystemService(android.content.Context.LAYOUT_INFLATER_SERVICE);
View row =inflater.inflate(R.layout.profile_list,parent,false);
TextView myProfile=(TextView)row.findViewById(R.id.Profile);
TextView myCondition=(TextView)row.findViewById(R.id.condition);
myProfile.setText(ProfileArray[position]);
myCondition.setText(resultarray[position]);
return row;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootview = inflater.inflate(R.layout.user,container,false);
Resources res=getResources();
Profile=res.getStringArray(R.array.Profile);
//how can i change the line below to let it get the data from the database array? or is there any other method?
condition=res.getStringArray(R.array.Profile_values);
list.setAdapter(adapter);
list=(ListView)rootview.findViewById(R.id.listView1);
return rootview;
}

Do you want to display all of data?
Think about using CursorLoader with SimpleCursorAdapter. It will load your data once activity is created in background. And in your activity class just implement interface LoaderManager.LoaderCallback, and in onCreate you simply initialize Loader with getSupportLoaderManager().initLoader(LOADER_ID, null, this)
Here is the link with good example http://www.androiddesignpatterns.com/2012/07/understanding-loadermanager.html
EDIT:
This code use in onCreate
// init DB
db = new DB(this);
db.open();
// forming columns from DB to views
String[] from = new String[] { KEY_ROWID, KEY_USERNAME, KEY_AGE...}; //array of columns from DB
int[] to = new int[] { R.id.textviewId, R.id.textviewUserName, R.id.textviewAge }; //Array of of view components
// create adapter
scAdapter = new SimpleCursorAdapter(this, R.layout.item, null, from, to, 0);
ListView lvData = (ListView) findViewById(R.id.lvData); // listview where you want to display data
lvData.setAdapter(scAdapter);
//init loader
getSupportLoaderManager().initLoader(0, null, this);
//implement these mothods with interface `LoaderManager.LoaderCallback<Cursor>`
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle bndl) {
return new MyCursorLoader(this, db);
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
scAdapter.swapCursor(cursor);
}
#Override
public void onLoaderReset(Loader<Cursor> loader) {
}
This code must works for you.
EDIT2
static class MyCursorLoader extends CursorLoader {
DB db;
public MyCursorLoader(Context context, DB db) {
super(context);
this.db = db;
}
#Override
public Cursor loadInBackground() {
return db.getAllData();
}
}
One detail added. This is a class where you download your data from db and return filled cursor.

Related

How to display more than one column data from the same table on ListView?

My ListView currently is able to display only one column data. I want it to display two column data.
Here is the code for my ListView:
public class ProjectExplorer extends ListActivity {
private projectdatabase database;
protected Cursor cursor;
protected ListAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
database = new projectdatabase(ProjectExplorer.this);
getinfo();
}
private void getinfo() {
database.open();
cursor = database.getDataforDisplay();
adapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_1, cursor, new String[] {"project_name"}, new int[] { android.R.id.text1 }, 0);
setListAdapter(adapter);
}
#Override
public void onListItemClick(ListView parent, View view, int position, long id) {
super.onListItemClick(parent, view, position, id);
Cursor c = ((SimpleCursorAdapter)parent.getAdapter()).getCursor();
c.moveToPosition(position);
// get project name here
String str_projectname= c.getString(c.getColumnIndex("project_name"));
Toast.makeText(this, str_projectname, Toast.LENGTH_LONG).show();
}
Here is the method in database class which return the cursor:
public Cursor getDataforDisplay () {
String[] columns = new String[] {KEY_ROWID, PROJECT_NAME, PROJECT_FINISH_DATE, PROJECT_DIFFICULTY, PROJECT_STATUS};
Cursor c = projectDatabase.query(DATABASE_TABLE, columns, null, null, null, null, null);
projectDatabase.query(DATABASE_TABLE, columns, null, null, null, null, null);
c.moveToFirst();
return c;
}
I also want to display KEY_ROWID which is defined as _id
You can use android.R.layout.simple_list_item_2 specifying column no.2 from table from where data can be retrieved and specifies location with help of it can be displayed on Activity - android.R.id.text2
adapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_2, cursor, new String[] {"project_name","column_no2"}, new int[] { android.R.id.text1, andriod.R.id.text2 }, 0);
You can also create your on custom Adapter specifying your own Listview and creating it from scratch and customized everything.
The best way to achieve this at least in my opinion is to create custom Adapter for your ListView in that case you can set your own design how single listview element should look like . Just populate some arrays using your Cursor and set them to your custom adapter.

Getting the _id of the rows in ListVew right

I have a ListView which shows a bunsh of values from a SQLite table. First I used a SimpleCursorAdapter to fill the ListView based on a Cursor from an SQL query. I switched over to using a SimpleAdapter in stead because I had to manipulate/add data in the list before sending it over to the ListView.
Using the SimpleCursorAdapter the id returned from the ListView after tapping a row is the correct ID from the database table, but using a SimpleAdapter the id looks like its just generated by the ListView because it is the same as the position.
My table looks like this:
_id | col1 | col2 | col3
The method producing the cursor for the SimpleCursorAdapter looks like this:
public Cursor fetchDataAsCursor()
{
return db.query("table_name", new String[] { "_id", "col1", "col2"}, null, null, null, null, null);
}
The method filling in the ListView using SimpleCursorAdapter looks like this:
private void simpleFillData()
{
Cursor cursor = dbAdapter.fetchDataAsCursor();
startManagingCursor(cursor);
String[] from = new String[] {"col1", "col2"};
int[] to = new int[] {R.id.col1, R.id.col2};
SimpleCursorAdapter notes = new SimpleCursorAdapter(this,
R.layout.list_row, cursor, from, to);
setListAdapter(notes);
}
This works fine as the id returned is ok in the following method:
protected void onListItemClick(ListView l, View v, int position, long id)
{
super.onListItemClick(l, v, position, id);
Intent i = new Intent(this, DetailActivity.class);
i.putExtra("_id", id);
startActivityForResult(i, ACTIVITY_EDIT);
}
Now switching over to the SimpleAdapter.
The code for producing the List:
public ArrayList<HashMap<String, Object>> getList()
{
ArrayList <HashMap<String, Object>> list = new ArrayList();
c = fetchDataAsCursor();
c.moveToFirst();
for(int i = 0; i < c.getCount(); i++)
{
HashMap<String, Object> h = new HashMap<String, Object>();
h.put("_id", c.getLong(0));
h.put("col1", c.getString(1));
h.put("col2", c.getString(2));
//This is the extra column
h.put("extra", calculateSomeStuff(c.getString(1), c.getString(2));
list.add(h);
c.moveToNext();
}
return list;
}
And then for the method which fills the ListView:
private void fillData()
{
ArrayList<HashMap<String, Object>> list = dbAdapter.getList();
String[] from = new String[] {"col1", "col2", "extra"};
int[] to = new int[] {R.id.col1, R.id.col2, R.id.extra};
SimpleAdapter notes = new SimpleAdapter(this, list, R.layout.list_row, from, to);
setListAdapter(notes);
}
In this last method the ListView failes to pick up the _id value in the list. I would have guessed that it would do this automaticly as it does when using a SimpleCursorAdapter
Is there a way to manipulate the id of a row in a ListView to be sure that it has the same value as the _id key in the database table?
(All code examples is greatly simplified)
Edit:
I figured it out. I had to make my own subclass of SimpleAdapter which overrides public long getItemId(int position)
public class MyListAdapter extends SimpleAdapter
{
private final String ID = "_id";
public PunchListAdapter(Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to)
{
super(context, data, resource, from, to);
}
#Override
public long getItemId(int position)
{
Object o = getItem(position);
long id = position;
if(o instanceof Map)
{
Map m = (Map)o;
if(m.containsKey(ID))
{
o = m.get(ID);
if(o instanceof Long)
id = (Long)o;
}
}
return id;
}
}
That is bad way to work with cursor by using SimpleAdapter. You should implement CursorAdapter.
public class MyCursorAdapter extends CursorAdapter
{
LayoutInflater inflater;
public MyCursorAdapter(Context context, Cursor c) {
super(context, c);
inflater = LayoutInflater.from(context);
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
//cursor is already setted to requared position, just get your column
TextView tv1 = (TextView)view.findViewById(R.id.textView1);
TextView tv2 = (TextView)view.findViewById(R.id.textView2);
tv1.setText(cursor.getString(1));
tv2.setText(cursor.getString(2));
viev.addOnClickListener(new OnClickListener{
public void onClick(View v){
...
cursor.getLong(0);
...
}
});
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return inflater.inflate(R.layout.my_raw_view, parent, false);
}
}
Than just set adapter to listview in your activity.
Cursor cursor = fetchDataAsCursor();
ListView myListView = (ListView)findViewById(R.id.my_list_view);
myListView.setAdapter(new MyCursorAdapter(this,cursot));

android IllegalStateException, database already closed

I am using SimpleCursorAdapter and database table to populate a List. The list gets populated and I am able to click on list items to open the desired item(This starts a new activity). The problem is when I press the back key, I got Following error.
IllegalStateException: database already closed.
My code is as follows:
public class populatingLectures extends ListActivity{
private static String[] FROM = {SUBJECT, TOPIC, LECTURENUMBER, DATE };
private static int[] TO = {R.id.subject, R.id.topic,
R.id.lecturenumber, R.id.date };
private static String[] data = { SUBJECT, TOPIC, LECTURENUMBER, _DATA };
private static String ORDER_BY = DATE + " DESC";
private SoftCopyDatabase lectures;
String gotId;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SoftCopyDatabase lectures = new SoftCopyDatabase(this);
try {
Cursor cursor = getLectures();
showLectures(cursor);
} finally {
lectures.close();
}
}
public void onStart() {
super.onStart();
lectures = new SoftCopyDatabase(this);
try {
Cursor cursor = getLectures();
showLectures(cursor);
} finally {
lectures.close();
}
}
private Cursor getLectures() {
SQLiteDatabase db = lectures.getReadableDatabase();
Cursor cursor = db.query(TABLE_NAME,null, "subject=?", new String[] {OpenClick.subjectName}, null, null,
ORDER_BY);
startManagingCursor(cursor);
return cursor;
}
private void showLectures(Cursor cursor) {
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
R.layout.item_lectures, cursor, FROM, TO);
setListAdapter(adapter);
}
private Cursor getFileName(String ID) {
SQLiteDatabase db = lectures.getReadableDatabase();
Cursor cursor = db.query(TABLE_NAME, data, "_ID=?",
new String[] { ID }, null, null, null);
startManagingCursor(cursor);
return cursor;
}
#Override
protected void onListItemClick(ListView listView, View view, int position,
long id) {
super.onListItemClick(listView, view, position, id);
//...CODE TO START NEW ACTIVITY
}
}
}
Kindly tell me what mistake am I doing. Because I am not closing the database explicitly any where.
Regards,
Waneya Iqbal.
finally
{
lectures.close();
}
I think this line gives the exception, so put it in onDestroy().
You're closing the database as soon as you populate the list. You should move the
lectures.close()
line from onStart() to onDestroy(), which will make sure your database gets closed when the activity is complete, rather than as soon as the list is populated.

onListItemClick, what statement do I need to get the value?

i can add to a db and list as a listview.
When I click a list item using onListItemClick, what statement do I
need to get the value?
Thanks in advance.
public class Main extends ListActivity {
private static String[] FROM = { _ID, DESCRIPTION, UN };
private static String ORDER_BY = DESCRIPTION + " ASC";
private static int[] TO = {R.id.itemrowid, R.id.itemdescription, R.id.itemun };
private EventsData events;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
events = new EventsData(this);
try {
Cursor cursor = getEvents();
showEvents(cursor);
} finally {
events.close();
}
**public void onListItemClick(ListView parent, View v, int position, long id) {
// What statement to put here to get the value of _ID,DESCRIPTION, UN
// selected**?
}
private Cursor getEvents() {
// Perform a managed query. The Activity will handle closing
// and re-querying the cursor when needed.
SQLiteDatabase db = events.getReadableDatabase();
Cursor cursor = db.query(TABLE_NAME, FROM, null, null, null,
null, ORDER_BY);
startManagingCursor(cursor);
return cursor;
}
private void showEvents(Cursor cursor) {
// Set up data binding
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
R.layout.item, cursor, FROM, TO);
setListAdapter(adapter);
}
First, you need to obtain item at clicked position:
Cursor cursor = getListAdapter().getItem(position);
Then you can get data from this cursor (I don't know what types do you use, so just for example it will be int and String):
int id = cursor.getInt(cursor.getColumnIndex(_ID));
String description = cursor.getString(cursor.getColumnIndex(DESCRIPTION));
See documentation for Cursor's available methods.
Adding to sergey answer you can also directly see what View was clicked and use findViewById() to find the components, therefore, the values you want.
This is just an alternative being the method Sergey much less 'patchy'

Strange behaviour with custom cursor adapter android

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.

Categories

Resources