Problem using Cursor to populate a spinner - android

I'm having a problem populating my spinner with data from my SQLite database. Here's the code from my Activity. The Activity crashes with an Unable to start Activity ComponentInfo error where indicated with an arrow.
public class ProjectsActivity extends Activity {
private ReelDbAdapter dbHelper;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.projects_select);
fillProjectSpinner();
}
private void fillProjectSpinner(){
// initialize cursor to manage data binding to spinner
Cursor projectCursor = null;
Spinner spnExistingProjects = (Spinner)findViewById(R.id.spnExistingProject);
---> projectCursor = dbHelper.getExistingProjects();
//startManagingCursor(projectCursor);
/*
//get the list of project names from the database
String[] from = new String[] {dbHelper.clmProjectName};
//add a new item to the spinner for each of the rows in the database
int [] to = new int[]{R.id.txtViewProjectRow};
//initialize a cursor adapter (similar to ArrayAdapter when populating a spinner from a pre-defined array)
SimpleCursorAdapter projectAdapter = new SimpleCursorAdapter(this, R.layout.view_project_row, projectCursor, from, to);
//add all the rows to the spinner
spnExistingProjects.setAdapter(projectAdapter);
*/
}
Here's the code from the getExistingProjects method from my dbAdapter
public Cursor getExistingProjects() {
if(mDb == null)
{
this.open();
}
return mDb.query(dbTableProject, new String[] {clmProjectName, clmProjectShootingTitle, clmProjectJobNumber},
null, null, null, null, null);
}
Any clues on what I might be doing wrong?
TIA for any help.
Norm

Why don't you try making sure the query is returning something before returning the cursor in your method? Put a log line in that spits out the count of the cursor. Also, you should be able to see this easily while stepping through with the debugger.
Also, why assign null to the cursor's deceleration when you're just going to initialize it a few lines down. Do it all in one line.
Lastly, what db are you trying to one with that this.open() line? I obviously can't tell with just the code you've posted, but put a try catch around that whole thing and spit out the strackTrace. You should see your issue.

Related

How to pass the data in the database to a spinner

I'm creating a method to read all the information in the database and view it through a spinner here is the code i tried for this function
public Spinner loadArtist(){
SQLiteDatabase DB = getReadableDatabase();
String[] projection = {
ArtistMaster.Artist.ARTIST_NAME};
Cursor cursor = DB.query(
ArtistMaster.Artist.TABLE_ARTIST,
projection,
null,
null,
null,
null,
null);
Spinner itemIds = new ArrayList<>();
while(cursor.moveToNext()) {
long itemId = cursor.getLong(
cursor.getColumnIndex(ArtistMaster.Artist.ARTIST_NAME));
itemIds.setAdapter(itemId);
}
cursor.close();
return itemIds;
}
but it gives me an error in this line Spinner itemIds = new ArrayList<>();
Should i declare it as a list instead of spinner
itemIds should be defined as an ArrayList<Long>. A Spinner is a UI element and an ArrayList is a data structure. You will most likely need to map the data to your UI using an adapter of some sort, eg. an ArrayAdapter:
Spinner spinner = ... // findViewById, new Spinner() etc.
ArrayList<Long> itemIds = new ArrayList<>();
//... fill array with artist IDs
spinner.setAdapter(
new ArrayAdapter(
this, // Context, Activity etc.,
android.R.layout.simple_list_item_1, // Spinner TextView item resource ID
itemIds // Data set.
));
By default, ArrayAdapter will call Object#toString() on each data object in the collection.
I'd suggest that it would be easier if you used a Cursor Adpater as they are designed to be used with a Cursor and there is no need to generate arrays.
SimpleCursorAdapter being that, a simple but still pretty flexible adapter for use with Cursors.
The only issue is that a Cursor Adapter requires a column name specifically _id (BaseColumns._ID resolves to this (as used below)).
First have the following member variables (obviously names can be what you wish)
:-
Cursor mCursor;
SimpleCursorAdapter mAdapter;
Spinner spinner;
SQLiteDatabase db;
In the onCreate Method of the activity have
:-
spinner = this.findViewById(R.id.?????); //
db = ???????? (as per your existing code)
manageSpinner();
Have a method
:-
private void manageSpinner() {
mCursor = db.query(
ArtistMaster.Artist.ARTIST_NAME,
new String[]{"*","rowid AS " + BaseColumns._ID}, //<<<<<<<< adds _ID column (unless the table is a WITHOUT ROWID table, pretty unlikely)
null,null,null,null,null
);
if (mAdapter == null) {
mAdapter = new SimpleCursorAdapter(
this,
android.R.layout.simple_list_item_1,
mCursor,
new String[]{"the_column"}, // column(s) from which to extract data
new int[]{android.R.id.text1}, // layout views into which the data is placed
0
);
spinner.setAdapter(mAdapter);
// You want want to do something when an Item in the spinner is clicked (this does nothing as it is)
spinner.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//........... do your stuff here
// notes
// id will be the id of the row
// cursor will be positioned, so you can access data from the cursor if needed
}
});
} else {
mAdapter.swapCursor(mCursor);
}
}
Override the activity's onResume (refresh the spinner when returning to activity as underlying data may have changed) and onDestroy (to close the Cursor) methods using
:-
#Override
protected void onDestroy() {
super.onDestroy();
mCursor.close();
}
#Override
protected void onResume() {
super.onResume();
manageSpinner();
}

