Android 如何从其他线程或意图服务调用getWritableDatabase(),应用程序在主线程中调用时崩溃

Android 如何从其他线程或意图服务调用getWritableDatabase(),应用程序在主线程中调用时崩溃,android,multithreading,sqlite,android-intent,intentservice,Android,Multithreading,Sqlite,Android Intent,Intentservice,这是主要的活动 import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.EditText; import android.widget.TextView; public class MainActivity extends AppCompatActivity { EditText myinpu

这是主要的活动

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;



public class MainActivity extends AppCompatActivity {

    EditText myinput;
    TextView mytext;
    MyDBHandler dbhandler;




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




        myinput =(EditText) findViewById(R.id.myinput);
        mytext =(TextView) findViewById(R.id.mytext);
        dbhandler= new MyDBHandler(this, null, null, 1);
        printDatabase();


    }

    //add product to database

    public void addstuff(View view)
    {
        products product = new products(myinput.getText().toString());
        dbhandler.addProduct(product);
        printDatabase();

    }

    //delete items from database

    public void deletestuff(View view)
    {
        String inputtext= myinput.getText().toString();
        dbhandler.deleteProduct(inputtext);
        printDatabase();


    }

    public void printDatabase()
    {
        String dbString= dbhandler.databaseToString();
        mytext.setText(dbString);
        myinput.setText("");
    }

}
产品类,用于获取和设置产品

public class products {

    private int _id;
    private String _productname;

    public products()
    {

    }

    public products(String productname) {
        this._productname = productname;
    }

    public void set_id(int _id) {
        this._id = _id;
    }

    public void set_productname(String _productname) {
        this._productname = _productname;
    }

    public int get_id() {
        return _id;
    }

    public String get_productname() {
        return _productname;
    }
}
数据库处理程序类

import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.Cursor;
import android.content.Context;
import android.content.ContentValues;


public class MyDBHandler extends SQLiteOpenHelper{

    private static final int DATABASE_VERSION = 1;
    private static final String DATABASE_NAME = "products.db";
    public static final String TABLE_PRODUCTS = "products";
    public static final String COLUMN_ID ="_id";
    public static final String COLUMN_PRODUCTNAME ="productname";


    public MyDBHandler(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, DATABASE_NAME, factory, DATABASE_VERSION);
    }


    @Override
    public void onCreate(SQLiteDatabase db) {

        String query= "CREATE TABLE " + TABLE_PRODUCTS + "(" +
                COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT , " +
                COLUMN_PRODUCTNAME + " TEXT " +
                ");";
        db.execSQL(query);

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS "+TABLE_PRODUCTS);
        onCreate(db);
    }

    //add a new row to the database
    public void addProduct(products product)
    {
        ContentValues values = new ContentValues();
        values.put(COLUMN_PRODUCTNAME, product.get_productname());
        SQLiteDatabase db= getWritableDatabase();
        db.insert(TABLE_PRODUCTS, null, values);
        db.close();
    }

    //delete product from the database
    public void deleteProduct(String productname)
    {
        SQLiteDatabase db= getWritableDatabase();
        db.execSQL("DELETE FROM "+ TABLE_PRODUCTS + " WHERE " + COLUMN_PRODUCTNAME + " =\"" + productname + "\";" );
    }

    //printing out the database as a string

    public String databaseToString()
    {
        String dbString ="";
        SQLiteDatabase db= getWritableDatabase();
        String query = "SELECT * FROM "+ TABLE_PRODUCTS + " WHERE 1";

        //CURSOR POINTS TO A LOCATION IN THE DATABASE RESULTS
        Cursor c= db.rawQuery(query,null);
        //go to 1st row in your results
        c.moveToFirst();

        while(!c.isAfterLast())
        {
            if(c.getString(c.getColumnIndex("productname"))!=null)
            {
                dbString += c.getString(c.getColumnIndex("productname"));
                dbString += "\n";

            }

        }
        db.close();
        return dbString;

    }



}
我尝试将getWriteableDatabase()代码放在runnables中,但databasetostring()方法无法做到这一点

如何从意图服务调用getWritableDatabase()

我想使用此intent服务获取WritableDatabase()

我不知道如何通过意向服务做到这一点

这是应用程序启动后的日志

