You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

向SQLite数据库插入数据时触发NullPointerException问题求助

解决SQLite插入数据时的NullPointerException问题

看起来你遇到的空指针问题根源很明确——在Fragment还未依附到Activity时就尝试获取Context来初始化SQLiteHelper,导致传入Db的Context为null,进而触发了getDatabasePath的空指针调用。

问题分析

你在StartFragment里直接把Db db = new Db(getActivity());作为成员变量初始化,但Fragment的生命周期里,成员变量初始化的时机远早于Fragment依附到Activity的时机(比如onAttach或onCreateView之前),这时候getActivity()返回的是null,传入Db的Context自然也是null。当你调用insertData时,this.getWritableDatabase()内部需要用到Context,就会抛出空指针异常。

另外还要提个小细节:你Db类的onUpgrade方法里表名拼错了,autiusm应该是autism,不然以后升级数据库时会因为找不到表而报错。

修复步骤

  1. 延迟Db的初始化时机:只声明Db变量,等到Fragment有可用Context时再初始化,比如在onAttach或onViewCreated方法里。
  2. 修正Db类里的表名拼写错误。
  3. 额外添加一些优化点,比如输入校验、数据库资源释放,提升代码健壮性。

修改后的代码

1. 修正StartFragment类

package com.llmago.autism;
import android.content.Context;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class StartFragment extends Fragment {
    private EditText edtName, edtAge, edtScore;
    private Button save;
    private Db db; // 只声明,不提前初始化

    public StartFragment() {
        // Required empty public constructor
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        // 在这里初始化Db,此时Context已经确定可用
        db = new Db(context);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_start, container, false);
        initUI(view);
        return view;
    }

    private void initUI(View view) {
        edtName = view.findViewById(R.id.name);
        edtAge = view.findViewById(R.id.age);
        edtScore = view.findViewById(R.id.result);
        save = view.findViewById(R.id.save);
        save.setOnClickListener(v -> btnSaveAction());
    }

    private void btnSaveAction() {
        String name = edtName.getText().toString().trim();
        String age = edtAge.getText().toString().trim();
        String score = edtScore.getText().toString().trim();

        // 先做输入校验,避免空数据插入
        if(name.isEmpty() || age.isEmpty() || score.isEmpty()){
            Toast.makeText(getActivity(), "请填写完整信息", Toast.LENGTH_SHORT).show();
            return;
        }

        boolean result = db.insertData(name, age, score);
        if (result) {
            Toast.makeText(getActivity(), "保存成功", Toast.LENGTH_LONG).show();
            // 保存后清空输入框,提升用户体验
            edtName.setText("");
            edtAge.setText("");
            edtScore.setText("");
        } else {
            Toast.makeText(getActivity(), "保存失败,请重试", Toast.LENGTH_LONG).show();
        }
    }
}

2. 修正Db类

package com.llmago.autism;
import android.content.ContentValues;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import androidx.annotation.Nullable;

public class Db extends SQLiteOpenHelper {
    public static final String DATABASE_NAME = "autism.db";
    private static final String TABLE_NAME = "autism"; // 用常量存储表名,避免拼写错误

    public Db(@Nullable Context context) {
        super(context, DATABASE_NAME, null, 1);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("CREATE TABLE " + TABLE_NAME + "(" +
                "id INTEGER PRIMARY KEY AUTOINCREMENT," +
                "name TEXT," +
                "age TEXT," +
                "score TEXT)");
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // 修正表名拼写错误,同时使用常量更可靠
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
        onCreate(db);
    }

    public boolean insertData(String name, String age, String score){
        SQLiteDatabase sqLiteDatabase = this.getWritableDatabase();
        ContentValues contentValues = new ContentValues();
        contentValues.put("name", name);
        contentValues.put("age", age);
        contentValues.put("score", score);

        long result = sqLiteDatabase.insert(TABLE_NAME, null, contentValues);
        sqLiteDatabase.close(); // 操作完成后关闭数据库,避免资源泄漏
        return result != -1;
    }
}

额外建议

  • 优先用onAttach(Context context)获取Context,这是Fragment依附到Activity时最早的回调,Context肯定可用;
  • 数据库操作完成后记得关闭连接,避免长期占用资源;
  • 对用户输入做基础校验,既能提升体验,也能保证数据有效性;
  • 用常量存储表名、列名,后期修改或维护时更方便,也能减少拼写错误。

内容的提问来源于stack exchange,提问作者Adnan Abou Elenein

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 08:32:40