【问题标题】:I recieve a null when I use findViewById () on a recylerview在回收站视图中使用 findViewById () 时收到 null
【发布时间】:2020-09-27 12:43:34
【问题描述】:

所以我正在创建一个使用回收器视图来显示卡片视图组件的应用程序,但问题是当我使用RecyclerView groceryRecycler = (RecyclerView) findViewById (R.id.recycler_view1) 时收到空指针异常。对我来说没有意义的是我正在为 groceryRecycler 变量引用正确的回收器视图布局。

我已经对空指针异常进行了研究,它仅在您声明变量但未为其分配对象时发生。但我确实使用findViewById () 为回收站视图变量分配了一个对象。结果,每当我在回收器视图变量上调用一个方法时,我都会得到一个空指针异常。我不明白我在这里做错了什么或如何解决问题,任何帮助将不胜感激。

这是我的回收站视图布局代码:

<androidx.recyclerview.widget.RecyclerView

xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/recycler_view1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical" >

</androidx.recyclerview.widget.RecyclerView>

这是我实例化回收器视图的代码:

package com.myapp.groceryapp;

import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

public class GroceryItem extends AppCompatActivity {

MyDatabaseHelper databaseHelper = new MyDatabaseHelper(this);
SQLiteDatabase db;
Cursor cursor;
RecyclerView groceryRecycler;

private static final int STORAGE_PERMISSION_CODE = 101;

protected void onCreate (Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_grocery_item);


    askForPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, STORAGE_PERMISSION_CODE);

    Log.d ("red", "onCreate has ran");

    StartDatabase sd = new StartDatabase();
    sd.execute(databaseHelper);
}

public void startIntent () {
    Intent intent = new Intent (this, Faan.class);
}

public void accessDataBase () {

    try {

        db = databaseHelper.getReadableDatabase();

        cursor = db.query ("GROCERY_TABLE", new String[] {"NAME", "PATHS"}, null, null, null, null, null);

        db.close();

    } catch (SQLiteException e) {
        e.printStackTrace();
    }

    Log.d ("red", "accessDataBase has ran");

}

public void createRecyclerView () {

    GridLayoutManager layoutManager = new GridLayoutManager(GroceryItem.this, 2, GridLayoutManager.VERTICAL, false);
    GroceryAdapter adapter = new GroceryAdapter (GroceryItem.this, cursor);

    groceryRecycler = (RecyclerView) findViewById(R.id.recycler_view1);


    if (groceryRecycler == null) {
        Log.d ("red", "grocery recylcerview is null");
    }

    groceryRecycler.setLayoutManager(layoutManager);
    groceryRecycler.setAdapter (adapter);

    Log.d ("red", "createRecyclerView has ran");

}

public void askForPermission (String permission, int requestCode) {
    if (isStoragePermissionGranted()) {
        ActivityCompat.requestPermissions(this, new String [] {permission}, requestCode);
    } else {
        Toast.makeText (this, "Permission already granted", Toast.LENGTH_SHORT)
                .show();

    }
}

public void onRequestPermissionsResult (int requestCode, String [] permissions, int [] grantResults) {
    super.onRequestPermissionsResult (requestCode, permissions, grantResults);

    if (requestCode == STORAGE_PERMISSION_CODE) {
        if (grantResults.length > 0 && grantResults [0] == PackageManager.PERMISSION_GRANTED) {
            Toast.makeText(this, "Storage Permission Granted", Toast.LENGTH_SHORT)
                    .show();
        } else {
            Toast.makeText(this, "Storage Permission Denied", Toast.LENGTH_SHORT)
                    .show();
        }
    }


}

public boolean isStoragePermissionGranted () {

    if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
        Toast.makeText(this, "permission granted", Toast.LENGTH_SHORT)
                .show();
        return true;
    }

    return false;
}

private class StartDatabase extends AsyncTask<MyDatabaseHelper, Void, Boolean> {

    protected void onPreExecute () {}