8-19 17:56:08.848  15523-15523/? I/art﹕ Late-enabling -Xcheck:jni
08-19 17:56:08.848  15523-15523/? I/art﹕ VMHOOK: rlim_cur : 0 pid:15523
08-19 17:56:09.218  15523-15523/com.example.vashisht.sqliteapp D/Atlas﹕ Validating map...
08-19 17:56:09.278  15523-15554/com.example.vashisht.sqliteapp I/Adreno-EGL﹕ <qeglDrvAPI_eglInitialize:410>: EGL 1.4 QUALCOMM build: TEST SBA LA.BF.1.1.1_RB1 AU_LINUX_ANDROID_LA.BF.1.1.1_RB1.05.00.02.042.012 + c1105519 + c_apilogging ()
    OpenGL ES Shader Compiler Version: E031.25.03.00
    Build Date: 01/23/15 Fri
    Local Branch:
    Remote Branch: refs/tags/AU_LINUX_ANDROID_LA.BF.1.1.1_RB1.05.00.02.042.012
    Local Patches: NONE
    Reconstruct Branch: NOTHING
08-19 17:56:09.478  15523-15523/com.example.vashisht.sqliteapp I/InputMethodManager﹕ [startInputInner] EditorInfo { packageName=com.example.vashisht.sqliteapp, inputType=0x20001, imeOptions=0x40000006, privateImeOptions=null }, windowGainingFocus=android.view.ViewRootImpl$W@1287b4e7, mServedView=android.support.v7.widget.AppCompatEditText{e909894 VFED..CL .F....I. 90,222-990,335 #7f0c004f app:id/myinput}, mServedInputConnectionWrapper=android.view.inputmethod.InputMethodManager$ControlledInputConnectionWrapper@18863f3d
然后我需要手动关闭应用程序,或者在一段时间后它说没有响应

我修改了databasetostring()方法以返回字符串数组,这样我就可以在listview中显示结果

 public String[] databaseToString()
    {


        String[] dbString;
        dbString = new String[]{};

        SQLiteDatabase db= getReadableDatabase();
        String query = "SELECT * FROM "+ TABLE_PRODUCTS + " WHERE 1";

        //CURSOR POINTS TO A LOCATION IN THE DATABASE RESULTS
        Cursor c= db.rawQuery(query,null);
        //go to 1st row in your results
        c.moveToFirst();
        int i=0;
        while(!c.isAfterLast())
        {
            if(c.getString(c.getColumnIndex(COLUMN_PRODUCTNAME))!=null)
                dbString[i] = c.getString(c.getColumnIndex(COLUMN_PRODUCTNAME));

            i++;

        }
        db.close();

        return dbString;


    }

但是在这里,
dbString[i]=c.getString(c.getColumnIndex(COLUMN\u PRODUCTNAME))是否引发数组越界异常

要从
IntentService
调用它,只需调用此

sqLiteDatabase = getApplicationContext().getWritableDatabase();
您需要
getApplicationContext()
因为
IntentService
扩展了
Context

import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.Cursor;
import android.content.Context;
import android.content.ContentValues;


public class MyDBHandler extends SQLiteOpenHelper{

    private static final int DATABASE_VERSION = 1;
    private static final String DATABASE_NAME = "products.db";
    public static final String TABLE_PRODUCTS = "products";
    public static final String COLUMN_ID ="_id";
    public static final String COLUMN_PRODUCTNAME ="productname";


    public MyDBHandler(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, DATABASE_NAME, factory, DATABASE_VERSION);
    }


    @Override
    public void onCreate(SQLiteDatabase db) {


        String query= "CREATE TABLE " + TABLE_PRODUCTS + "(" +
                COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT , " +
                COLUMN_PRODUCTNAME + " TEXT " +
                ");";
        db.execSQL(query);


    }



    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_PRODUCTS);
        onCreate(db);
    }

    //add a new row to the database
    public void addProduct(products product)
    {
        final ContentValues values = new ContentValues();
        values.put(COLUMN_PRODUCTNAME, product.get_productname());

        SQLiteDatabase db= getWritableDatabase();
                db.insert(TABLE_PRODUCTS, null, values);
                db.close();





    }

    //delete product from the database
    public void deleteProduct(final String productname)
    {



                SQLiteDatabase db = getWritableDatabase();
        db.execSQL("DELETE FROM " + TABLE_PRODUCTS + " WHERE " + COLUMN_PRODUCTNAME + " =\"" + productname + "\";");





    }

    //printing out the database as a string

    public String databaseToString()
    {
        String dbString ="";
        SQLiteDatabase db= getWritableDatabase();
        String query = "SELECT * FROM "+ TABLE_PRODUCTS + " WHERE 1";

        //CURSOR POINTS TO A LOCATION IN THE DATABASE RESULTS
        Cursor c= db.rawQuery(query,null);
        //go to 1st row in your results
        c.moveToFirst();

        while(!c.isAfterLast())
        {
            if(c.getString(c.getColumnIndex("productname"))!=null)
            {
                dbString += c.getString(c.getColumnIndex("productname"));
                dbString += "\n";

            }
            c.moveToNext();
问题就在这里,我忘记将光标移动到下一个结果,这导致了一个无限while循环!哎呀

        }
        db.close();
        return dbString;

    }



}

