0

我在使用 Eclipse 进行 android 应用程序的数据库连接时遇到了可怕的问题

我有一个这样的工作示例,但由于我已经对其进行了调整,因此我无法打开数据库连接。

我有一个在异步任务中打开“getData”的主要活动

这会下载一个 JOSN 格式的文档,解析并传递给“writeSync”类

该类旨在打开数据库连接添加记录然后关闭连接。

运行 database.open 方法时收到错误消息,但无法捕获特定错误。

我检查了我没有传递 Null 值并且填充了 Helper 对象。

如果有人能发现我的问题,这是我的代码。

我还编写了一个包装类来在数据库打开时传递上下文

主要活动

package com.example.jsondb;

import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.view.Menu;

public class MainActivity extends Activity {
public Context context;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    getContext contextrequest = new getContext();

    AsyncTask<String, Void, String> JSONData;
    //Get JSON Data as a string
    //Update display#
    //SyncDataProducts();
    JSONData = new GetData().execute("null");

    String WriteDB = "";
    //pass JSONData to database to be written
    //update display

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

}

获取数据

package com.example.jsondb;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;

import android.os.AsyncTask;
import android.util.Log;

public class GetData extends AsyncTask<String, Void, String> {


public String getServerData(String strURL) {    
    InputStream is = null;

    ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
    nameValuePairs.add(new BasicNameValuePair("code","A"));

    //get http data
    try{
        HttpClient httpclient = new DefaultHttpClient();
        HttpPost httppost = new HttpPost(strURL);
        httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
        HttpResponse response = httpclient.execute(httppost);
        HttpEntity entity = response.getEntity();
        is = entity.getContent();

}catch(Exception e){
        Log.e("log_tag", "Error in http connection "+e.toString());
}


    //convert response to string
    String result = "";
    try{
            BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8);
            StringBuilder sb = new StringBuilder();
            String line = null;
            while ((line = reader.readLine()) != null) {
                    sb.append(line + "\n");
            }
            is.close();

            result=sb.toString();

            //send data to database
            AsyncTask<String, Void, String> WriteData;
            WriteData = new WriteSync().execute(result);

            return result;

    }catch(Exception e){
            Log.e("log_tag", "Error converting result "+e.toString());
    }




    return result;





}

@Override
protected String doInBackground(String... arg0) {
    // TODO Auto-generated method stub
    return getServerData("http://500kgiveaway.co.uk/android/products.php");
}
} 

写同步

package com.example.jsondb;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;

public class WriteSync extends AsyncTask<String, Void, String> {
private Context adapterContext;
public String WriteSyncData(String result) {
String httpResponce = "";
String returnstring = "";
httpResponce = result;


adapterContext = getContext.getContextNow();

DataSource datasource;
datasource = new DataSource(adapterContext);

datasource.open();


try{
        JSONArray jArray = new JSONArray(httpResponce);
        for(int i=0;i<jArray.length();i++){
                JSONObject json_data = jArray.getJSONObject(i);

                datasource.createProduct(json_data.getString("stockref"), json_data.getString("title"), json_data.getString("price"));

                //Get an output to the screen
                returnstring += "\n\t" + jArray.getJSONObject(i); 
        }
}catch(JSONException e){
        Log.e("log_tag", "Error parsing data "+e.toString());
}


return returnstring;


}

@Override
protected String doInBackground(String... params) {
    // TODO Auto-generated method stub

    return WriteSyncData(params[0]);
}
}

mysql助手

package com.example.jsondb;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

public class MySQLiteHelper extends SQLiteOpenHelper{
  //Product Table
  public static final String TABLE_NAME = "products";
  public static final String COLUMN_ID = "_id";
  public static final String COLUMN_STOCKREF = "stockref";
  public static final String COLUMN_TITLE = "title";
  public static final String COLUMN_PRICE = "price";

  private static final String DATABASE_NAME = "Logma.db";
  private static final int DATABASE_VERSION = 2;

  // Database creation sql statement

  private static final String DATABASE_CREATE = "create table "
          + TABLE_NAME 
          + "(" + COLUMN_ID  + " integer primary key autoincrement," 
          + COLUMN_STOCKREF + " text not null,"
          + COLUMN_TITLE + " text not null,"
          + COLUMN_PRICE + " text not null"
          + ");";


  public MySQLiteHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
      }

      @Override
      public void onCreate(SQLiteDatabase database) {
        database.execSQL(DATABASE_CREATE);
      }

      @Override
      public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)     {
        Log.w(MySQLiteHelper.class.getName(),
            "Upgrading database from version " + oldVersion + " to "
                + newVersion + ", which will destroy all old data");
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
        onCreate(db);
      }

}

数据源

package com.example.jsondb;

import android.content.ContentValues;
import android.content.Context;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;

public class DataSource {
  private SQLiteDatabase database;
  private MySQLiteHelper dbHelper;
  private String[] allColumns_products = { MySQLiteHelper.COLUMN_ID,
            MySQLiteHelper.COLUMN_STOCKREF,MySQLiteHelper.COLUMN_TITLE,MySQLiteHelper.COLUMN_PRICE};

