我已将我的活动设置为listview-> Listview-> listview->表格布局 - >等等 在导航应用程序应用程序时工作得很好。但是程序随机崩溃只是时间问题。
03-06 21:12:29.350: W/dalvikvm(7132): threadid=3: thread exiting with uncaught exception (group=0x4001b188)
03-06 21:12:29.350: E/AndroidRuntime(7132): Uncaught handler: thread main exiting due to uncaught exception
03-06 21:12:29.370: E/AndroidRuntime(7132): java.lang.NullPointerException
03-06 21:12:29.370: E/AndroidRuntime(7132): at wanted.pro.madlibs.title.onListItemClick(title.java:55)
03-06 21:12:29.370: E/AndroidRuntime(7132): at android.app.ListActivity$2.onItemClick(ListActivity.java:312)
03-06 21:12:29.370: E/AndroidRuntime(7132): at android.widget.AdapterView.performItemClick(AdapterView.java:284)
03-06 21:12:29.370: E/AndroidRuntime(7132): at android.widget.ListView.performItemClick(ListView.java:3285)
03-06 21:12:29.370: E/AndroidRuntime(7132): at android.widget.AbsListView$PerformClick.run(AbsListView.java:1640)
03-06 21:12:29.370: E/AndroidRuntime(7132): at android.os.Handler.handleCallback(Handler.java:587)
03-06 21:12:29.370: E/AndroidRuntime(7132): at android.os.Handler.dispatchMessage(Handler.java:92)
03-06 21:12:29.370: E/AndroidRuntime(7132): at android.os.Looper.loop(Looper.java:123)
03-06 21:12:29.370: E/AndroidRuntime(7132): at android.app.ActivityThread.main(ActivityThread.java:4363)
03-06 21:12:29.370: E/AndroidRuntime(7132): at java.lang.reflect.Method.invokeNative(Native Method)
03-06 21:12:29.370: E/AndroidRuntime(7132): at java.lang.reflect.Method.invoke(Method.java:521)
03-06 21:12:29.370: E/AndroidRuntime(7132): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
03-06 21:12:29.370: E/AndroidRuntime(7132): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
03-06 21:12:29.370: E/AndroidRuntime(7132): at dalvik.system.NativeStart.main(Native Method)
03-06 21:12:29.380: I/dalvikvm(7132): threadid=7: reacting to signal 3
03-06 21:12:29.380: E/dalvikvm(7132): Unable to open stack trace file '/data/anr/traces.txt': Permission denied
从logcat看起来问题出现在我的onlistitemclick中。虽然我不知道为什么它会工作一段时间然后没有。下面是我用于其中一个列表视图的代码。
public class title extends ListActivity {
private PopupWindow pw;
public static int titleClick;
private dbadapter mydbhelper;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.category_list);
mydbhelper = new dbadapter(this);
mydbhelper.open();
fillData();
}
private void fillData() {
Cursor t = mydbhelper.getTitles();
startManagingCursor(t);
// Create an array to specify the fields we want to display in the list (TITLE,DATE,NUMBER)
String[] from = new String[] {dbadapter.KEY_TITLEDESC};
// an array of the views that we want to bind those fields to (in this case text1,text2,text3)
int[] to = new int[] {R.id.text1};
// Now create a simple cursor adapter and set it to display
SimpleCursorAdapter adapter =
new SimpleCursorAdapter(this, R.layout.cate_row, t, from, to);
setListAdapter(adapter);
}
@Override
protected void onListItemClick(ListView list, View v, int position, long id)
{
super.onListItemClick(list, v, position, id);
titleClick = (int) list.getPositionForView(v);
final Intent intent = new Intent(this, inputpage.class);
final MediaPlayer titleClickSound = MediaPlayer.create(this, R.raw.button50);
titleClickSound.start();
startActivityForResult(intent, position);
}
@Override
protected void onResume() {
if (mydbhelper != null) {
mydbhelper.open();};
super.onResume();
}
@Override
protected void onPause() {
mydbhelper.close();
super.onPause();
}
//Menu Items
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.layout.menu, menu);
return true;
}
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()) {
case R.id.help:
showHelp();
return true;
}
return false;
}
private void showHelp() {
LayoutInflater inflater = (LayoutInflater)
this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
pw = new PopupWindow(
inflater.inflate(R.layout.help, null, false),
LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT,
true);
pw.showAtLocation(this.findViewById(R.id.text1), Gravity.CENTER, 0, 0);
}
public void onClickHelp(View helper){pw.dismiss();
}
}
这次尝试再次导致崩溃,它给了我一个不同的错误
03-06 21:52:40.250: E/Database(15818): Leak found
03-06 21:52:40.250: E/Database(15818): java.lang.IllegalStateException: /data/data/wanted.pro.madlibs/databases/madlib SQLiteDatabase created and never closed
03-06 21:52:40.250: E/Database(15818): at android.database.sqlite.SQLiteDatabase.<init>(SQLiteDatabase.java:1695)
03-06 21:52:40.250: E/Database(15818): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:739)
03-06 21:52:40.250: E/Database(15818): at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:761)
03-06 21:52:40.250: E/Database(15818): at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:754)
03-06 21:52:40.250: E/Database(15818): at android.app.ApplicationContext.openOrCreateDatabase(ApplicationContext.java:473)
03-06 21:52:40.250: E/Database(15818): at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:193)
03-06 21:52:40.250: E/Database(15818): at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:98)
03-06 21:52:40.250: E/Database(15818): at wanted.pro.madlibs.dbadapter.open(dbadapter.java:176)
03-06 21:52:40.250: E/Database(15818): at wanted.pro.madlibs.title.onCreate(title.java:29)
03-06 21:52:40.250: E/Database(15818): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
03-06 21:52:40.250: E/Database(15818): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2459)
03-06 21:52:40.250: E/Database(15818): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2512)
03-06 21:52:40.250: E/Database(15818): at android.app.ActivityThread.access$2200(ActivityThread.java:119)
03-06 21:52:40.250: E/Database(15818): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1863)
03-06 21:52:40.250: E/Database(15818): at android.os.Handler.dispatchMessage(Handler.java:99)
03-06 21:52:40.250: E/Database(15818): at android.os.Looper.loop(Looper.java:123)
03-06 21:52:40.250: E/Database(15818): at android.app.ActivityThread.main(ActivityThread.java:4363)
03-06 21:52:40.250: E/Database(15818): at java.lang.reflect.Method.invokeNative(Native Method)
03-06 21:52:40.250: E/Database(15818): at java.lang.reflect.Method.invoke(Method.java:521)
03-06 21:52:40.250: E/Database(15818): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
03-06 21:52:40.250: E/Database(15818): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
03-06 21:52:40.250: E/Database(15818): at dalvik.system.NativeStart.main(Native Method)
我一直试图阻止这种泄漏。以为我有它,但猜不是。想知道泄漏是否可能导致问题,因为onclick中的int用于dbhelperclass底部的游标
public class dbadapter extends SQLiteOpenHelper {
//The Android's default system path of your application database.
public static final String DB_PATH = "/data/data/wanted.pro.madlibs/databases/";
public static final String DB_NAME = "madlib";
public static final int DB_VERSION = 39;
//database variables
public static final String KEY_ID = "_id";
public static final String KEY_CATEGORYDESC = "categorydesc";
public static final String KEY_TITLE = "titlekey";
public static final String KEY_TITLEDESC = "titledesc";
public static final String KEY_TITLESTORY = "titlestory";
public static final String KEY_SOURCEDESC = "sourcedesc";
public static final String KEY_SOURCE = "sourcekey";
public static final String KEY_CATEGORY = "categorykey";
public static final String KEY_USERWORD = "userword";
public static final String KEY_EDITWORD = "editword";
public static final String KEY_QUICK = "quick";
//table variables
public static final String CATEGORY_TABLE = "category";
public static final String SOURCE_TABLE = "source";
public static final String TITLE_TABLE = "title";
public static final String SOURCE_CATEGORY_TABLE = "source_category";
public static final String SOURCE_TITLE_TABLE = "source_title";
public static final String CATEGORY_TITLE_TABLE = "category_title";
public static final String USER_WORD_TABLE = "userword";
private dbadapter mydbhelper;
public static SQLiteDatabase myDataBase;
/**
* Constructor
* Takes and keeps a reference of the passed context in order to access to the application assets and resources.
* @param context
*/
private final Context mCtx;
public dbadapter(Context context) {
super(context, DB_NAME, null, DB_VERSION);
this.mCtx = context;
}
/**
* Creates a empty database on the system and rewrites it with your own database.
* */
public void createDataBase() throws IOException{
boolean dbExist = checkDataBase();
if(dbExist){
Log.v("DB Exists", "db exists");
this.getWritableDatabase();
//do nothing - database already exist
}
dbExist=checkDataBase();
if(!dbExist){
//By calling this method and empty database will be created into the default system path
//of your application so we are gonna be able to overwrite that database with our database.
this.getReadableDatabase();
try {
copyDataBase();
} catch (IOException e) {
throw new Error("Error copying database");
}
}
}
/**
* Check if the database already exist to avoid re-copying the file each time you open the application.
* @return true if it exists, false if it doesn't
*/
private boolean checkDataBase(){
SQLiteDatabase checkDB = null;
try{
String myPath = DB_PATH + DB_NAME;
checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
}catch(SQLiteException e){
//database does't exist yet.
}
if(checkDB != null){
checkDB.close();
}
return checkDB != null ? true : false;
}
/**
* Copies your database from your local assets-folder to the just created empty database in the
* system folder, from where it can be accessed and handled.
* This is done by transferring bytestream.
* */
private void copyDataBase() throws IOException{
//Open your local db as the input stream
InputStream myInput = mCtx.getAssets().open(DB_NAME);
// Path to the just created empty db
String outFileName = DB_PATH + DB_NAME;
//Open the empty db as the output stream
OutputStream myOutput = new FileOutputStream(outFileName);
//transfer bytes from the inputfile to the outputfile
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer))>0){
myOutput.write(buffer, 0, length);
}
//Close the streams
myOutput.flush();
myOutput.close();
myInput.close();
}
public void openDataBase() throws SQLException{
//Open the database
String myPath = DB_PATH + DB_NAME;
this.getWritableDatabase();
myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);
}
@Override
public synchronized void close() {
if(myDataBase != null)
myDataBase.close();
super.close();
}
@Override
public void onCreate(SQLiteDatabase db) {
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (newVersion > oldVersion)
mCtx.deleteDatabase(DB_NAME);
}
public dbadapter open() throws SQLException {
mydbhelper = new dbadapter (mCtx);
myDataBase = mydbhelper.getWritableDatabase();
return this;
}
// retrieves all the categories
public Cursor getAllCategories()
{
return myDataBase.query(CATEGORY_TABLE, new String[] {
KEY_ID, KEY_CATEGORY,
KEY_CATEGORYDESC,
},
null, null, null, null, KEY_CATEGORYDESC);
}
// retrieves all the titles
public Cursor getTitles()
{
return myDataBase.query(TITLE_TABLE, new String[] {
KEY_ID,
KEY_TITLE,
KEY_TITLEDESC,
KEY_TITLESTORY, KEY_CATEGORY, KEY_SOURCE,
},
KEY_CATEGORY+ "=" + categories.categoryClick + " AND " + KEY_SOURCE+ "=" +source.sourceClick, null, null, null, KEY_TITLEDESC);
}
// retrieves all the descriptions for the edittext fields
public Cursor getUserWord()
{
return myDataBase.query(USER_WORD_TABLE, new String[] {
KEY_ID,
KEY_CATEGORY,
KEY_SOURCE, KEY_TITLE, KEY_USERWORD, KEY_QUICK
},
KEY_CATEGORY+ "=" + categories.categoryClick + " AND " + KEY_SOURCE+ "="
+source.sourceClick + " AND " + KEY_TITLE+ "=" + title.titleClick,
null, null, null, KEY_ID);
}
// Quick Start
public Cursor getQuickStory()
{
return myDataBase.query(TITLE_TABLE, new String[] {
KEY_ID,
KEY_TITLE,
KEY_TITLEDESC,
KEY_TITLESTORY, KEY_CATEGORY, KEY_SOURCE,
},
KEY_ID+ "=" + main.RandomNum, null, null, null, null);
}
public Cursor getQuickWord()
{
return myDataBase.query(USER_WORD_TABLE, new String[] {
KEY_ID,
KEY_CATEGORY,
KEY_SOURCE, KEY_TITLE, KEY_USERWORD, KEY_QUICK
},
KEY_QUICK+ "=" + main.RandomNum,
null, null, null, KEY_ID);
}
public Cursor getSource()
{
return myDataBase.query(SOURCE_TABLE, new String[]{
KEY_ID, KEY_SOURCEDESC, KEY_CATEGORY,},
KEY_CATEGORY+ "=" + categories.categoryClick, null, null, null, KEY_SOURCEDESC);
}
// retrieves story to diplay in last activity
public Cursor getStory()
{
return myDataBase.query(TITLE_TABLE, new String[] {
KEY_ID,
KEY_TITLE,
KEY_TITLEDESC,
KEY_TITLESTORY, KEY_CATEGORY, KEY_SOURCE,
},
KEY_CATEGORY+ "=" + categories.categoryClick + " AND " + KEY_SOURCE+ "=" +source.sourceClick + " AND " + KEY_TITLE+ "=" + title.titleClick, null, null, null, null);
}
}
答案 0 :(得分:0)
我不确定这是否是您的异常的原因,但以下看起来可能会导致您遇到一些问题。你定义:
public static int titleClick;
然后在onListItemClick
致电:
titleClick = (int) list.getPositionForView(v);
我假设正在从应用程序中的其他活动访问此公共静态变量。由于Android管理您的Activity
的方式(请参阅流程图here),如果您的应用程序的进程已被终止然后重新启动,则此静态变量可能会变为空/未定义。如果在调用 onListItemClick
之前访问,它也将为null。
此外,您应该可以使用position
中的onListItemClick
参数代替:(int) list.getPositionForView(v)