logcat上有什么?
sqLiteDatabase=getApplicationContext().getWritableDatabase()?@pskink I'v添加了日志猫,请检查。我没有看到任何崩溃,请将代码张贴在您使用日志的位置MyDBHandler@pskink我正在mainactivity中使用MyDBHandler!代码在那里..我应该导入什么包来获取getApplicationContext()方法?我还没有在intent服务类中编写任何代码,我想调用getWritableDatabase()在后台。我如何从IntentService调用它,然后在我的数据库处理程序类中使用它。@iaaphpd13当您调用
MyDBHandler#getWritableDatabase()
?@pskink I'v发布的日志猫,当启动程序活动开始时,当我输入文本并单击界面上的“添加”按钮时(当调用getWritableDatabase()并执行插入查询时),在创建mainactivity时也会调用getWritableDatabase(),但此时应用程序运行良好。只要将任何答案标记为正确的@iaaphpd13,社区就必须知道此问题的答案正确
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.Cursor;
import android.content.Context;
import android.content.ContentValues;


public class MyDBHandler extends SQLiteOpenHelper{

    private static final int DATABASE_VERSION = 1;
    private static final String DATABASE_NAME = "products.db";
    public static final String TABLE_PRODUCTS = "products";
    public static final String COLUMN_ID ="_id";
    public static final String COLUMN_PRODUCTNAME ="productname";


    public MyDBHandler(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, DATABASE_NAME, factory, DATABASE_VERSION);
    }


    @Override
    public void onCreate(SQLiteDatabase db) {


        String query= "CREATE TABLE " + TABLE_PRODUCTS + "(" +
                COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT , " +
                COLUMN_PRODUCTNAME + " TEXT " +
                ");";
        db.execSQL(query);


    }



    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_PRODUCTS);
        onCreate(db);
    }

    //add a new row to the database
    public void addProduct(products product)
    {
        final ContentValues values = new ContentValues();
        values.put(COLUMN_PRODUCTNAME, product.get_productname());

        SQLiteDatabase db= getWritableDatabase();
                db.insert(TABLE_PRODUCTS, null, values);
                db.close();





    }

    //delete product from the database
    public void deleteProduct(final String productname)
    {



                SQLiteDatabase db = getWritableDatabase();
        db.execSQL("DELETE FROM " + TABLE_PRODUCTS + " WHERE " + COLUMN_PRODUCTNAME + " =\"" + productname + "\";");





    }

    //printing out the database as a string

    public String databaseToString()
    {
        String dbString ="";
        SQLiteDatabase db= getWritableDatabase();
        String query = "SELECT * FROM "+ TABLE_PRODUCTS + " WHERE 1";

        //CURSOR POINTS TO A LOCATION IN THE DATABASE RESULTS
        Cursor c= db.rawQuery(query,null);
        //go to 1st row in your results
        c.moveToFirst();

        while(!c.isAfterLast())
        {
            if(c.getString(c.getColumnIndex("productname"))!=null)
            {
                dbString += c.getString(c.getColumnIndex("productname"));
                dbString += "\n";

            }
            c.moveToNext();
        }
        db.close();
        return dbString;

    }



}