【问题标题】:AsyncTask + database attempt to invoke virtual method on a null object reference [duplicate]AsyncTask +数据库尝试在空对象引用上调用虚拟方法[重复]
【发布时间】:2017-04-19 06:53:36
【问题描述】:

所以我得到了这个令人讨厌的 nullPointerException 并且是 Android 新手,我只是不知道为什么。

代码如下:

public class GetCoffeeBrandsAndSaveToDB extends Activity implements AsyncResponse {

private Gson gson = new Gson();
DatabaseHandler dbh;
Context context;

public GetCoffeeBrandsAndSaveToDB(Context context) {
    this.context = context;
}

@Override
protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
     dbh = new DatabaseHandler(getApplicationContext());
}

public void getAllCoffeeBrands(){
    GetAllBrands g = new GetAllBrands("http://192.168.2.105:3000/api/", this);
g.execute();
}

@Override
public void processFinished(String output) {
    Log.d("this is output: ", "her kommer output fra GetCBandSaveToDB: " + output);



    CoffeeBrand[] cBrand = gson.fromJson(output, CoffeeBrand[].class);

    for (CoffeeBrand eachBrand : cBrand) {
        CoffeeBrand cBrandForDB = new CoffeeBrand(eachBrand.getDatabaseId(), eachBrand.getBrandName(), eachBrand.getCoffeesNeeded());
        Log.d("her er cBrandForDB", " : " + cBrandForDB.getBrandName() + " and the number: " + cBrandForDB.getCoffeesNeeded());
        dbh.addCoffeeBrand(cBrandForDB);

    }

    List<CoffeeBrand> brands = dbh.getAllCoffeeBrands();

    for (CoffeeBrand cb : brands) {
        String log = "Id: "+cb.getDatabaseId()+" ,Name: " + cb.getBrandName() + " ,coffeesNeeded: " + cb.getCoffeesNeeded();
        // Writing CoffeeBrands to log
        Log.d("Name: ", log);
    }

}

}

问题出现在 dbh.addCoffeeBrand(cBrandForDB); 我的日志在 cBrandForDB 上工作,所以我知道它不为空,所以我猜测 dbh 是问题所在?

我的数据库处理程序构造函数如下所示:

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

完整的日志:

12-05 00:16:15.920 5025-5075/kasper.pagh.keebin D/full url:: http://192.168.2.105:3000/api/coffee/allbrands/
12-05 00:16:15.985 5025-5079/kasper.pagh.keebin D/full url:: http://192.168.2.105:3000/api/users/allcards
12-05 00:16:15.993 5025-5080/kasper.pagh.keebin D/OpenGLRenderer: Use EGL_SWAP_BEHAVIOR_PRESERVED: true

[ 12-05 00:16:16.001  5025: 5025 D/         ]
HostConnection::get() New Host Connection established 0xaaaf1580, tid 5025
12-05 00:16:16.017 5025-5025/kasper.pagh.keebin D/this is output:: her kommer output fra GetCBandSaveToDB: [{"id":1,"brandName":"Baresso","numberOfCoffeeNeeded":10},{"id":2,"brandName":"Riccos","numberOfCoffeeNeeded":10}]
12-05 00:16:16.043 5025-5025/kasper.pagh.keebin D/her er cBrandForDB:  : Baresso and the number: 0
12-05 00:16:16.044 5025-5025/kasper.pagh.keebin D/AndroidRuntime: Shutting down VM


--------- beginning of crash
12-05 00:16:16.046 5025-5025/kasper.pagh.keebin E/AndroidRuntime: FATAL EXCEPTION: main
Process: kasper.pagh.keebin, PID: 5025
java.lang.NullPointerException: Attempt to invoke virtual method 'void kasper.pagh.keebin.DatabaseHandler.addCoffeeBrand(entity.CoffeeBrand)' on a null object reference
    at kasper.pagh.keebin.GetCoffeeBrandsAndSaveToDB.processFinished(GetCoffeeBrandsAndSaveToDB.java:53)
    at CoffeeRest.rest.GetAllBrands.onPostExecute(GetAllBrands.java:89)
    at CoffeeRest.rest.GetAllBrands.onPostExecute(GetAllBrands.java:19)
    at android.os.AsyncTask.finish(AsyncTask.java:651)
    at android.os.AsyncTask.-wrap1(AsyncTask.java)
    at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:668)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:148)
    at android.app.ActivityThread.main(ActivityThread.java:5417)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

获取所有品牌:

public class GetAllBrands extends AsyncTask<String, Void, String>
{
public AsyncResponse delegate = null;
private String baseUrl;

public GetAllBrands(String baseUrl, AsyncResponse delegate)
{
    this.baseUrl = baseUrl;
    this.delegate = delegate;
}


private String getBrands() throws IOException
{
    InputStream input = null;
    BufferedReader bufferedReader = null;
    StringBuilder sb = null;

    try
    {
        URL url = new URL(baseUrl + "coffee/allbrands/");
        Log.d("full url: ", url.toString());
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("GET");
        connection.setReadTimeout(10000);
        connection.setConnectTimeout(15000);
        connection.setDoInput(true);
        connection.setRequestProperty("Accept", "application/json");
        connection.setRequestProperty("refreshToken", "xxxxxxxx"); //edited out
        connection.setRequestProperty("accessToken", "xxxxxxxxxxxx"); //edited out


        connection.connect();

        input = connection.getInputStream();
        bufferedReader = new BufferedReader(new InputStreamReader(input));
        sb = new StringBuilder();
        String line;
        while ((line = bufferedReader.readLine()) != null)
        {
            sb.append(line + "\n");
        }
        bufferedReader.close();
        return sb.toString();
    } finally
    {
        if (input != null)
        {
            input.close();
        }
    }
}

@Override
protected String doInBackground(String... params)
{
    try
    {
        return getBrands();
    } catch (IOException e)
    {

        e.printStackTrace();
        return null;
    }
}

@Override
protected void onPostExecute(String result)
{
    delegate.processFinished(result);
}

}

【问题讨论】:

  • 你去 :)
  • 请也显示GetAllBrands的全班
  • 嗯嗯嗯。但是我不明白为什么 cBrandForDB 不为空,所以输出也不为空(意味着 GetAllBrands 按预期工作)
  • 这不为空。我只是想确保您没有在 AsyncTask 中执行其他操作
  • 啊,我明白了。谢谢。

标签: java android sqlite nullpointerexception


【解决方案1】:

根据我看到的,这个类不需要扩展Activity。您似乎应该创建一个new GetCoffeeBrandsAndSaveToDB(context)(这是一个非常冗长的名称,但无论如何)。当你这样做时,onCreate 不会被调用,因此dbh 对象为空。

因此,我建议这样做。

public class GetCoffeeBrandsAndSaveToDB implements AsyncResponse {

    private Gson gson = new Gson();
    DatabaseHandler dbh;
    Context context;

    public GetCoffeeBrandsAndSaveToDB(Context context) {
        this.context = context;
        dbh = new DatabaseHandler(context);
    }

    public void getAllCoffeeBrands(){
        GetAllBrands g = new GetAllBrands("http://192.168.2.105:3000/api/", this);
        g.execute();
    }

在相关新闻中,您应该查看 HTTP API 调用的 Retrofit。甚至可能是允许轻松同步的替代数据库解决方案。我相信 Realm 正在开发同步服务器,但 Couchbase Lite 或 Parse Server 都是可行的选择,具体取决于您的硬件可用性。

【讨论】:

    猜你喜欢
    • 2023-03-25
    • 1970-01-01
    • 2023-03-13
    • 1970-01-01
    • 2016-07-30
    • 2015-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多