Android 单击按钮时插入

Android 单击按钮时插入,android,sqlite,Android,Sqlite,为什么当我单击我的按钮时,我的应用程序会崩溃?如何修复它 单击按钮时,我需要将行插入我的SQLite数据库。它包含两个值,这应该足够简单。一个是日期,使用SimpleDataFormatter格式化。另一个只是ArrayList中的一个位置。我的代码中没有红线,但当我按下按钮插入行时,我的应用程序崩溃。下面是3个相互交互的Java文件中的代码。我有一种预感,问题在于我的Model.java,但可能不止这些。如果需要更多的代码,请询问 MainActivity.java public class

为什么当我单击我的
按钮时,我的应用程序会崩溃?如何修复它

单击按钮时,我需要将
插入我的
SQLite
数据库
。它包含两个值,这应该足够简单。一个是日期
,使用
SimpleDataFormatter
格式化。另一个只是
ArrayList
中的一个位置。我的代码中没有红线,但当我按下按钮插入行时,我的应用程序崩溃。下面是3个相互交互的
Java
文件中的代码。我有一种预感,问题在于我的Model.java,但可能不止这些。如果需要更多的代码,请询问

MainActivity.java

public class MainActivity extends Activity {
final String TAG = "*** DEBUG ***";

public static final String SMOKIN_DATA_FILE = "smokin.dat";
public static final int EDIT_ACTIVITY = 1;

public static Model model = null;
public static MySmokinDatabase mySmokinDatabase;
public static Cursor cursor;
public static SimpleCursorAdapter adapter;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);

    restoreModel();

    if (mySmokinDatabase == null)
        mySmokinDatabase = new MySmokinDatabase(this);

    refreshView();
}

@Override
protected void onResume() {
    super.onResume();

    if (model == null)
        restoreModel();

    refreshView();
}

protected void onPause() {
    super.onPause();

    saveModel();
}

private void refreshView() {
    Spinner spinner = (Spinner) findViewById(R.id.location_spinner);

    ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
             android.R.layout.simple_spinner_item, model.getLocationsArray());

    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);

    spinner.setAdapter(adapter);

    SimpleDateFormat sdf = new SimpleDateFormat("E, MMM dd");

    TextView dateText = (TextView) findViewById(R.id.date);
    TextView countText = (TextView) findViewById(R.id.count);
    TextView daysText = (TextView) findViewById(R.id.days);
    TextView totalText = (TextView) findViewById(R.id.total);
    TextView aveText = (TextView) findViewById(R.id.ave);

    GregorianCalendar now = new GregorianCalendar();
    dateText.setText(sdf.format(now.getTime()));
    //get today's count from data in the SQLite table - count entries with today's date
    countText.setText("" + "");
    //mySmokinDatabase.getTodaysCount());

    // Table data
    daysText.setText("" + String.format("%10d", model.getDays()));
    totalText.setText("" + "get total count from data in SQLite table - count total rows");

    if (model.getDays() > 0)
        aveText.setText("calc average from SQLite and model info");

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.activity_main, menu);
    return true;
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data)  { 
    super.onActivityResult(requestCode, resultCode, data); 
    if (resultCode == RESULT_OK && requestCode == EDIT_ACTIVITY) { 
        saveModel();
    }
}

public void smokedHandler(View view) {
    Spinner spinner = (Spinner) findViewById(R.id.location_spinner);

    String s = spinner.getSelectedItem().toString();
    String d = model.getDates();

    mySmokinDatabase.insertSmokinValues(new Model(s,d));

    cursor = mySmokinDatabase.getAllSmokinCursor();
    adapter.changeCursor(cursor);   

    refreshView();
}

public void restoreModel() {
    // Restore from disk, or start with an empty model
    try {
        ObjectInputStream ois = new ObjectInputStream(
                openFileInput(SMOKIN_DATA_FILE));

        model = (Model) ois.readObject();
        ois.close();
    }
    catch (Exception e){
        Log.v("*** DEBUG ***", "Error writing to file: " + e);
        model = new Model();
    }
}

public void saveModel() {
    Log.v("*** AJ ***", "In onPause");

    try {
        ObjectOutputStream oos = new ObjectOutputStream(
                openFileOutput(SMOKIN_DATA_FILE, Context.MODE_PRIVATE));

        oos.writeObject(model);
        oos.close();
    }
    catch (Exception e){
        Log.v("*** MatchIt ***", "Error writing to file: " + e);
    }
}
模型文件

