显示来自sqlite数据库的数据时“尝试在空对象引用上调用虚拟方法”[重复]

Posted

技术标签:

【中文标题】显示来自sqlite数据库的数据时“尝试在空对象引用上调用虚拟方法”[重复]【英文标题】:"Attempt to invoke virtual method on a null object reference" while displaying data from the sqlite database [duplicate] 【发布时间】:2018-10-30 07:14:28 【问题描述】:

我想从数据库中检索详细信息并使用文本视图将它们打印在一个选项卡式活动片段中。 但是,我得到空对象引用。关于我为什么会收到此错误以及我应该做些什么来避免此类错误的任何线索?


这是我的片段(fragment_home_left.class),我必须在其中显示数据库中的记录

package com.rishabh.admin.bucomp;

import android.database.Cursor;
import android.os.Bundle;

import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

public class fragment_home_left extends android.support.v4.app.Fragment implements View.OnClickListener 

    Login_Signup_DB_adapter db_adapter;
    String TAG = "FRAGMENT_HOME_LEFT";

//Button addGroup ,addMember;
    //EditText new_group_edit_text;

    Button display_users;

    TextView display_box;
    String details_recieved;


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 

        View view = inflater.inflate(R.layout.fragment_main_activity_home_left, container, false);

        //addGroup = (Button) view.findViewById(R.id.button_add_Group);
        display_users = (Button)view.findViewById(R.id.button_display_users);
        //addMember = (Button) view.findViewById(R.id.button_display_users);
        //new_group_edit_text = (EditText) view.findViewById(R.id.editText_fragment_left);
        display_box = (TextView) view.findViewById(R.id.editText_displayBox);

        //addMember.setOnClickListener(this);
        display_users.setOnClickListener(this);
        //addGroup.setOnClickListener(this);
        //To display the records of all the users registered within the database
        //Display_user_data();
        return view;
    
    @Override
    public void onClick(View v) 
        if(v.getId() == R.id.button_display_users)
        
            //details_recieved = new_group_edit_text.getText().toString().trim();
            //Toast.makeText(getActivity(),"Member added "+details_recieved,Toast.LENGTH_LONG).show();

            Log.i(TAG, "onClick: Display users button clicked, calling display function");
            Fetch_user_data();
        else
            Log.i(TAG, "onClick: NO ID BUTTON");
        
    

    private void Fetch_user_data() 
        Log.i(TAG, "Fetch_user_data: CALLING FETCH USER DATA METHOD");
        Cursor cursor = db_adapter.getAll_users();
        Log.i(TAG, "Fetch_user_data: CURSOR RECIEVED SOMETHING");
        Display_user_data(cursor);

    

    private void Display_user_data(Cursor cursor) 
        Log.i(TAG, "Display_user_data: CALLED DISPLAY_USER_DATA");
        String message = "";

        if(cursor!= null && cursor.getCount() > 0)
            Log.i(TAG, "Display_user_data: DO WHILE LOOP WILL BE EXECUTED");
            cursor.moveToFirst();
            do
                int user_id;
                String user_name,user_email,user_password;

                user_id = cursor.getInt(db_adapter.USER_COL_ROW_ID);
                user_name = cursor.getString(db_adapter.USER_COL_NAME);
                user_email = cursor.getString(db_adapter.USER_COL_EMAIL);
                user_password = cursor.getString(db_adapter.USER_COL_PASSWORD);

                message = message+"id="+user_id+","+"name="+user_name+","+"email="+user_email
                        +","+"pass="+user_password+"\n";
                Log.i(TAG, "Display_user_data: NEW MESSAGE STRING APPENDED");
            while(cursor.moveToNext());
            cursor.close();
            Log.i(TAG, "Display_user_data: CURSOR IS CLOSED");
        
        Log.i(TAG, "Display_user_data: CALLING SET_DATA_EDIT_TEXT METHOD");
        set_data_in_editText(message);
    

    private void set_data_in_editText(String message) 
        Log.i(TAG, "set_data_in_editText: NOW SETTING MESSAGE TO TEXT VIEW");
        display_box.setText(message);
    