How I retrieve data from SQLite DB in a ListView? [duplicate]

I'd like to refresh the Listview items. These items are populated from SQLite database. My code is below
public class Weeve extends Activity {
private String[] lv_arr;
protected ListView CView;
private DBAdapter mDbHelper;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mDbHelper = new DBAdapter(this);
mDbHelper.open();
Cursor c = mDbHelper.getAll();
if (c.getCount() > 0)
{if (c.moveToFirst())
{
ArrayList strings = new ArrayList();
do {
String mC = c.getString(0);
strings.add(mC);
} while (c.moveToNext());
lv_arr = (String[]) strings.toArray(new String[strings.size()]);
}
}
else Toast.makeText(this,
"No more Records",
Toast.LENGTH_SHORT).show();
c.close();
ListView CView = new ListView(this);
CView.setAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, lv_arr));
setContentView(CView);}}
I'd like to make refreshing this list view after adding, updating or deleting SQLite table. These operations are called by content or option menu. I tried to create these code into a separated function and call it after every operation. But can't. I think setContentView(CView) statement.
I also tried to use SimpleCursorAdapter like notepad sample from Android.com. I got Thread error. Help me.
You can do that using Adapter.notifyDataSetChanged().
However, I find your code slightly off. You're fetching rows from the database using a cursor, just to create a new ArrayAdapter for the row values. Why not use a CursorAdapter to back your list? That's what it's meant for.
make sure all your activities are in the manifest

How do you amend a row value before displaying it using ListView and SimpleCursorAdaptor?

I'm using SimpleCursorAdaptor and a ListView to display the values in my SQLite database rows. One of the values in my row is a date (column 'date'). Rather than display this date I need to run this through a method that will return another string based on what the date is. This is the value I want displayed in my list rather than the actual value taken straight from the Database.
In short I wish to display all values from my database table row except for one, where I need to change it before displaying it.
Here is my code:
public class BinCollectionDayListActivity extends ListActivity{
//
private static final String fields[] = { "name", "date", BaseColumns._ID };
//
public void onCreate(Bundle savedInstanceState) {
//
super.onCreate(savedInstanceState);
//
DatabaseHelper helper = new DatabaseHelper(this);
SQLiteDatabase database = helper.getWritableDatabase();
Cursor data = database.query("names", fields, null, null, null, null, null);
CursorAdapter dataSource = new SimpleCursorAdapter(this, R.layout.binrow, data, fields, new int[] { R.id.name, R.id.date });
dataSource.getCursor().requery();
//
ListView view = getListView();
view.setHeaderDividersEnabled(true);
setListAdapter(dataSource);
//
helper.close();
database.close();
}
}
As you can tell I am pretty new to Android development and would love to know what the best approach would be to achieving the desired result.
Thanks in advance,
Tony
Two options that I've used before:
Array Adapter (Preferred):
Create an ArrayAdapter and populate the Cursor data into your ArrayAdapter.
http://anujarosha.wordpress.com/2011/11/17/how-to-create-a-listview-using-arrayadapter-in-android/
ViewBinder: On your Cursor, you can setup/specify a ViewBinder where you can check the data that's about to be mapped, perform some logic on it, and spit out a different result if desired. This is probably exactly what you're looking for, but do consider the ArrayAdapter as it tends to give you better control and it's a pain to switch these things later on.
Changing values from Cursor using SimpleCursorAdapter

Outputting ListView exception: File from xml type layout resource ID #0x102000a

