Android - Displaying all SQLite database entries in a ListView - java

What I am trying to do is display the contents of the database in a ListView. The layout contains a ListView which I have used and implemented but I can't seem to get them working together (or even the cursor), could someone give me a hand and an explanation of why my cursor implementation doesn't work?
I have a method to return the database entries as a Cursor:
public Cursor getAllRecords() {
return db.query(DATABASE_TABLE, new String[] {KEY_ROWID, KEY_TEXT}, null, null, null, null, null);
}
I have the class where I want to insert and display the database entries:
Button add;
EditText tM;
ListView generalList;
DBAdapter dba = new DBAdapter(this);
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_general);
add = (Button) findViewById(R.id.button1);
tM = (EditText) findViewById(R.id.editText1);
generalList = (ListView) findViewById(R.id.generalList);
Cursor c = dba.getAllRecords();
c.moveToFirst();
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.id.generalList, c, new String[] {dba.KEY_TEXT}, new int[] {R.id.generalList}, 0);
// This doesn't seem to work for me, I don't know how to fix it
// or how to then get it working with the ListView
generalList.setAdapter(adapter);
add.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
insertIntoDatabase();
}
});
}
public void insertIntoDatabase() {
dba.open();
dba.insertRecord(textMessage.getText().toString());
Toast.makeText(this, "Added:\n" + tM.getText().toString(), Toast.LENGTH_LONG).show();
dba.close();
}

When using a ListView with a CursorAdapter, the Cursor returned from the column must contain a column with the name _id uniquely identifying each row. I'm guessing that the one column you are fetching (dba.KEY_TEXT) is not named "_id". You can either add a column to your table named _id or when you perform your SELECT have the database return the name as _id
i.e.
SELECT col_name as _id FROM my_table;
OR
SELECT col_name _id FROM my_table;

if the list contains only 1 TextView, you can use android.R.layout.simple_list_item_1 instead of your R.id.generalList.
and change the new int[] {R.id.generalList} to new int[] {android.R.id.text1}
like :
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_1, c, new String[] {dba.KEY_TEXT}, new int[] {android.R.id.text1}, 0);

on the arguments that receives the simplecursoradapter, remember the layout it receives is the layout for the actual item not the listview. so remove the R.id.generalList from there, cause that is the id that identified the listview not a full layout. so replace that with a layout that contains a textview. now, on the int array goes the id of the textview that will show the text you want and on the string array pass on the names of the fields in the record read from the database. do as mentioned by aprian and know that you can customize items as much as you need.

Related

How to inflate the XML layout using Custom ArrayAdapter Class?

In my app,I need to have delete button in my listview,So to do that I refer this link ListView with Add and Delete Buttons in each Row in android.
I refer the first answer,but the problem now is,in that they are adding items to the listview like this.
ArrayList<String> list = new ArrayList<String>();
list.add("item1");
list.add("item2");
But ,I fetch data to listview using cursor.Below one is my code to fetch data from database to listview.
private void fetchData() {
db = helper.getReadableDatabase();
Cursor c = db.query(DBhelper.TABLE1, null, null, null, null, null, null);
adapter = new SimpleCursorAdapter(
this,
R.layout.row,
c,
new String[]{DBhelper.Name},
new int[]{R.id.lblreload});
rldlist.setAdapter(adapter);
}
Now I don't have any idea,how to modify that code.please help me to solve this.
You can subclass CursorAdapter and provide implementations for newView() and bindView().

ListView doesn't show items when updated from a fucntion

