Question

i ve created a project with a single activity in android and i want to add a new record to database by pressing "insert button" as i showed in picture, but i want as soon as the New record saved to database , ListView updates and show the added record to the list in the last position...

when i run this code unexpected error occures and it close where is the error or any suggestion ...

enter image description here

i put all the codes and layout here...

MainActivity.java

package com.example.db;

import java.util.ArrayList;

import android.app.Activity;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.Toast;

public class MainActivity extends Activity implements OnClickListener {

Button Btninser;
SQLiteDatabase db;
EditText etName, etPhone;
ListView lv;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    etName = (EditText) findViewById(R.id.etName);
    etPhone = (EditText) findViewById(R.id.etPhone);
    Btninsert = (Button) findViewById(R.id.btnInsert);
    lv = (ListView) findViewById(R.id.listView1);
    Btninsert.setOnClickListener(this);
    Open_Create();

}

    public void Open_Create() {
    db = openOrCreateDatabase("MyDB1", MODE_PRIVATE, null);
    db.execSQL("CREATE TABLE IF NOT EXISTS MyTable (_id INTEGER PRIMARY KEY AUTOINCREMENT, LastName VARCHAR,Phone VARCHAR);");

}

public void Insert_Info() {
    db.execSQL("INSERT INTO MyTable (LastName,Phone) VALUES('" + etName.getText().toString()
            + "','" + etPhone.getText().toString() + "');");

    Populate_ListView();

    // db.close();
    Toast.makeText(this, "Data has been saved!", Toast.LENGTH_LONG).show();

}

public void Populate_ListView() {
    Cursor cursor = db.rawQuery("SELECT LastName,Phone FROM MyTable", null);
    startManagingCursor(cursor);

    String[] from = new String[] { "LastName", "Phone" };
    int[] to = new int[] { R.id.tvItemListName, R.id.tvItemListPhone };

    SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
            R.layout.item_list, cursor, from, to);

    lv.setAdapter(adapter);
}

And here is the XML file

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" >

         <TextView
            android:id="@+id/textView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_alignParentTop="true"
            android:text="Name" />

        <EditText
            android:id="@+id/etName"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:layout_toRightOf="@+id/textView1"
            android:ems="10" >

            <requestFocus />
        </EditText>

        <TextView
            android:id="@+id/textView2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_alignParentTop="true"
            android:text="Phone" />

        <EditText
            android:id="@+id/etPhone"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:layout_toRightOf="@+id/textView1"
            android:ems="10" >
        </EditText>

        <Button
            android:id="@+id/btnInsert"
            style="?android:attr/buttonStyleSmall"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:text="Insert" />

    <ListView
    android:id="@+id/listView1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="21dp" >
    </ListView>

</RelativeLayout>

I ve added the error from DDMS also as you can see in Error page It mentioned a field "_id" that i never had it!!!! :( confusing me too much...

enter image description here

Was it helpful?

Solution

If you want to use a Cursor, Android automatically assumes that your tables have a column called _id which acts as the row's unique primary identifier, for more details on that see the "Class Overview" section of the CursorAdapter's documentation which says:

Adapter that exposes data from a Cursor to a ListView widget. The Cursor must include a column named "_id" or this class will not work.

Basically all you need to do is replace your CREATE TABLE call with:

db.execSQL("CREATE TABLE IF NOT EXISTS MyTable (_id INTEGER PRIMARY KEY AUTOINCREMENT, LastName VARCHAR,Phone VARCHAR);");

That should fix your crash. To get it to automatically refresh the list, see my comment regrading notifyDatasetChanged().

And as a sidenote: I'd strongly recommend using a SQLiteOpenHelper instance to handle the opening and creation of your tables, rather than what you are doing now, it's bad form to repeatedly call CREATE TABLE IF NOT EXISTS where you could only call it the one time you know it'd need to be called. Vogella.com has a great guide on that.

Edit: Based on your last edit of your code: You're still not requesting the _id field that you made. If you don't have it in your SELECT statement the cursor can't access it!

Replace your rawQuery in Populate_ListView with SELECT * FROM MyTable so that the _id field is also returned by the cursor.

OTHER TIPS

Have you try to delete Open_Create() call from onClick() method? You have two consecutive call to openOrCreateDatabase() without any close() in the middle. Don't forget the try { ... } catch (SQLiteException) { ... }. You test.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top