public long insertSmokinValues(Model model) {
    ContentValues newSmokinValues = new ContentValues();
    newSmokinValues.put(KEY_DATE, model.getDates());
    newSmokinValues.put(KEY_LOCATION, model.getLocations());        
    SQLiteDatabase db = smokinDBOpenHelper.getWritableDatabase();

    return db.insert(SmokinDBOpenHelper.INCIDENTS_TABLE, null, newSmokinValues);
}

public Cursor getAllSmokinCursor() {
    SQLiteDatabase db = smokinDBOpenHelper.getWritableDatabase();

    return db.query(SmokinDBOpenHelper.INCIDENTS_TABLE, new String[] 
            {KEY_ID, KEY_LOCATION, KEY_DATE}, null, null, null, null, null);        
}
private ArrayList<String> locations = new ArrayList<String>();
public String [] defaultLocations = {"Home", "Work", "Commuting", "School", "Bar", 
"Restaurant", "Social Gathering", "Other"};

public Model(GregorianCalendar date){
    startDate = date;

    for (String s : this.defaultLocations)
        locations.add(s);
}

public Model(String s, String d) {
    place = s;
    dates = d;      
}

public String getDates() {
    GregorianCalendar gc = new GregorianCalendar();
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
    dates = sdf.format(gc.getTime());       

    return dates;
}   

public String getLocations() {
    for (String s : this.locations)
        place = s;
    return place;
}       
public Cursor getAllSmokinCursor() {
    SQLiteDatabase db = smokinDBOpenHelper.getWritableDatabase();

    return db.query(SmokinDBOpenHelper.INCIDENTS_TABLE, new String[] 
            {KEY_ID, KEY_LOCATION, KEY_DATE}, null, null, null, null, null);        
}
第119行:适配器.changeCursor(游标);所涉及的方法发布在我的DB文件中


一如既往,我们感谢您的帮助

Log说明了一切:您正在尝试使用
adapter
,它在此行中为
null

adapter.changeCursor(cursor); 
adapter.changeCursor(cursor);   
编辑:

正如我所想,您可以在这里声明
适配器
字段:

public static SimpleCursorAdapter adapter;
但是您不需要初始化它,而且正如您在Java中应该知道的那样,如果您在没有初始化的情况下声明一个字段,它就会被设置为
null
。这就是为什么你会犯错误

我个人没有使用过
SimpleCursorAdapter
类,但您可能想看看android文档中描述的它的构造函数:

因此,基本上在
onCreate()
方法中,您应该执行以下操作:

adapter = new SimpleCursorAdapter( this, 
                                   R.layout.some_layout,
                                   cursor,
                                   columns,
                                   to,
                                   0 );
在我之前发布的链接文档中描述了使用过的构造函数参数

您可能还希望检查此使用
SimpleCursorAdapter
的代码:

编辑: 就像其他人说的。
适配器负责
NPE

但是,采用正确的方法处理Sqlite
游标也很重要

重要的是要做到以下几点

更换

public long insertSmokinValues(Model model) {
    ContentValues newSmokinValues = new ContentValues();
    newSmokinValues.put(KEY_DATE, model.getDates());
    newSmokinValues.put(KEY_LOCATION, model.getLocations());        
    SQLiteDatabase db = smokinDBOpenHelper.getWritableDatabase();

    return db.insert(SmokinDBOpenHelper.INCIDENTS_TABLE, null, newSmokinValues);
}

public Cursor getAllSmokinCursor() {
    SQLiteDatabase db = smokinDBOpenHelper.getWritableDatabase();

    return db.query(SmokinDBOpenHelper.INCIDENTS_TABLE, new String[] 
            {KEY_ID, KEY_LOCATION, KEY_DATE}, null, null, null, null, null);        
}
private ArrayList<String> locations = new ArrayList<String>();
public String [] defaultLocations = {"Home", "Work", "Commuting", "School", "Bar", 
"Restaurant", "Social Gathering", "Other"};

public Model(GregorianCalendar date){
    startDate = date;

    for (String s : this.defaultLocations)
        locations.add(s);
}

public Model(String s, String d) {
    place = s;
    dates = d;      
}

public String getDates() {
    GregorianCalendar gc = new GregorianCalendar();
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
    dates = sdf.format(gc.getTime());       

    return dates;
}   

public String getLocations() {
    for (String s : this.locations)
        place = s;
    return place;
}       
public Cursor getAllSmokinCursor() {
    SQLiteDatabase db = smokinDBOpenHelper.getWritableDatabase();

    return db.query(SmokinDBOpenHelper.INCIDENTS_TABLE, new String[] 
            {KEY_ID, KEY_LOCATION, KEY_DATE}, null, null, null, null, null);        
}