I am using Android Studio, I have an activity with a list, when I add items to the list after filling a textbox and clicking a button the items show, but when I try to add items to the list from an SQL query the list does not show the items.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent d = getIntent();
setContentView(R.layout.activity_add_group);
String choosengroup = d.getStringExtra("chosen");
groupn = (EditText) findViewById(R.id.gname);
soldiern = (EditText) findViewById(R.id.soldiername);
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, list);
final Button savebutton = (Button) findViewById(R.id.savegroup);
final Button addbutton = (Button) findViewById(R.id.addsoldier);
final DatabaseHelper db;
db = new DatabaseHelper(getApplicationContext());
setListAdapter(adapter);
if(!choosengroup.equals("")){
groupn.setText(choosengroup);
list=getAllsoldiers(choosengroup,db);
// Log.d("list",list.toString());
onContentChanged ();
}
savebutton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
db.createGroup(new Groups(groupn.getText().toString())); //Creates a group in Groups table
// Creates a new table for the specific group
db.getWritableDatabase().execSQL(" CREATE TABLE `Group_"+groupn.getText().toString()+"` (`id` INTEGER PRIMARY KEY AUTOINCREMENT ,`name` TEXT,`ghours` INTEGER DEFAULT "+'"'+"0"+'"'+",`ahours`INTEGER DEFAULT "+'"'+"0"+'"'+", `khours` INTEGER DEFAULT "+'"'+"0"+'"'+");");
for (String name: list) {
// Log.d("names:",name.toString());
db.getWritableDatabase().execSQL("INSERT INTO `Group_"+groupn.getText().toString()+"` (name) VALUES('"+name+"');");
}
Intent act2 = new Intent(view.getContext(),ChooseGroup.class);
startActivity(act2);
}
});
addbutton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// soldier.add(new Soldiers(soldiern.getText().toString()));
list.add(soldiern.getText().toString());
soldiern.setText("");
//setListAdapter(adapter);
Log.d("list",list.toString());
onContentChanged ();
}
});
The addbutton.setOnClickListener add items and they are shown on the list.
But this :
if(!choosengroup.equals("")){
groupn.setText(choosengroup);
list=getAllsoldiers(choosengroup,db);
// Log.d("list",list.toString());
onContentChanged ();
}
Does not show the items on the listview.
Any idea why?
Thanks in advance.
Try
list.addAll(getAllsoldiers(choosengroup,db));
instead of
list=getAllsoldiers(choosengroup,db);
My thinking is that the assignment:
list=getAllsoldiers(choosengroup,db);
changes the value of the reference held in list from the original list to a new reference, and the adapter is still using the reference to the original list.
ie when you created the adapter, you passed in the value of the reference to the original list
when you did the assignment, you just changed the value of reference stored in list, but the adapter is still holding the pointer to the original list
using addAll() will add the items to the original list which is still being referenced by your adapter.

Sectioning Listview

can somebody give me an example on how to section the listview?
im using SimpleCursorAdapter to display the datas in the listview..
my code is like this.
private WordDbAdapter dbHelper;
private SimpleCursorAdapter dataAdapter;
this are the codes on the onCreate() method.
dbHelper = new WordDbAdapter(this);
dbHelper.open();
//Clean all data
dbHelper.deleteAllWords();
//Add some data
dbHelper.insertSomeWords();
//Generate ListView from SQLite Database
displayListView();
and this is the code outside the onCreate method.
#SuppressWarnings("deprecation")
private void displayListView() {
Cursor cursor = dbHelper.fetchAllWords();
// The desired columns to be bound
String[] columns = new String[] {
WordDbAdapter.KEY_WORD,
};
// the XML defined views which the data will be bound to
int[] to = new int[] {
R.id.Word,
};
// create the adapter using the cursor pointing to the desired data
//as well as the layout information
dataAdapter = new SimpleCursorAdapter(
this, R.layout.word_info,
cursor,
columns,
to
);
ListView listView = (ListView) findViewById(R.id.Diclist);
// Assign adapter to ListView
listView.setAdapter(dataAdapter);
listView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> listView, View view,
int position, long id) {
// Get the cursor, positioned to the corresponding row in the result set
Cursor cursor = (Cursor) listView.getItemAtPosition(position);
// Get the word name from this row in the database.
String wordSelected =
cursor.getString(cursor.getColumnIndexOrThrow("word"));
String wordSyllabication =
cursor.getString(cursor.getColumnIndexOrThrow("syllabication"));
String wordPartofSpeech =
cursor.getString(cursor.getColumnIndexOrThrow("partofspeech"));
String wordMeaning =
cursor.getString(cursor.getColumnIndexOrThrow("meaning"));
EditText TextDic = (EditText) findViewById(R.id.TextDic);
TextDic.setText(wordSelected);
Toast.makeText(getApplicationContext(),
wordSyllabication + "\n" + wordPartofSpeech + "\n" + wordMeaning , Toast.LENGTH_SHORT).show();
}
});
I found a good example of sectioned listview on this blog.It is done by using ArrayAdapter but you can see the concept and try to manipulate the code accordingly to make it work with SimpleCursorAdapter.
I hope it will be helpful !!
This is tricky with a cursor adapter as you have to remap your positions. I've made a library called SectionCursorAdapter to help with this. It's really easy to implement. To get this to work with your data, when you extend the SectionCursorAdapter just do the following.
#Override
protected Object getSectionFromCursor(Cursor cursor) {
int columnIndex = cursor.getColumnIndex("word");
String word = cursor.getString(columnIndex);
return word.toUpperCase().substring(0, 1);
}
Right now you don't have to worry about recycling your views but you do have to bind the data yourself. If this library gets popular enough I will add a SimpleSectionCursorAdapter.

setContentView doesn't allow search to work