I'm trying to output a list from an SQLite database and am getting this exception:
android.content.res.Resources$NotFoundException: File from xml type layout resource ID #0x102000a
After checking around on similar questions, I've made sure my ListView is defined as #id/android:list but still get the same exception. The problem occurs when the onCreate method in the ListActivity class completes. The getAllDiaryEntries() method does get the data from the db, but again, once it comes back to the ListActivity class and onCreate finishes I get the exception. Here's the relevant parts of code.
This is the ListActivity class:
public class DiarySchedule extends ListActivity
{
private DiaryDataSource datasource;
private static final String TAG = "DiaryDbAdapter";
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.diary_schedule);
datasource = new DiaryDataSource(this);
datasource.open();
List<DiaryEntry> values = datasource.getAllDiaryEntries();
ArrayAdapter<DiaryEntry> adapter = new ArrayAdapter<DiaryEntry>(this,
android.R.id.list, values);
setListAdapter(adapter);
}
Next we have the getAllDiaryEntries() method:
public List<DiaryEntry> getAllDiaryEntries()
{
List<DiaryEntry> diaryEntries = new ArrayList<DiaryEntry>();
Cursor cursor = database.query(DiaryDbAdapter.DIARY_TABLE,
allColumns, null, null, null, null, null);
cursor.moveToFirst();
while (!cursor.isAfterLast())
{
DiaryEntry diaryEntry = cursorToDiaryEntry(cursor);
diaryEntries.add(diaryEntry);
cursor.moveToNext();
}
// Make sure to close the cursor
cursor.close();
return diaryEntries;
}
And the layout (not styled or anything yet):
<ListView
android:id="#id/android:list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
I'm still pretty new to Android so may have missed something simple, but thanks in advance for any help.
Edited - here's the cursortoDiaryEntry method
private DiaryEntry cursorToDiaryEntry(Cursor cursor)
{
DiaryEntry diaryEntry = new DiaryEntry();
diaryEntry.setId(cursor.getLong(0));
diaryEntry.setTitle(cursor.getString(1));
diaryEntry.setDate(cursor.getString(2));
diaryEntry.setDescription(cursor.getString(3));
return diaryEntry;
}
The constructor (the one you're using) of the ArrayAdapter is defined as follows:
public ArrayAdapter (Context context, int textViewResourceId, List<T> objects)
In here the textViewResourceId is "The resource ID for a layout file containing a TextView to use when instantiating views.". See here.
You should pass a layout file containing a <TextView/> element, using R.layout.layout_file.
dennisg has the right answer to fix your problem.
Might I suggest that you are making extra work by turning your cursor into an array? You can save some cycles by using your cursor directly to create your list adapter.
Cursor cursor = database.query(DiaryDbAdapter.DIARY_TABLE,
allColumns, null, null, null, null, null);
getActivity().startManagingCursor(cursor);
String[] from = new String[] { DiaryDbAdapter.DIARY_ENTRY };
int[] to = new int[] { R.id.ListItem1 };
SimpleCursorAdapter adapter = new SimpleCursorAdapter(getActivity(),
R.layout.listlayoutdouble, cursor, from, to);
setListAdapter(adapter);
Your from string[] contains the list of columns you wish to include in the display, the to int[] contains the resource id's you wish to put the data into (in matching order with the from array). Then the adapter callout specifies which row layout to use, what cursor and the two arrays to map the data to the view.

Android ListView with SQLite

I'd like to refresh the Listview items. These items are populated from SQLite database. My code is below
public class Weeve extends Activity {
private String[] lv_arr;
protected ListView CView;
private DBAdapter mDbHelper;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mDbHelper = new DBAdapter(this);
mDbHelper.open();
Cursor c = mDbHelper.getAll();
if (c.getCount() > 0)
{if (c.moveToFirst())
{
ArrayList strings = new ArrayList();
do {
String mC = c.getString(0);
strings.add(mC);
} while (c.moveToNext());
lv_arr = (String[]) strings.toArray(new String[strings.size()]);
}
}
else Toast.makeText(this,
"No more Records",
Toast.LENGTH_SHORT).show();
c.close();
ListView CView = new ListView(this);
CView.setAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, lv_arr));
setContentView(CView);}}
I'd like to make refreshing this list view after adding, updating or deleting SQLite table. These operations are called by content or option menu. I tried to create these code into a separated function and call it after every operation. But can't. I think setContentView(CView) statement.
I also tried to use SimpleCursorAdapter like notepad sample from Android.com. I got Thread error. Help me.
You can do that using Adapter.notifyDataSetChanged().
However, I find your code slightly off. You're fetching rows from the database using a cursor, just to create a new ArrayAdapter for the row values. Why not use a CursorAdapter to back your list? That's what it's meant for.
make sure all your activities are in the manifest

Categories

Resources