与上述片段链接的xml布局(fragment_main_activity_home_left.xml)

<?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_ android:layout_>

    <Button
        android:id="@+id/button_display_users"
        android:layout_
        android:layout_
        android:layout_alignParentBottom="true"
        android:layout_alignParentEnd="true"
        android:layout_marginBottom="67dp"
        android:layout_marginEnd="140dp"
        android:background="@color/Material_red"


android:elegantTextHeight="true"
        android:paddingLeft="5dp"
        android:paddingRight="5dp"
        android:text="Display_users"
        android:textColor="@android:color/background_light" />

    <EditText
        android:id="@+id/editText_displayBox"
        android:layout_
        android:layout_
        android:layout_above="@+id/button_display_users"
        android:layout_alignParentStart="true"
        android:layout_marginBottom="10dp"
        android:ems="10"
        android:inputType="textPersonName"
        android:text="Name" />

</RelativeLayout>

这是存储sqlite数据库中数据并与之交互的数据库助手类

package com.rishabh.admin.bucomp;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

public class Login_Signup_DB_adapter 

    //Database constants area

    private static final String TAG = "DATABASE ADAPTER";
    public static final String DB_NAME = "bucomp_db";
    public static final int DB_VERSION = 2;

    //Current_active_user_id stores the id of the current user
    public static long Current_active_user_id = -2;

    //Current_active_group_id stores the group id of the current group
    public static long Current_active_group_id = 0;

    private final Context context;
    private DBHelper MYDBHelper;
    private SQLiteDatabase db_readable, db_writable;

    //End of database constants area



    //column names for USER

    public static final String DB_TABLE_USER = "user_table";

    public static final String USER_KEY_ROWID = "user_id";
    public static final String USER_KEY_NAME = "user_name";
    public static final String USER_KEY_EMAIL = "user_email";
    public static final String USER_KEY_PASSWORD = "user_password";

    //column number for all the columns created above

    public static final int USER_COL_ROW_ID = 0;
    public static final int USER_COL_NAME = 1;
    public static final int USER_COL_EMAIL = 2;
    public static final int USER_COL_PASSWORD = 3;

    //USER_ALL_KEYS stores the list of all the columns created

    public static final String[] USER_ALL_KEYS = 
            USER_KEY_ROWID, USER_KEY_NAME, USER_KEY_EMAIL, USER_KEY_PASSWORD
            ;

    //create table query to be used by the database helper

    private static final String DB_CREATE_QUERY_USER =
            "create table " + DB_TABLE_USER
            + " (" + USER_KEY_ROWID + " integer primary key autoincrement, "
            + USER_KEY_NAME + " text not null, "
            + USER_KEY_EMAIL + " text not null, "
            + USER_KEY_PASSWORD + " text not null"
            + ");";


    //column names for GROUPS within USERS

    public static final String DB_TABLE_GROUP = "group_table";

    public static final String GROUP_KEY_ROWID = "group_id";
    public static final String GROUP_KEY_NAME = "group_name";
    public static final String GROUP_KEY_TOTAL_BUDGET = "group_budget";
    public static final String GROUP_KEY_TOTAL_MEMBERS = "group_total_members";
    public static final String GROUP_KEY_LINKED_USER_ID = "group_linked_user_id";

    //column number for all the columns created above

    public static final int GROUP_COL_ROW_ID = 0;
    public static final int GROUP_COL_NAME = 1;
    public static final int GROUP_COL_TOTAL_BUDGET = 2;
    public static final int GROUP_COL_TOTAL_MEMBERS = 3;

    //GROUP_ALL_KEYS stores the list of all the columns created

    public static final String[] GROUP_ALL_KEYS = 
            GROUP_KEY_ROWID,
            GROUP_KEY_NAME,
            GROUP_KEY_TOTAL_BUDGET,
            GROUP_KEY_TOTAL_MEMBERS,
            GROUP_KEY_LINKED_USER_ID
    ;

    //create table query to be used by the database helper

    private static final String DB_CREATE_QUERY_GROUP =
            "create table " + DB_TABLE_GROUP
                    + " (" + GROUP_KEY_ROWID + " integer primary key autoincrement, "
                    + GROUP_KEY_NAME + " text not null, "
                    + GROUP_KEY_TOTAL_BUDGET + " integer, "
                    + GROUP_KEY_TOTAL_MEMBERS + " integer, "
                    + GROUP_KEY_LINKED_USER_ID + " integer not null"
                    + ");";


    //column names for MEMBERS within GROUPS

    public static final String DB_TABLE_MEMBER = "member_table";

    public static final String MEMBER_KEY_ROWID = "member_id";
    public static final String MEMBER_KEY_NAME = "member_name";
    public static final String MEMBER_KEY_LINKED_GROUP_ID = "member_linked_group_id";
    public static final String MEMBER_KEY_LINKED_USER_ID = "member_linked_user_id";

    //column number for all the columns created above

    public static final int MEMBER_COL_ROW_ID = 0;
    public static final int MEMBER_COL_NAME = 1;
    public static final int MEMBER_COL_LINKED_GROUP_ID = 2;
    public static final int MEMBER_COL_LINKED_USER_ID = 3;

    //MEMBER_ALL_KEYS stores the list of all the columns created

    public static final String[] MEMBER_ALL_KEYS = 
            MEMBER_KEY_ROWID,
            MEMBER_KEY_NAME,
            MEMBER_KEY_LINKED_GROUP_ID,
            MEMBER_KEY_LINKED_USER_ID
    ;

    //create table query to be used by the database helper

    private static final String DB_CREATE_QUERY_MEMBER =
            "create table " + DB_TABLE_MEMBER
                    + " ("
                    + MEMBER_KEY_ROWID + " integer primary key autoincrement, "
                    + MEMBER_KEY_NAME + " text not null, "
                    + MEMBER_KEY_LINKED_GROUP_ID + " integer not null, "
                    + MEMBER_KEY_LINKED_USER_ID + " integer not null"
                    + ");";


    public Login_Signup_DB_adapter(Context context) 
        this.context = context;
        MYDBHelper = new DBHelper(context);
    

    public Login_Signup_DB_adapter open_database()
        db_writable = MYDBHelper.getWritableDatabase();
        db_readable = MYDBHelper.getReadableDatabase();
        return this;
    

    public void close_database()
        MYDBHelper.close();
    

    //insert new user in the user table

    public long SignUp_new_user(String UserName, String UserEmail, String UserPassword)

        //set up contentValues to insert the data into the required DB

        ContentValues contentValues = new ContentValues();

        //feed data into the contentValues

        contentValues.put(USER_KEY_NAME, UserName);
        contentValues.put(USER_KEY_EMAIL, UserEmail);
        contentValues.put(USER_KEY_PASSWORD, UserPassword);

        //insert the data stored in the contentValues into the DB_USER
        //The return statement will return the id of the newly entered user in the user table
        //this is the reason why the return type is long
        Log.i(TAG, "SignUp_new_user: WRITING NEW USER IN THE DATABSE");
        return db_writable.insert(DB_TABLE_USER, null, contentValues);
    


    public long Check_Login_user(String UserName, String UserPassword)
    
        Log.i(TAG, "Check_Login_user: ENTERED Check_Login_user");
        //db_readable = MYDBHelper.getReadableDatabase();
        Log.i(TAG, "Check_Login_user: READABLE DB SET");
        /* To verify if the user if already registered and take appropriate actions as below:
        1. If the user is already registered and enters correct details, grant login access.
        2. If the user is already registered but enters incorrect details, revoke access.
        3. If the user is not registered, simply revoke the access.

        NOTE: If possible, try to redirect the user to the signUp page if CASE 3 occurs.

        */

        String where = USER_KEY_NAME+"=?";
        String[] args = UserName;
        Log.i(TAG, "Check_Login_user: QUERYING DB FOR LOGIN");

        Cursor cursor = db_readable.query(
                DB_TABLE_USER,
                USER_ALL_KEYS,
                where,
                args,
                null,
                null,
                null
        );

        Log.i(TAG, "Check_Login_user: CURSOR POPULATED");
        if (cursor.getCount() > 0)
        
            Log.i(TAG, "Check_Login_user: CURSOR IS NOT NULL");
            cursor.moveToFirst();
            String password = cursor.getString(USER_COL_PASSWORD);
            String username = cursor.getString(USER_COL_NAME);
            String email = cursor.getString(USER_COL_EMAIL);

            Log.i(TAG, "Check_Login_user: DATA FETCHED FROM DB IS :\n"
                    + "NAME: " + username + "\n"
                    + "Email : " + email + "\n"
                    + "Password : " + password + "\n"
            );
            Log.i(TAG, "Check_Login_user: MATCHING :" + username + " with " + UserName
            + " and " + password + " with " + UserPassword +"\n");
            if (username.equals(UserName) && password.equals(UserPassword)) 
                Log.i(TAG, "Check_Login_user: USER FOUND \n");
                Current_active_user_id = cursor.getInt(USER_COL_ROW_ID);
                Log.i(TAG, "Check_Login_user: CURRENT USER ID IS :" + Current_active_user_id + "\n");


             else 
                Log.i(TAG, "Check_Login_user: INCORRECT PASSWORD");
                Current_active_user_id = -2;
            
        else
            Log.i(TAG, "Check_Login_user: NO SUCH USERNAME");
            Current_active_user_id = -4;
        
        return Current_active_user_id;
    

    //insert new group of the current user in the group table

    public long insert_Row_group(String GroupName, int TotalBudget, int TotalMembers)

        //set up contentValues to insert the data into the required DB

        ContentValues contentValues = new ContentValues();

        //feed data into the contentValues

        contentValues.put(GROUP_KEY_NAME, GroupName);
        contentValues.put(GROUP_KEY_TOTAL_BUDGET, TotalBudget);
        contentValues.put(GROUP_KEY_TOTAL_MEMBERS, TotalMembers);



        /*
        insert the data stored in the contentValues into the DB_GROUP
        The return statement will return the id of the newly entered user in the user table
        this is the reason why the return type is long
        */

        return db_writable.insert(DB_TABLE_GROUP, null, contentValues);
    

    //insert new member of the current group in the member table

    public long insert_Row_member()
        return -1;
    

    //delete specific user in the user table

    public boolean delete_Row_user()
        return true;
    

    //delete specific group of the current user in the group table

    public boolean delete_Row_group()
        return true;
    

    //delete specific member in the group of the current user from the member table

    public boolean delete_Row_member()
        return true;
    

    //delete all the users from the user table

    public void delete_all_users()

    

    //delete all the groups of the current user from the group table

    public void delete_all_groups()

    

    //delete all the members in the current group of the active user from the member table

    public void delete_all_members()

    


    //retrieve all the data present in the user table.

    public Cursor getAll_users()
        Log.i(TAG, "getAll_users: ENTERED getAll_users");

        Cursor cursor = db_readable.query(
                DB_TABLE_USER,
                USER_ALL_KEYS,
                null,
                null,
                null,
                null,
                null,
                null
        );

        if(cursor != null)
           Log.i(TAG, "getAllRows_users: DATA FETCHED SUCCESSFULLY");
            cursor.moveToFirst();
        
        else 
            Log.i(TAG, "getAllRows_users: NO DATA FOR USERS FETCHED");
        
        return cursor;
    

    //retrieve all the data present in the group table for the current user

    //public Cursor getAllRows_groups()

    //

    //retrieve all the data present in the member table for the specific group of current user

    //public Cursor getAllRows_members()

    //





    //Creating private DataBase Helper class to initialize the database

    private static class DBHelper extends SQLiteOpenHelper
        public DBHelper(Context context) 
            super(context, DB_NAME, null, DB_VERSION);
        

        @Override
        public void onCreate(SQLiteDatabase db) 
            //initialize user table
            db.execSQL(DB_CREATE_QUERY_USER);
            //initialize group table
            db.execSQL(DB_CREATE_QUERY_GROUP);
            //initialize member table
            db.execSQL(DB_CREATE_QUERY_MEMBER);
        

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) 
            //if table columns are changed or updated, delete the previous version

            db.execSQL("DROP TABLE IF EXISTS " + DB_TABLE_USER);
            db.execSQL("DROP TABLE IF EXISTS " + DB_TABLE_GROUP);
            db.execSQL("DROP TABLE IF EXISTS " + DB_TABLE_MEMBER);
            //and re-initialize the databases with updated parameters
            onCreate(db);

        
    //End of DBHelper class
