使用异步任务时光标变为空?
Posted
技术标签:
【中文标题】使用异步任务时光标变为空?【英文标题】:My cursor becomes null when I use async task? 【发布时间】:2020-12-25 15:28:04 【问题描述】:我有一个数据库代码,它从我的表中获取数据并将其存储到我的光标中,但是当我打开在回收站视图上显示数据的活动时,在主线程上运行数据库代码会减慢我的应用程序的速度。所以我将数据库代码移动到一个 asyntask 内部类并尝试运行它。
但是,在 onCreate ()
中运行 asyntask 后,我的回收器视图适配器代码运行并且在游标对象上调用的 getItemCount ()
会抛出 null pointer exception
,因为游标为空。
通过调试,我发现光标在哪里变为空,但不明白为什么它变为空。 accessDatabase ()
运行时的游标不为空,但在onCreate ()
运行asynctask内部类后游标变为空。
onCreate方法中的代码:
protected void onCreate (Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.item_grocery);
RecyclerView groceryRecycler = (RecyclerView) findViewById(R.id.grocery_recycler_view);
StartDatabase sd = new StartDatabase();
sd.execute(databaseHelper);
Log.d ("blue", "sd has ran");
if (cursor == null)
Log.d ("green", "cursor is null");//I receive this in the log cat
captionedImagesAdapter adapter = new captionedImagesAdapter (this, cursor);
GridLayoutManager layoutManager = new GridLayoutManager(this, 2, GridLayoutManager.VERTICAL, false);
groceryRecycler.setLayoutManager(layoutManager);
groceryRecycler.setAdapter (adapter);
异步任务内部类:
private class StartDatabase extends AsyncTask<MyDatabaseHelper, Void, Boolean>
protected void onPreExecute ()
@Override
protected Boolean doInBackground(MyDatabaseHelper... myDatabaseHelpers)
try
accessDataBase();
return true;
catch (SQLiteException e)
return false;
protected void onPostExecute (Boolean success)
if (!success)
Toast toast = Toast.makeText(grocery_item.this, "Database unavailable", Toast.LENGTH_SHORT);
toast.show();
访问数据库方法:
public void accessDataBase ()
try
db = databaseHelper.getReadableDatabase();
cursor = db.query ("GROCERY_DATA", new String[] "NAME", "PATHS", null, null, null, null, null);
if (cursor == null)
Log.d ("blue", "cursor is null");
catch (SQLiteException e)
e.printStackTrace();
我的回收视图适配器:
public class captionedImagesAdapter extends RecyclerView.Adapter <captionedImagesAdapter.ViewHolder>
private Context context;
private Cursor cursor;
public captionedImagesAdapter (Context context, Cursor cursor)
this.context = context;
this.cursor = cursor;
if (this.cursor == null)
Log.d ("red", "cursor is null");//I receive this in the log cat
public captionedImagesAdapter.ViewHolder onCreateViewHolder (ViewGroup parent, int viewType)
LayoutInflater inflater = LayoutInflater.from(context);
CardView cv = (CardView) inflater.inflate(R.layout.card_view, parent, false);
return new ViewHolder (cv);
public void onBindViewHolder(ViewHolder holder, int position)
if (!cursor.moveToPosition(position))
return;
String info_text = cursor.getString (0);
holder.textView.setText(info_text);
String image_Path = cursor.getString(1);
File file = new File (image_Path);
if (file.exists())
Bitmap bitmap = BitmapFactory.decodeFile (file.getAbsolutePath());
holder.imageView.setImageBitmap(bitmap);
public int getItemCount()
return cursor.getCount();//Line throwing the exception
public static class ViewHolder extends RecyclerView.ViewHolder
private ImageView imageView;
private TextView textView;
public ViewHolder(CardView view)
super(view);
imageView = view.findViewById(R.id.info_image);
textView = view.findViewById(R.id.info_text);
我收到的异常:
java.lang.NullPointerException: Attempt to invoke interface method 'int android.database.Cursor.getCount()' on a null object reference
at com.myapps.myapplication.captionedImagesAdapter.getItemCount(captionedImagesAdapter.java:58)
at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep1(RecyclerView.java:4135)
at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:3939)
at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4499)
at android.view.View.layout(View.java:22085)
at android.view.ViewGroup.layout(ViewGroup.java:6290)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
at android.view.View.layout(View.java:22085)
at android.view.ViewGroup.layout(ViewGroup.java:6290)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1829)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1673)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1582)
at android.view.View.layout(View.java:22085)
at android.view.ViewGroup.layout(ViewGroup.java:6290)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
at android.view.View.layout(View.java:22085)
at android.view.ViewGroup.layout(ViewGroup.java:6290)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1829)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1673)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1582)
at android.view.View.layout(View.java:22085)
at android.view.ViewGroup.layout(ViewGroup.java:6290)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
at com.android.internal.policy.DecorView.onLayout(DecorView.java:786)
at android.view.View.layout(View.java:22085)
at android.view.ViewGroup.layout(ViewGroup.java:6290)
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:3333)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2810)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1930)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7988)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1154)
at android.view.Choreographer.doCallbacks(Choreographer.java:977)
at android.view.Choreographer.doFrame(Choreographer.java:893)
at android.view.Choreographer$FrameHandler.handleMessage(Choreographer.java:1082)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7682)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:516)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
【问题讨论】:
在你的异步任务的 postexecute() 中设置你的适配器,你应该很高兴 主线程不会等到完成 AsyncTask。我认为这是获取空值的问题。您可以将整个适配器类放在 onPostExecute() 中。 【参考方案1】:您将其设为 null 的原因之一是错误地假设主线程正在等待异步任务完成。那当然是错误的(否则您将不需要其他线程)。您有不同的选择来修复它,例如:
【讨论】:
- 考虑任何其他异步解决方案(Rx、线程池、协程......)。 AsyncTask 和 Loaders 已经过时了。 关于异步任务的公平点。不适用于装载机 imo developer.android.com/guide/components/loaders "从 Android P (API 28) 开始,加载程序已被弃用。" 我错过了。谢谢@Kikiwa以上是关于使用异步任务时光标变为空?的主要内容,如果未能解决你的问题,请参考以下文章