  public DataSource(Context context) {
       dbHelper = new MySQLiteHelper(context);
      }

  public void open() throws SQLException {
        database = dbHelper.getWritableDatabase();
      }

  public void close() {
        dbHelper.close();
      }

  public String createProduct(String strStockRef, String strTitle, String strPrice)   {
        ContentValues values = new ContentValues();
        values.put(MySQLiteHelper.COLUMN_STOCKREF, strStockRef);
        values.put(MySQLiteHelper.COLUMN_TITLE, strTitle);
        values.put(MySQLiteHelper.COLUMN_PRICE, strPrice);


        long insertId = database.insert(MySQLiteHelper.TABLE_NAME, null,
            values);

        return "Completed";
      }

}

获取上下文

package com.example.jsondb;

import android.content.Context;

public class getContext extends android.app.Application {

private static getContext instance;

public getContext() {
    instance = this;
}

 public static Context getContextNow() {
    return instance;
}

}

这是我的堆栈跟踪

05-01 15:21:22.948: E/AndroidRuntime(24214): FATAL EXCEPTION: AsyncTask #2
05-01 15:21:22.948: E/AndroidRuntime(24214): java.lang.RuntimeException: An error  occured while executing doInBackground()
05-01 15:21:22.948: E/AndroidRuntime(24214):    at android.os.AsyncTask$3.done(AsyncTask.java:299)
05-01 15:21:22.948: E/AndroidRuntime(24214):    at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:352)
05-01 15:21:22.948: E/AndroidRuntime(24214):    at java.util.concurrent.FutureTask.setException(FutureTask.java:219)
05-01 15:21:22.948: E/AndroidRuntime(24214):    at java.util.concurrent.FutureTask.run(FutureTask.java:239)
05-01 15:21:22.948: E/AndroidRuntime(24214):    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
05-01 15:21:22.948: E/AndroidRuntime(24214):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
05-01 15:21:22.948: E/AndroidRuntime(24214):    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
05-01 15:21:22.948: E/AndroidRuntime(24214):    at java.lang.Thread.run(Thread.java:856)
05-01 15:21:22.948: E/AndroidRuntime(24214): Caused by: java.lang.NullPointerException
05-01 15:21:22.948: E/AndroidRuntime(24214):    at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:236)
05-01 15:21:22.948: E/AndroidRuntime(24214):    at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:224)
05-01 15:21:22.948: E/AndroidRuntime(24214):    at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:164)
05-01 15:21:22.948: E/AndroidRuntime(24214):    at com.example.jsondb.DataSource.open(DataSource.java:19)
05-01 15:21:22.948: E/AndroidRuntime(24214):    at com.example.jsondb.WriteSync.WriteSyncData(WriteSync.java:24)
05-01 15:21:22.948: E/AndroidRuntime(24214):    at com.example.jsondb.WriteSync.doInBackground(WriteSync.java:51)
05-01 15:21:22.948: E/AndroidRuntime(24214):    at com.example.jsondb.WriteSync.doInBackground(WriteSync.java:1)
05-01 15:21:22.948: E/AndroidRuntime(24214):    at android.os.AsyncTask$2.call(AsyncTask.java:287)
05-01 15:21:22.948: E/AndroidRuntime(24214):    at java.util.concurrent.FutureTask.run(FutureTask.java:234)
05-01 15:21:22.948: E/AndroidRuntime(24214):    ... 4 more
4

2 回答 2

0

我查看了ContextWrapper(引发空指针异常的 Android 框架类)的源代码,看来Context您正在提供给您的SQLiteOpenHelperis null. 您要求的方式Context(使用您的“getContext”类 - 请以大写开头)对我来说似乎很尴尬。getContext()如果没有可用的方法,我通常将“this”指针传递给我的 Activity 。getReadableDatabase()在调用or之前你不会注意到这个错误getWritableDatabase(),因为在那SQLiteOpenHelper之前不会使用给定的Context

另外:目前您的代码跟踪还AsyncTask.execute()从后台线程调用 an (特别是,当您execute()WriteSync内部调用时GetData.doInBackground()。根据文档,这是不允许的。您应该始终AsyncTask.execute()从主线程调用。我从经验中知道,虽然调用来自另一个线程的 execute() 大部分时间都是正确的,它肯定不会一直正确。同样:这与您的问题无关(这只是您传递给您的空上下文SQLiteOpenHelper),但它是你在看的时候我会看看的东西。

于 2013-05-01T15:05:33.107 回答
0

您应该使用与您的异步任务相关的活动、BordcastReceiver 或服务的上下文。在您的情况下使用 MainActivity 上下文:

public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
   ...
   JSONData = new GetData(this.getContext()).execute("null");


public class GetData extends AsyncTask<String, Void, String> {
  Context context = null
  public GetData(Context context) {
    this.context=context;
于 2013-05-01T15:22:08.220 回答