//End Login_Signup_DB_adapter class

这是我在单击“显示用户”按钮时遇到的日志错误。

05-20 08:37:20.413 1818-1818/? I/LOGIN: checkInDataBase: LOGIN USER EXISTS WITH ID :1
05-20 08:37:25.106 594-938/? I/WindowManager: Destroying surface Surface(name=com.rishabh.admin.bucomp/com.rishabh.admin.bucomp.MainActivity_Login) called by com.android.server.wm.WindowStateAnimator.destroySurface:2014 com.android.server.wm.WindowStateAnimator.destroySurfaceLocked:881 com.android.server.wm.WindowState.destroyOrSaveSurface:2073 com.android.server.wm.WindowManagerService.tryStartExitingAnimation:3017 com.android.server.wm.WindowManagerService.relayoutWindow:2897 com.android.server.wm.Session.relayout:215 android.view.IWindowSession$Stub.onTransact:286 com.android.server.wm.Session.onTransact:136 

<LOG ERROR>
05-20 08:37:33.637 1818-1818/? E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.rishabh.admin.bucomp, PID: 1818
    java.lang.NullPointerException: Attempt to invoke virtual method 'android.database.Cursor com.rishabh.admin.bucomp.Login_Signup_DB_adapter.getAll_users()' on a null object reference
        at com.rishabh.admin.bucomp.fragment_home_left.Fetch_user_data(fragment_home_left.java:72)
        at com.rishabh.admin.bucomp.fragment_home_left.onClick(fragment_home_left.java:62)
        at android.view.View.performClick(View.java:5609)
        at android.view.View$PerformClick.run(View.java:22259)
        at android.os.Handler.handleCallback(Handler.java:751)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6077)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)

