I have connected a database in my Android Application. Now I have created a button and when it is clicked, that should get the next data from the table of database. I have cursor and he moveToFirst() and moveToNext() methods in my code. also I have set onclick listener to my button. but in output when I click the button, its is not fetching the next data from database
heres the part of code where I have tried to set on click listener for button
c=myDbHelper.query(myDbHelper.DB_PATH +"/MainTable",null, null, null, null,null, null);
c.moveToFirst();
myques=(TextView)findViewById(R.id.question);
myrg=(RadioGroup)findViewById(R.id.rg1);
myc1=(RadioButton)findViewById(R.id.radio0);
myc2=(RadioButton)findViewById(R.id.radio1);
myc3=(RadioButton)findViewById(R.id.radio2);
myc4=(RadioButton)findViewById(R.id.radio3);
NxtQues=(Button)findViewById(R.id.button1);
myques.setText(c.getString(1));
myc1.setText(c.getString(2));
myc2.setText(c.getString(3));
myc3.setText(c.getString(4));
myc4.setText(c.getString(5));
NxtQues.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View V)
{
c.moveToNext();
}
});
what changes should I make in this code to set on click listener in a proper way.
So in your code is a few problems. At first here:
c = myDbHelper.query(myDbHelper.DB_PATH +"/MainTable", ...);
As first parameter of query() method is "raw" tablename so you can't assign there full path of your database(if it isn't real tablename...), it's wrong. Just assign MainTable like this:
c = myDbHelper.query("MainTable", null, null, null, null, null, null);
Then your logic about fetching data from database is not good at all. You assigned values to your widgets only once and no more. They never be refreshed, you need to call as many times setText() method as you want to update widget's content. Actually you don't update them.
You need to change your logic to:
#Override
public void onClick(View V) {
if (c.moveToNext()) {
myques.setText(c.getString(1));
myc1.setText(c.getString(2));
myc2.setText(c.getString(3));
myc3.setText(c.getString(4));
myc4.setText(c.getString(5));
}
}
Recommendation:
When you are using "getters" methods of Cursor, i recommend you to use column names to get columns indexes:
myques.setText(c.getString(c.getColumnIndex("columnName")));
Related
I have a table, c_question in which I stored some questions with this structure
autoincrement column _id,
question,
option1,
option2,
option3,
correct_answer
Now I want to retrieve the question in a TextView and the answers in a RadioGroup.
If the user selects the correct answer, then the question and options will change
in the same page.
Logcat: fatal exception at main ..... cursorIndexOutOfBoundException
The output shows the last data (question with answers) I entered in the db and if I click any answer, the app crashes.
String row="SELECT* FROM c_question";
final Cursor c=db.rawQuery(row, null);
c.moveToFirst();
if(c.moveToFirst())
{
do
{
tv1.setText(c.getString(1));
r0=(RadioButton)findViewById(R.id.radio0);
r0.setText(c.getString(2));
r1=(RadioButton)findViewById(R.id.radio1);
r1.setText(c.getString(3));
r2=(RadioButton)findViewById(R.id.radio2);
r2.setText(c.getString(4));
k.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
int idd=r.getCheckedRadioButtonId();
r0=(RadioButton)findViewById(idd);
String r=r0.getText().toString();
if(r.equals(c.getString(5)))
{
Toast.makeText(QuestionsOn.this, "correct!!!", 123).show();
;
} else
Toast.makeText(QuestionsOn.this, "Incorrect!!!", 123).show();
}
});
} while(c.moveToNext());
}
Output showing the last data(Question with options) I entered in DB
That's what you get when you update the save views in a loop; only the last "row" will get shown.
If you want to show a list of data from the database, you need some Adapter class in a ListView / ViewPager
and if I click any option, the app crashes...
According to the error, c.getString(5) doesn't exist, so seems like you didn't create your database with the correct number of columns.
I'm having a very strange issue on my Android app wherein when I am inserting a value to a DB table, the first entry is disappearing somehow. However, any subsequent entries are appearing fine.
To be a little more specific, part of my application allows users to create a simple log where they enter some text and when they save it, it shows up on a list of log entries. However, when I try to insert the very first entry to an empty table, that entry is not being displayed, nor does the database indicate there is any data when I query for a count.
Interestingly enough, when I look at the return of the database insert call (SQLiteDatabase.insert()) I see a valid row number returned. In fact, when I look at any log entry I've saved to the database, the row number is correctly incrementing. As per the docs, my understanding is that if a non-negative number is returned, the insert was successful.
Here is the code that takes the result of the EditText from my AlertDialog, creates a new log entry, and calls the insert method:
newPainLogEntryDialog.setPositiveButton("Save",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
//make new pain log entry
PainLog painLog = new PainLog();
painLog.setPainEntry(input.getText().toString());
painLog.setPainDateTime(Calendar.getInstance());
Database.init(PainLogTab.this.getActivity());
Database.createPainLog(painLog);
updatePainLogList();
//display success to user
Toast.makeText(PainLogTab.this.getActivity(),
"Log entry saved", Toast.LENGTH_SHORT).show();
}
});
The code for Database.createPainLog():
public static long createPainLog(PainLog painLog) {
ContentValues cv = new ContentValues();
cv.put(COLUMN_PAINLOG_ENTRY, painLog.getPainEntry());
cv.put(COLUMN_PAINLOG_DATETIME, painLog.getPainDateTimeString());
return getDatabase().insert(PAINLOG_TABLE, null, cv);
}
And the last call before the Toast message is updatePainLogList(), which gets all the DB entries:
public void updatePainLogList(){
Database.init(PainLogTab.this.getActivity());
final List<PainLog> painLogs = Database.getAllPainLogs();
painLogListAdapter.setPainLogs(painLogs);
Log.d(getClass().getSimpleName(), "number of painLogs found: " + painLogs.size());
getActivity().runOnUiThread(new Runnable() {
public void run() {
// reload content
PainLogTab.this.painLogListAdapter.notifyDataSetChanged();
if(painLogs.size() > 0){
getView().findViewById(android.R.id.empty).setVisibility(View.INVISIBLE);
}else{
getView().findViewById(android.R.id.empty).setVisibility(View.VISIBLE);
}
}
});
}
And for completion sake, the body of the getAll() and its accompanying method getCursor():
public static Cursor getPainLogCursor() {
String[] columns = new String[] {
COLUMN_PAINLOG_ID,
COLUMN_PAINLOG_ENTRY,
COLUMN_PAINLOG_DATETIME
};
return getDatabase().query(PAINLOG_TABLE, columns, null, null, null, null,
null);
}
public static List<PainLog> getAllPainLogs() {
List<PainLog> painLogs = new ArrayList<PainLog>();
Cursor cursor = Database.getPainLogCursor();
if (cursor.moveToFirst()) {
while (cursor.moveToNext()) {
PainLog painLog = new PainLog();
painLog.setId(cursor.getInt(IDX_PAINLOG_ID));
painLog.setPainEntry(cursor.getString(IDX_PAINLOG_ENTRY));
painLog.setPainDateTime(cursor.getString(IDX_PAINLOG_DATETIME));
painLogs.add(painLog);
}
}
cursor.close();
return painLogs;
}
Now with some code I can explain what debugging steps I have taken thus far. As mentioned above, when I look at the return of the DB insert, I get a positive, non-zero number. However, when I try to print the number of logs in the immediately following update method (no deletes or anything get called en route), it displays 0, and indeed if I follow the Cursor I find that it never enters the loop which adds logs to the list which is displayed, also indicating it is not picking up the entry.
I have tried to set the DB insert in a transaction so that I can manually commit, but this does not help either. What makes this more interesting to me is that I have similar functionality elsewhere in my app where I save user preferences and display them in a list, and this does not suffer from the same problem...I have compared against this code and couldn't find any differences that would cause it.
To sum it up, my question is two-fold: why is only my first insert on an empty table showing up as not there, while all following ones are fine?; why am I getting a valid return from the database insert and yet immediately following the insert when I query for that data it is missing?
Thanks in advance for any help you can provide :)
if (cursor.moveToFirst()) {
while (cursor.moveToNext()) {
This skips the first row in cursor. moveToFirst() moves to the first row and moveToNext() moves to the next one, skipping the first one.
You can replace this with just while (cursor.moveToNext()). When you get your cursor from a query, it is placed at index -1 first i.e. at the row before the first one.
if (cursor.moveToFirst()) {
while (cursor.moveToNext()) {
This would be the best solution for it....
I have a problem, I created database for all activities, and in each activity I should insert information to database, so for the first activity , the insert is done , for the second activity I update the row with new insertion to complete all information and so on, my problem is that I don't know how to refer to the last row, I mean what should I do that make the update for the second activity occurs to the last row that has been insert in the first activity, do you have any suggestions ???
Well you can just use the primary key. When you insert something into the database you get as a return value the primary key. You can add this to the Intent that opens the other Activity and that way refer back to the row you previously inserted.
Edit:
I don't know if you are working with and SQLiteDatabase Object or with a ContentProvider, but in any case the code would be pretty much the same. In this example I will work directly with an SQLiteDatabase Object, even though using ContentProviders is in most cases the better alternative.
In your first Activity:
// When you perform an insert you get the id of the row which was just inserted.
long id = sqliteDatabase.insert("some_table", null, contentValues);
// The id will be -1 if an error occured
if(id >= 0) {
...
}
...
// When you start your second Activity you can add the id to the Intent
Intent intent = new Intent(getApplicationContext(), SecondActivity.class);
// The String is a tag with which you can later retrieve the id from the Intent.
// Note that you should never hardcode String like that, use constants in your app.
intent.putExtra("rowId", id);
In the onCreate Method of your second Activity you can retrieve the id:
#Override
protected void onCreate (Bundle savedInstanceState) {
// Check if the Activity has been created for the first time
if(savedInstanceState == null) {
// Retrieve the Intent with which the Activity was started
Intent intent = getIntent();
long id = intent.getLongExtra ("rowId", -1);
// If id is valid proceed
if(id >= 0) {
Cursor cursor = sqliteDatabase.query("some_table", columns, "_id = ?",
new String[] { String.valueOf(id) }, null, null, null, null);
// Check if Cursor is valid and if yes read your data.
if(cursor != null) {
...
}
}
}
}
The best way to do this would be to add a column to your database which will hold the time the row was inserted. Then when you need the latest row, query for the one with the most current time. An example SQL string would be:
SELECT * FROM my_table WHERE 1 ORDER BY time_stamp LIMIT 1
I am trying to write a simple app just to display on screen the results on a sql query.
public class ContactLookup extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Cursor c = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,
null, null, null, null
);
}
}
How exactly do I print the results of the cursor? Everything I find goes into to way more detail then I need at the moment... I just want to know how to get that variable printed on screen.
You'll need to have something that shows text (or whatever you get from your DB). Most likely this will be a simple TextView (you can do this in the XML-Layout or in Java-Code).
If you declared your TextView in the XML-Layout, then you'll need to find the TextView in order to set it's text.
After that, you'll want to move the Cursor to the first set of data in it so you can read your results from it.
After that, you can simply use the Cursor's getXX()-methods to get your values form the result-set.
I have an app that uses a cursor to select data via rawQuery from an SQLite DB to populate a ListView in Android. Every time the user clicks on a listview item I create a new instance of Activity to re-populate listview.
Is it better to call cursor.close() and db.close() to avoid memory problems? I actually have db.close() in OnDestroy() of my activity.
You can close the cursor once you have retrieved the values for that particular object inside your method.
btw...You don't have to recreate a listview every time for a user click event. Just notify that there is some change in data of your adapter that has been set on the listview.
Something like
youradaptername.notifyDataSetChanged();
This should repopulate contents inside ur listview automatically.
Well if you are creating a new instance every time of the same Activity (though I am not sure its a good programming practice). You can close the cursor as soon as your have finished traversing / iterating through the source of the listview.
Example:
A sample implementation would be something like
//Pre cursor code
startManagingCursor(cursor);
if (cursor.moveToFirst()) {
do {
if (cursor.getString(0).equals(value)) {
cursor.close();
a = true;
return a;
}
} while (cursor.moveToNext());
}
//Close cursor here, when its work is complete
cursor.close();
//Post cursor code ...