I have been tryng to get my search function working ever since adopting TabHosts and I have figured out that in my onCreate method for my Search class that when setContentView(R.layout.main); it causes the following error
03-30 09:19:53.301: E/AndroidRuntime(728): android.view.WindowManager$BadTokenException: Unable to add window -- token android.app.LocalActivityManager$LocalActivityRecord#4053c270 is not valid; is your activity running?
When I comment it out though the search dialog pops up when you click on the hardware search button and I can type a value and press search but then I get the next stumbling block
03-30 09:23:37.061: D/PhoneWindow(776): couldn't save which view has focus because the focused view com.android.internal.policy.impl.PhoneWindow$DecorView#4053ff38 has no id.
Below is my code as it is at the moment for my Search class
public class Search extends ListActivity {
private TextView mTextView;
//protected ListAdapter adapter;
private DxDbAdapter mDbHelper;
DxSimpleCursorAdapter adapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.main);
//mTextView = (TextView) findViewById(R.id.text1);
// Get the intent, verify the action and get the query
Intent intent = getIntent();
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
String query = intent.getStringExtra(SearchManager.QUERY);
doMySearch(query);
}
}
public void doMySearch(String query_results) {
//SQLiteDatabase db = (new DatabaseHelper(this)).getWritableDatabase();
mDbHelper = new DxDbAdapter(this);
mDbHelper.open();
String[] columns = new String[] {"diagnosis", "diagcode"};
int[] to = new int[] {R.id.diagnosis, R.id.code};
// Add "No Results Found" message
Cursor cursor = mDbHelper.search(query_results.trim());
//Cursor cursor = db.rawQuery("Select _id, diagnosis, diagcode From DiagLookup Where diagnosis Like ? order by diagnosis asc", new String[]{"%"+query_results.trim()+"%"});
/* if (cursor == null) {
mTextView.setText(getString(R.string.no_results, new Object[] {query_results}));
}
else {*/
adapter = new DxSimpleCursorAdapter(this,R.layout.list_detail,cursor,columns,to);
setListAdapter(adapter);
// }
}
public void onListItemClick(ListView parent, View view, int position, long id) {
SQLiteDatabase db = (new DatabaseHelper(this)).getWritableDatabase();
Cursor c = (Cursor) getListAdapter().getItem(position);
String arg = c.getString(c.getColumnIndex("_id"));
Cursor cursor = db.rawQuery("Select category, subcategory From DiagLookup Where _id = ?", new String[]{""+arg});
cursor.moveToFirst();
Context context = getApplicationContext();
CharSequence text = "Category: " + cursor.getString(cursor.getColumnIndex("category")) + "\nSubcategory: " + cursor.getString(cursor.getColumnIndex("subcategory"));
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
}
}
Furthermore I created a custom SimpleCursorAdapter so I can do some actions to an imageview. When I originally had entered adapter = new SimpleCursorAdapter(this,R.layout.list_detail,cursor,columns,to); entering a search term and pressing on the search button had populated the listview but my imageview was not functioning so when I just changed the code to adapter = new DxSimpleCursorAdapter(this,R.layout.list_detail,cursor,columns,to); and added on the top DxSimpleCursorAdapter adapter; it no longer worked and caused the couldn't save focus error.
I am using TabActivity and ActivityGroup to create tabs along the top of my app and I think my context is messed up which is causing the focus to be lost...I am not sure though.
Anyone with some guidance on how I can go about solving these issues?
Thanks in advance.
If you are using TabActivity, why use the ListActivity again? If you want to use the ListView inside the Tabs, you can simply define it in the layout xml file.
If you want to use the Tabs inside an activity, then try this out, Android: TabHost without TabActivity
Switch to ViewPager instead of TabActivity Set default page for ViewPager in Android

Getting the row ID of a listview from a Android SQlite database

I have created a listview which displays all the people in the database. But how do I get the row id of the one I select so I can pass that infomation to the next activity.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.load_game1);
listContent = (ListView)findViewById(R.id.contentlist);
mDbAdapter = new DbAdapter(this);
mDbAdapter.open();
Cursor cursor = mDbAdapter.fetchAll();
startManagingCursor(cursor);
String[] from = new String[]{DbAdapter.KEY_NAME, DbAdapter.KEY_ROWID};
int[] to = new int[]{R.id.text};
cursorAdapter = new SimpleCursorAdapter(this, R.layout.row, cursor, from, to);
listContent.setAdapter(cursorAdapter);
mDbAdapter.close();
}
Which displays
displays http://i.minus.com/iGEtGKGyF1Wgc.png
Now I want to click on a name get that row id from the database.
Use this API call: cursorAdapter.getItemId(positionInListView)
Use setOnItemClickListener on your Listview then you will get the id of the selected item (item id start from 0 but Database _id column is start from 1 so you should send id+1, please confirm this).
And send the id using intents.
You have to register implement and add an OnItemClickListener to the list so you can react when an item was clicked. The item id will be passed into the onListItemClick() method of the OnItemClickListener.

Categories