AsyncTask +数据库尝试在空对象引用上调用虚拟方法[重复]

Posted

技术标签:

【中文标题】AsyncTask +数据库尝试在空对象引用上调用虚拟方法[重复]【英文标题】:AsyncTask + database attempt to invoke virtual method on a null object reference [duplicate] 【发布时间】: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 中执行其他操作 啊,我明白了。谢谢。 【参考方案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 都是可行的选择,具体取决于您的硬件可用性。

【讨论】:

以上是关于AsyncTask +数据库尝试在空对象引用上调用虚拟方法[重复]的主要内容,如果未能解决你的问题,请参考以下文章

ListView 未在 AsyncTask 中初始化

无法在 asyncTask 中的 onPostExecute 中发送消息

java.lang.NullPointerException:尝试在 OnPostExecute() 上的空对象引用错误上调用接口方法 - AsyncTask

带有 REST API 的 AsyncTask

数据库错误:尝试在空对象引用上调用虚拟方法“Cursor .getScene()”[重复]

数据库错误:“NullPointerException:尝试在空对象引用上调用虚拟方法 getApplicationInfo()...”[重复]