【问题讨论】:

【参考方案1】:

你还没有初始化你的 db_adapter 这就是为什么 db_adapternull 并且你正在调用 Login_Signup_DB_adapter 类的函数。所以,你需要在fragment_home_left类的onCreateView中像这样初始化db_adapter

db_adapter = new Login_Signup_DB_adapter(this);

【讨论】:

我这样做了,但错误仍然存​​在 致命异常:主进程:com.rishabh.admin.bucomp,PID:21432 java.lang.NullPointerException:尝试调用虚拟方法 'android. database.Cursor android.database.sqlite.SQLiteDatabase.query(java.lang.String, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, java.lang .String, java.lang.String, java.lang.String)' 在 com.risabh.admin.bucomp.Login_Signup_DB_adapter.getAll_users(Login_Signup_DB_adapter.java:312) 的空对象引用上 有什么想法吗? @rishabhkalra 将您的 logcat 错误与您的问题放在一起,这在 cmets 中是无法理解的。 对不起,对不起,我只想告诉你,现在我在数据库查询中遇到了同样的空指针异常 @rishabhkalra 那是因为你没有在任何地方调用open_database 来初始化db_readabledb_writable 该死!!我没有……那我有点傻!感谢您指出这一点【参考方案2】:

您必须实例化适配器。尝试添加

db_adapter = new Login_Signup_DB_adapter(getContext())

在您的 Fragment onCreate() 方法中

【讨论】:

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

如何在 Android Studio 中显示来自 SQLite 数据库浏览器的图像?

在表格布局中显示来自 sqlite 的数据,

使用基本适配器和列表视图显示来自 SQLite 的变量数据

来自 SQLite 数据库 C# Android 的 Xamarin ListView 显示项目

来自sqlite的Android中的Textview显示

如何使用光标和循环显示来自 sqlite 的片段的 recyclerview