public List<Model> getAllSmokinCursor() {
   List<Model> models= new ArrayList<Model>();
    SQLiteDatabase db = smokinDBOpenHelper.getWritableDatabase();

    Cursor cursor= db.query(SmokinDBOpenHelper.INCIDENTS_TABLE, new String[] 
            {KEY_ID, KEY_LOCATION, KEY_DATE}, null, null, null, null, null);        

 cursor.moveToFirst();
      while (!cursor.isAfterLast()) {
         Model device = fromCursorToObject(cursor);

         models.add(device);
         cursor.moveToNext();
      }
      // Make sure to close the cursor
      cursor.close();
      return models;

我假设您必须将getter/setter添加到您的模型类以及ID字段(private Long ID)

首先,您应该在以下函数中关闭数据库:

public long insertSmokinValues(Model model) {
    ContentValues newSmokinValues = new ContentValues();
    newSmokinValues.put(KEY_DATE, model.getDates());
    newSmokinValues.put(KEY_LOCATION, model.getLocations());        
    SQLiteDatabase db = smokinDBOpenHelper.getWritableDatabase();

    return db.insert(SmokinDBOpenHelper.INCIDENTS_TABLE, null, newSmokinValues);
}

public Cursor getAllSmokinCursor() {
    SQLiteDatabase db = smokinDBOpenHelper.getWritableDatabase();

    return db.query(SmokinDBOpenHelper.INCIDENTS_TABLE, new String[] 
            {KEY_ID, KEY_LOCATION, KEY_DATE}, null, null, null, null, null);        
}
第二,如果在
gestSmokinCursor
中没有结果时不想更改适配器中的光标,只需使用
moveToFirst
检查光标是否包含结果,如果不抛出自定义异常,则可以说
EmptyCursorException
,在获取光标时可以处理该异常

您还需要考虑如何关闭游标,因为我不确定在您更改游标和活动被破坏时适配器是否正在关闭游标,但这也是您的责任


如果您的
NullPointerException
位于此行:

adapter.changeCursor(cursor); 
adapter.changeCursor(cursor);   


然后,您的适配器只是
null
,需要启动,这与数据库无关,但是您的代码仍然有很多问题需要解决,否则,当人们开始使用应用程序时,您将遇到错误和泄漏。

从您的logcat发布堆栈跟踪。如果没有logcat,我们将什么也不做。logcat已发布,对此表示抱歉。还向DB文件中添加了另一个方法,即smokedHandler()方法中的NPE。那里有些东西是空的,119线是什么?您试图使用空对象。在我单击此按钮之前,数据库中没有任何值。数据库由日期和位置组成。此按钮添加这些条目。因此,返回“所有值”的游标没有返回任何内容,因为数据库中没有任何内容。有办法解决这个问题吗?日志上说
适配器
在哪里是空的?“没有行号的方法可能是任何东西。”Tushar他刚刚发布了119行中的内容。看看他的照片,啊,我明白了。很抱歉:)@irishwisky首先,您得到的错误与
光标
无关。第二件事是,当用户单击按钮时,您应该确保数据库已填充。现在检查解决方案,如果您不介意的话,可以向我解释一下
while循环
?不确定我是否完全理解它在那里做什么。@Irishwisky如果你的查询中没有任何限制,它可以返回一个列表,这就是我使用while loop的原因。如果他在日志中提到的地方得到了
NullPointerException
,那么这不是
光标的问题,而是
适配器的问题。看起来这似乎可以工作,但我对完全理解代码在这里所做的工作还很陌生。我迷路@Model device=方法\u到\u转换\u光标\u到\u模型(光标);看起来像是psuedo代码。我会调查这件事的,尽管可能需要一点时间while@IrishWhiskey我只是更新了我的帖子,添加了一个将游标转换为模型对象的方法。您可能100%正确。虽然这是家庭作业,但我认为教授是在故意教我们一些东西。他经常在任务到期后再看一遍,并发布适当的约定和更现实的解决方案。仅仅因为它运行,并不意味着它被正确编程。我理解。@irishwisky我理解您只是想让它运行,我指出的事情将帮助您解决
NullPointerException
解决后将收到的异常。即使适配器不是
null
,您编写的代码也会引发异常。感谢您的帮助。我需要学习更多关于
光标
适配器
。不过,你确实为我指明了正确的方向,当我完成学习时,我相信你的帖子会非常有意义