3

为什么单击我的应用程序会崩溃button,如何解决?

单击按钮时,row我需要在其中插入一个。SQLite database它包含两个值,这应该很容易。一个是date, 使用simpledateformatter. 另一个只是一个位置ArrayList。我的代码中没有红线,但是当我按下该insert行的按钮时,我的应用程序崩溃了。下面是来自Java相互交互的 3 个文件的代码。我有一种预感,问题出在我的 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;
}       

根据要求的日志猫:

 03-18 15:52:42.397: W/dalvikvm(676): threadid=1: thread exiting with uncaught  
 exception
 (group=0x40a13300)
 03-18 15:52:42.457: E/AndroidRuntime(676): FATAL EXCEPTION: main
03-18 15:52:42.457: E/AndroidRuntime(676): java.lang.IllegalStateException: Could not    
execute method of the activity
03-18 15:52:42.457: E/AndroidRuntime(676):  at    
android.view.View$1.onClick(View.java:3591)
03-18 15:52:42.457: E/AndroidRuntime(676):  at   
android.view.View.performClick(View.java:4084)
03-18 15:52:42.457: E/AndroidRuntime(676):  at   
android.view.View$PerformClick.run(View.java:16966)
03-18 15:52:42.457: E/AndroidRuntime(676):  at   
android.os.Handler.handleCallback(Handler.java:615)
03-18 15:52:42.457: E/AndroidRuntime(676):  at   
android.os.Handler.dispatchMessage(Handler.java:92)
03-18 15:52:42.457: E/AndroidRuntime(676):  at android.os.Looper.loop(Looper.java:137)
03-18 15:52:42.457: E/AndroidRuntime(676):  at   
android.app.ActivityThread.main(ActivityThread.java:4745)
03-18 15:52:42.457: E/AndroidRuntime(676):  at    
java.lang.reflect.Method.invokeNative(Native Method)
03-18 15:52:42.457: E/AndroidRuntime(676):  at 
java.lang.reflect.Method.invoke(Method.java:511)
03-18 15:52:42.457: E/AndroidRuntime(676):  at 
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
03-18 15:52:42.457: E/AndroidRuntime(676):  at    
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
03-18 15:52:42.457: E/AndroidRuntime(676):  at dalvik.system.NativeStart.main(Native   
Method)
03-18 15:52:42.457: E/AndroidRuntime(676): Caused by: 
java.lang.reflect.InvocationTargetException
03-18 15:52:42.457: E/AndroidRuntime(676):  at   
java.lang.reflect.Method.invokeNative(Native Method)
03-18 15:52:42.457: E/AndroidRuntime(676):  at   
java.lang.reflect.Method.invoke(Method.java:511)
03-18 15:52:42.457: E/AndroidRuntime(676):  at   
android.view.View$1.onClick(View.java:3586)
03-18 15:52:42.457: E/AndroidRuntime(676):  ... 11 more
03-18 15:52:42.457: E/AndroidRuntime(676): Caused by: java.lang.NullPointerException
03-18 15:52:42.457: E/AndroidRuntime(676):  at     
com.example.smokin4ThomasSullivan.MainActivity.smokedHandler(MainActivity.java:119)
03-18 15:52:42.457: E/AndroidRuntime(676):  ... 14 more

第 119 行:adapter.changeCursor(cursor); 所涉及的方法发布在我的数据库文件中

一如既往地感谢任何帮助!

4

3 回答 3

3

日志说明了一切:您正在尝试使用adapter这一null行中的内容:

adapter.changeCursor(cursor); 

编辑:

正如我所想,你adapter在这里声明你的领域:

public static SimpleCursorAdapter adapter;

但是你没有初始化它,正如你在 Java 中应该知道的,如果你声明一个没有初始化的字段,它被设置为null. 这就是为什么你得到你的错误。

我没有亲自使用过SimpleCursorAdapter类,但你可能想看看它在 android 文档中描述的构造函数:http: //developer.android.com/reference/android/widget/SimpleCursorAdapter.html

所以基本上内部onCreate()方法,你应该做这样的事情:

adapter = new SimpleCursorAdapter( this, 
                                   R.layout.some_layout,
                                   cursor,
                                   columns,
                                   to,
                                   0 );

使用的构造函数的参数在我之前发布链接的文档中进行了描述。

您可能还想检查使用以下代码的代码SimpleCursorAdapterhttp ://www.mysamplecode.com/2012/07/android-listview-cursoradapter-sqlite.html

于 2013-03-18T20:30:55.120 回答
1

编辑: 就像其他人说的那样。adapter负责人是正确的NPE

但是,通过处理 Sqlite 采用正确的方法也很重要cursor

执行以下操作很重要

代替

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;

}

我在这里使用一个列表,因为您的 requestpublic static Device 没有任何限制

fromCursorToObject(Cursor cursor) {
      Model model = new Model();
      int i = 0;
      model.setId(cursor.getLong(i++));
      model.setLocation(cursor.getString(i++));
      model.setDate(cursor.getString(i++));
      return model;
   }

我假设您必须将 getter/setter 添加到您的 Model 类以及 ID 字段(私有 Long id)

于 2013-03-18T20:34:02.407 回答
1

首先你应该在这些函数中关闭数据库:

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);   

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

于 2013-03-18T20:44:06.887 回答