No matter what I seem to try and do regarding this listview and trying to get it to dynamically update whenever I hit a button it doesn't work and always throws a NPE.
The code is below and I would really welcome an assistance. I've tried requery and I've tried notifyDataSetChanged, but I'll be honest, this is only my second project and the 1st one that is using a database or listview and I'll struggling.
DatabaseHelper
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.provider.BaseColumns;
import android.util.Log;
public class DatabaseHelper extends SQLiteOpenHelper {
private static final String TAG = DatabaseHelper.class.getSimpleName();
public static final String DATABASE_NAME = "reordermymeds.db";
public static final int DATABASE_VERSION = 3;
public static final String TABLE_NAME = "Medicines";
public static final String C_ID = BaseColumns._ID;
public static final String C_MED_NAME = "med_name";
public static final String TABLE_NAME_SURG = "Surgeries";
public static final String SURGERY_NAME = "sName";
public static final String SURGERY_TEL = "sTel";
public static final String SURGERY_MAIL = "sMail";
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
// TODO Auto-generated constructor stub
}
@Override
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
String sql = String.format("CREATE TABLE %s (%s INTEGER PRIMARY KEY, %s TEXT)", TABLE_NAME, C_ID, C_MED_NAME);
String sql_surg = String.format(
"create table %s (%s int primary key, %s TEXT, %s TEXT, %s TEXT)",
TABLE_NAME_SURG, C_ID, SURGERY_NAME, SURGERY_TEL, SURGERY_MAIL);
Log.d(TAG, "onCreate sql: "+sql);
db.execSQL(sql);
db.execSQL(sql_surg);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
db.execSQL("d开发者_运维知识库rop table if exists " + TABLE_NAME);
db.execSQL("drop table if exists " + TABLE_NAME_SURG);
this.onCreate(db);
}
}
and
Activity
import android.app.ListActivity;
import android.content.ContentValues;
import android.content.Context;
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.Button;
import android.widget.EditText;
import android.widget.SimpleCursorAdapter;
import android.widget.Toast;
public class pills extends ListActivity {
public static final String C_MED_NAME = "med_name";
public SimpleCursorAdapter ladapter;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.pills);
try {
DatabaseHelper DBHelper= new DatabaseHelper(this);
SQLiteDatabase db = DBHelper.getReadableDatabase();
Cursor cur = db.query("Medicines", null, null, null, null, null, null);
startManagingCursor(cur);
String [] columns = new String[] {C_MED_NAME};
int [] to = new int[] {R.id.meditem};
SimpleCursorAdapter ladapter = new SimpleCursorAdapter(this, R.layout.meditem, cur, columns, to);
this.setListAdapter(ladapter);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Button saveMed = (Button) findViewById(R.id.pills_newmedsubmit);
saveMed.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
final EditText newMed = (EditText) findViewById(R.id.pills_newmedtxtbox);
if (newMed.getText().toString().equals("")) {
Context context = getApplicationContext();
CharSequence text = "Please type the name of a new prescription item.";
int duration = Toast.LENGTH_SHORT;
Toast toast= Toast.makeText(context, text, duration);
toast.show();
}
else
{
String medName = newMed.getText().toString();
insertNewPrescriptionItem(medName);
EditText clearTextBox = (EditText) findViewById(R.id.pills_newmedtxtbox);
clearTextBox.setText("");
Context context = getApplicationContext();
CharSequence text = "Saved";
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
}
setListAdapter(ladapter);
ladapter.notifyDataSetChanged();
}
});}
private void insertNewPrescriptionItem (String medName){
DatabaseHelper DbHelper = new DatabaseHelper(this);
SQLiteDatabase db = DbHelper.getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put(DatabaseHelper.C_MED_NAME, medName);
db.insert(DatabaseHelper.TABLE_NAME, DatabaseHelper.C_MED_NAME, cv);
db.close();
}
}
and of course, last but not least, the stack trace. I can see the line with the error, but every I have tried using Google just results in the same thing. Can anyone show were I must be going stupidly wrong??
Stack Trace
08-11 01:21:26.095: ERROR/AndroidRuntime(15327): FATAL EXCEPTION: main
08-11 01:21:26.095: ERROR/AndroidRuntime(15327): java.lang.NullPointerException
08-11 01:21:26.095: ERROR/AndroidRuntime(15327): at com.asurya.reordmymeds.pills$1.onClick(pills.java:90)
08-11 01:21:26.095: ERROR/AndroidRuntime(15327): at android.view.View.performClick(View.java:2485)
08-11 01:21:26.095: ERROR/AndroidRuntime(15327): at android.view.View$PerformClick.run(View.java:9080)
08-11 01:21:26.095: ERROR/AndroidRuntime(15327): at android.os.Handler.handleCallback(Handler.java:587)
08-11 01:21:26.095: ERROR/AndroidRuntime(15327): at android.os.Handler.dispatchMessage(Handler.java:92)
08-11 01:21:26.095: ERROR/AndroidRuntime(15327): at android.os.Looper.loop(Looper.java:130)
08-11 01:21:26.095: ERROR/AndroidRuntime(15327): at android.app.ActivityThread.main(ActivityThread.java:3683)
08-11 01:21:26.095: ERROR/AndroidRuntime(15327): at java.lang.reflect.Method.invokeNative(Native Method)
08-11 01:21:26.095: ERROR/AndroidRuntime(15327): at java.lang.reflect.Method.invoke(Method.java:507)
08-11 01:21:26.095: ERROR/AndroidRuntime(15327): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
08-11 01:21:26.095: ERROR/AndroidRuntime(15327): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
08-11 01:21:26.095: ERROR/AndroidRuntime(15327): at dalvik.system.NativeStart.main(Native Method)
08-11 01:21:26.107: WARN/ActivityManager(110): Force finishing activity com.asurya.reordmymeds/.pills
Oops. It would have helped if I let you all know that rather than count them yourselves:)
The line of code which is causing the NPE is:
ladapter.notifyDataSetChanged();
Also, if I simply comment out this line, the app runs fine, but you have to refresh the Activity to see the updated data in the database. Thanks all.
import android.app.ListActivity;
import android.content.ContentValues;
import android.content.Context;
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.Button;
import android.widget.EditText;
import android.widget.SimpleCursorAdapter;
import android.widget.Toast;
public class pills extends ListActivity {
public static final String C_MED_NAME = "med_name";
public SimpleCursorAdapter ladapter;
Context context;
Cursor cur;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.pills);
context=this;
try {
DatabaseHelper DBHelper= new DatabaseHelper(this);
SQLiteDatabase db = DBHelper.getReadableDatabase();
cur = db.query("Medicines", null, null, null, null, null, null);
startManagingCursor(cur);
String [] columns = new String[] {C_MED_NAME};
int [] to = new int[] {R.id.meditem};
ladapter = new SimpleCursorAdapter(this, R.layout.meditem, cur, columns, to);
this.setListAdapter(ladapter);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Button saveMed = (Button) findViewById(R.id.pills_newmedsubmit);
saveMed.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
final EditText newMed = (EditText) findViewById(R.id.pills_newmedtxtbox);
if (newMed.getText().toString().equals("")) {
// Context context = getApplicationContext();
CharSequence text = "Please type the name of a new prescription item.";
int duration = Toast.LENGTH_SHORT;
Toast toast= Toast.makeText(context, text, duration);
toast.show();
}
else
{
String medName = newMed.getText().toString();
insertNewPrescriptionItem(medName);
EditText clearTextBox = (EditText) findViewById(R.id.pills_newmedtxtbox);
clearTextBox.setText("");
// Context context = getApplicationContext();
CharSequence text = "Saved";
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
}
refresh();
}
});}
private void insertNewPrescriptionItem (String medName){
DatabaseHelper DbHelper = new DatabaseHelper(this);
SQLiteDatabase db = DbHelper.getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put(DatabaseHelper.C_MED_NAME, medName);
db.insert(DatabaseHelper.TABLE_NAME, DatabaseHelper.C_MED_NAME, cv);
db.close();
}
}
public void refresh(){
cur = db.query("Medicines", null, null, null, null, null, null);
ladapter.notifyDataSetChanged();
}
try this, i think your context is null thats why it is happening so
Once you have set the adapter you dont need to do .setListAdapter()
. Declare you adapter as global variable in your class (as you did at the beginning), and then just call adapter.notifyDataSetChanged()
at point where there is change in the adapter data. If it doesnt work, try reinstantiating the adapter on and on, and then calling notifyDataSetChanged()
.
In the try remove the type definition of the adapter, you already did public SimpleCursorAdapter ladapter;
just feed it with data in the try.
精彩评论