    @Override
    protected Boolean doInBackground(MyDatabaseHelper... myDatabaseHelpers) {

        try {
            accessDataBase();

            Log.d ("red", "doInBackground has ran");

            return true;
        } catch (SQLiteException e) {

            Log.d ("red", "doInBackground has ran");

            return false;

        }


    }

    protected void onPostExecute (Boolean success) {

        createRecyclerView();

      
        adapter.setOnItemClickListener(new GroceryAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(int position) {
                startIntent();
            }
        });
      

        if (!success) {
            Toast toast = Toast.makeText(GroceryItem.this, "Database unavailable", Toast.LENGTH_SHORT);
            toast.show();
        }

        Log.d ("red", "onPostExcecute has ran");

    }
}

}

这是我收到的异常:

    java.lang.NullPointerException: Attempt to invoke virtual method 'void androidx.recyclerview.widget.RecyclerView.setLayoutManager(androidx.recyclerview.widget.RecyclerView$LayoutManager)' on a null object reference
    at com.myapp.groceryapp.GroceryItem.createRecyclerView(GroceryItem.java:70)
    at com.myapp.groceryapp.GroceryItem$StartDatabase.onPostExecute(GroceryItem.java:131)
    at com.myapp.groceryapp.GroceryItem$StartDatabase.onPostExecute(GroceryItem.java:112)
    at android.os.AsyncTask.finish(AsyncTask.java:755)
    at android.os.AsyncTask.access$900(AsyncTask.java:192)
    at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:772)
    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)

【问题讨论】:

  • 你从哪里调用 createRecyclerView?
  • 我从asyncTask中的onPostExecute()调用createRecyclerView()
  • 可能的原因是,您启动的异步任务在您的 setconteview() 完成工作之前就完成了。 (请提及您从哪里开始异步任务)
  • @vishnu 哦,你也许是对的,也许 asynctask 线程在主线程之前完成了,但是,我将如何确认或解决问题?感谢您的帮助
  • 异步任务完成后无需运行任何代码。在 onCreate 中设置回收器,然后保留对适配器的引用。使用异步调用完成时的结果更新适配器的数据

标签: java android android-recyclerview nullpointerexception findviewbyid


【解决方案1】:

您不能将RecyclerView 用作根布局,而必须将其包装到实际布局中。

【讨论】:

  • 我们可以使用RecyclerView作为根布局。请查看this 文档。
【解决方案2】:

尝试使用它从onCreate访问数据库

AsyncTask.execute(new Runnable() {
            @Override
            public void run() {
                //Your task here
            }
        });

希望这会有所帮助。很抱歉这个简短的回答。随时要求澄清...

【讨论】:

  • 我已经在onCreate () 中实现了上面的代码,在run () 中实现了数据库代码,还有在onCreate () 中设置回收器视图的代码,但回收器视图仍然存在空值。然后我尝试在数据库代码之后在run () 中实例化回收器视图,但回收器视图仍然为空。
  • 现在我怀疑回收器视图为空是否是线程问题,因为我尝试在主线程和后台线程上运行代码,并且两次回收器视图都是空值。我不明白是什么让它为空。
  • 我还尝试在 onCreate 中实例化回收器视图时引用回收器视图、适配器和布局管理器实例变量,然后在 onPostExecute () 中实例化适配器和布局管理器在onCreate () 中设置回收站视图,但回收站视图仍为空。
  • @ZahidHabib 听到这个消息很难过。我很抱歉地说我认为您的代码中不需要AsyncTask - [据我所知]。数据库查询只需要很少的时间,可以在UI Thread 中完成。很抱歉让您失望了。
  • @ZahidHabib 另外,如果您正在从事 android 开发,我强烈建议您使用Room Persistence Library 来使用SQLite DatabaseThis 是一个很好的起点。另请查看this 视频教程
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-12-21
  • 1970-01-01
  • 1970-01-01
  • 2016-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多