如何使 AsyncTask“doInBackground()”等待一个数组列表

Posted

技术标签:

【中文标题】如何使 AsyncTask“doInBackground()”等待一个数组列表【英文标题】:How to make the AsyncTask "doInBackground()" wait for an arraylist 【发布时间】:2018-01-14 20:46:28 【问题描述】:

我想在我的 android 设备上的本地 SQL DB 中保存一些对象。 如果我尝试运行该应用程序,我会在 onPostExecute() 的单元格 ArrayList 上收到 null object reference 错误。

公共类 CellApiTask 扩展 AsyncTask> 私有上下文上下文;

public CellApiTask(Context context) 
    this.context = context;


@Override
protected ArrayList<Cell> doInBackground(Void... params) 
    Fragment_Battery_Cell_Voltage cellVoltageClass = new Fragment_Battery_Cell_Voltage();
    return cellVoltageClass.getCellsForDB();



@Override
protected void onPostExecute(ArrayList<Cell> cell) 
    CellDbHelper dbHelper = new CellDbHelper(context);
    try
        SQLiteDatabase db = dbHelper.getWritableDatabase();

        ContentValues values = new ContentValues();

        try 
            /* delete old db if it exists */
            db.delete(CellEntryContract.CellEntry.TABLE_NAME_CELL, null, null);
         catch (Exception e)
        


        for (int i = 0; i<cell.size();i++) 

            values.put(CellEntryContract.CellEntry.COLUMN_NAME_CELL_NUMBER, cell.get(i).getCellNo());
            values.put(CellEntryContract.CellEntry.COLUMN_NAME_CELL_DENSITY, cell.get(i).getDensity());
            values.put(CellEntryContract.CellEntry.COLUMN_NAME_CELL_VOLTAGE, cell.get(i).getCellVoltage());
            db.insert(CellEntryContract.CellEntry.TABLE_NAME_CELL, null, values);
        
        Log.i(CellStorage.class.toString(),"Cells successful saved");
    catch(Exception ex) 
        Log.e(CellStorage.class.toString(), "Could not save cells in local data storage. ", ex);
     finally 
        if (dbHelper != null)
            dbHelper.close();

    

片段:

public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) 
....
    amountOfCells = (((AnnualServiceActivity) getActivity()).getBatteryFromIntent().getCell().intValue());
    generateGrid();
    CellStorage cellStorage = new CellStorage(getContext());
    cellStorage.runCellApiTasks();
    return view;


....
public ArrayList<Cell> getCellsForDB() 
    for (int i = 0; i < amountOfCells; i++) 
        Cell cell = new Cell();
        cell.setCellNo(i + 1);
        cell.setCellVoltage(0);
        cell.setDensity(0);
        Log.i("öööööööööööö",cellsForDB.get(i).getCellNo()+"");
        cellsForDB.add(cell);
    
    return cellsForDB;

...

我认为在 getCellsForDB() 中准备好 ArrayList 之前完成的 doInBackground(...) 方法可能是因为我收到空对象引用错误。那么是否可以让方法等到 getCellsForDB() 中的 ArrayList 准备好?

崩溃日志:

    08-07 15:43:54.388 1585-1585/frontend.datastorage.CellStorage: Could not save cells in local data storage. 
                                                                                                                              java.lang.NullPointerException: Attempt to invoke virtual method 'int java.util.ArrayList.size()' on a null object reference
                                                                                                                                  at CellApiTask.onPostExecute(CellApiTask.java:49)
                                                                                                                                  at CellApiTask.onPostExecute(CellApiTask.java:20)
                                                                                                                                  at android.os.AsyncTask.finish(AsyncTask.java:660)
                                                                                                                                  at android.os.AsyncTask.-wrap1(AsyncTask.java)
                                                                                                                                  at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:677)
                                                                                                                                  at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                                                                                  at android.os.Looper.loop(Looper.java:154)
                                                                                                                                  at android.app.ActivityThread.main(ActivityThread.java:6692)
                                                                                                                                  at java.lang.reflect.Method.invoke(Native Method)
                                                                                                                                  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1468)
                                                                                                                                  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1358)
08-07 15:43:54.392 1585-1585/fronius.com.serviceapp_frontend E/class fronius.com.serviceapp_frontend.datastorage.CellStorage: Could not save cells in local data storage. 
                                                                                                                              java.lang.NullPointerException: Attempt to invoke virtual method 'int java.util.ArrayList.size()' on a null object reference
                                                                                                                                  at CellApiTask.onPostExecute(CellApiTask.java:49)
                                                                                                                                  at CellApiTask.onPostExecute(CellApiTask.java:20)
                                                                                                                                  at android.os.AsyncTask.finish(AsyncTask.java:660)
                                                                                                                                  at android.os.AsyncTask.-wrap1(AsyncTask.java)
                                                                                                                                  at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:677)
                                                                                                                                  at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                                                                                  at android.os.Looper.loop(Looper.java:154)
                                                                                                                                  at android.app.ActivityThread.main(ActivityThread.java:6692)
                                                                                                                                  at java.lang.reflect.Method.invoke(Native Method)
                                                                                                                                  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1468)
                                                                                                                                  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1358)

【问题讨论】:

添加你的崩溃日志 你在哪里实例化了 cellsForDB? @USKMobility 我添加了错误日志。我在 Fragment onCreateView() 方法中实例化它 getCellsForDB 这个方法是另一个类 @WeSt 你在后台创建片段的新实例 oncreate() 和 oncreateview() 此时也不会调用你的所有列表..不会被实例化 【参考方案1】:

您不必在这里等待任何东西,doInBackground 方法在 cellVoltageClass.getCellsForDB() 返回时完成其执行。 getCellsForDB() 似乎返回 null,因为 cellsForDB 为 null(您没有早点崩溃的唯一原因是因为 amountOfCells 为 0 并且 getCellsForDB() 内部的 for 没有循环)

【讨论】:

这听起来很正确。但是,如果首先插入 Fragment,则 amountOfCells 不为 0,它会运行。如何先完成片段的插入,然后调用 cellsForDB。我试图在 Fragment 的 onCreateView() 末尾调用 doInBackground,但它不起作用 让你的应用程序逻辑与片段生命周期事件绑定不是一个好方法,但你可以在第一次调用片段的 onResume() 时做到这一点 - 在这里你可以确定你的片段已经“插入”,现在对用户可见。

以上是关于如何使 AsyncTask“doInBackground()”等待一个数组列表的主要内容,如果未能解决你的问题,请参考以下文章

使用 AsyncTask 会使应用程序变慢

如何从 Android AsyncTask 更改活动 UI?

使 android AsyncTask 等待结果

如何在 Android Studio 中使用 AsyncTask 从可绘制对象中设置图像

AsyncTask 运行时 Espresso 测试返回按钮

使用AsyncTask在android中创建JSoup类