首页 > 解决方案 > 从一列更新 SQLite 一个值

问题描述

我有一个使用 RecyclerView 和 SQLite 的应用程序。

我的数据库是:

public class countersDatabase extends SQLiteOpenHelper {

    private static final String DB_NAME = "Counters.db";
    private static final String DB_TABLE = "Counters_Table";

    //Columns
    private static final String ID = "ID";
    private static final String ITEM_INDEX = "ITEM_INDEX";
    private static final String COLOR = "COLOR";
    private static final String MAXTIME = "MAXTIME";
    private static final String NAME = "NAME";
    private static final String TYPE = "TYPE";
    private static final String USINGTIME = "USINGTIME";

    private static final String CREATE_TABLE = "CREATE TABLE " + DB_TABLE + " (" +
            ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + //i = 0
            ITEM_INDEX + " INTEGER, " +                   //i = 1
            COLOR + " TEXT, " +                           //i = 2
            MAXTIME + " TEXT, " +                         //i = 3
            NAME + " TEXT, " +                            //i = 4
            TYPE + " TEXT, " +                            //i = 5
            USINGTIME + " TEXT " + ") ";                  //i = 6

    public countersDatabase(Context context) {
        super(context, DB_NAME, null, 1);
    };

    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
        sqLiteDatabase.execSQL(CREATE_TABLE);
    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
        sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + DB_TABLE);
        onCreate(sqLiteDatabase);
    }

    public boolean insertData(int item_index ,String color, String maxTime, String name, String type, String usingTime) {
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues contentValues = new ContentValues();

        contentValues.put(ITEM_INDEX, item_index);
        contentValues.put(COLOR, color);
        contentValues.put(MAXTIME, maxTime);
        contentValues.put(NAME, name);
        contentValues.put(TYPE, type);
        contentValues.put(USINGTIME, usingTime);

        long result = db.insert(DB_TABLE, null, contentValues);

        if (result == -1) return false;
        else
            return true;
    }

    public ArrayList<Counter> getAllData() {
        ArrayList<Counter> arrayList = new ArrayList<>();
        SQLiteDatabase db = this.getReadableDatabase();
        Cursor cursor = db.rawQuery("SELECT * FROM " + DB_TABLE, null);

        while (cursor.moveToNext()) {
            int id = cursor.getInt(0);
            int item_index = cursor.getInt(1);
            String color = cursor.getString(2);
            String maxTime = cursor.getString(3);
            String name = cursor.getString(4);
            String type = cursor.getString(5);
            String usingTime = cursor.getString(6);
            Counter counter = new Counter(id, item_index, color, maxTime, name, type, usingTime);
            arrayList.add(counter);
        }
        return arrayList;
    }

    public void updateTimeOnData(int position, String time) {
        SQLiteDatabase db = getWritableDatabase();
        db.execSQL("UPDATE "+DB_TABLE+" SET "+USINGTIME+" = '"+time+"' WHERE "+ITEM_INDEX+" = "+position+";");
        db.close();
    }

    public void deleteDataItem(int position) {
        SQLiteDatabase db = getWritableDatabase();
        db.execSQL("DELETE FROM " + DB_TABLE + " WHERE " +
                ITEM_INDEX + " = " + position + ";");
        db.execSQL("UPDATE " + DB_TABLE + " SET " + ITEM_INDEX + " = " +
                ITEM_INDEX + " -1 " + " WHERE " + ITEM_INDEX + " > " + position + ";");
        db.close();
    }
}

当我尝试updateTimeOnData(int position, String time)从 CounterHolder 类调用如下:

public class CounterHolder extends RecyclerView.ViewHolder {

    countersDatabase countersDatabase;

    NumberPicker timePicker;
    TextView timeLabel;
    TextView txtUnderTime;

    double usingHours;
    double maxHours;
    int counterPosition;
    String counterDiffHours;

    private final TextView t3_name;
    private final TextView t4_type;
    private final Button t5_usingTime;
    private final TextView remainLabel;

    private Counter counter;
    private Context context;

    public CounterHolder(Context context, View itemView) {
        super(itemView);

        (...)

        itemView.setOnClickListener(view -> {
            if (counter != null) {
                maxHours = timeStringToDouble(counter.getMaxTime());
                usingHours = timeStringToDouble(counter.getUsingTime());
                counterPosition = getAdapterPosition();

                TextView titleToolbarCounter = ((MainActivity)context).findViewById(R.id.titleToolbarCounter);
                String name = counter.getName();
                titleToolbarCounter.setText(name);

                TextView usingTimeCounter = ((MainActivity)context).findViewById(R.id.txtTime);
                String usingTime = counter.getUsingTime();
                usingTimeCounter.setText(usingTime);

                counterBottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);

                TextView pickerLabel = ((MainActivity)context).findViewById(R.id.timePickerLabel);
                pickerLabel.setText("00:30");

                timeLabel = ((MainActivity)context).findViewById(R.id.txtTime);
                txtUnderTime = ((MainActivity)context).findViewById(R.id.txtUnderTime);

                counterDiffHours = timeDoubleToString(maxHours - usingHours);

                Button minusButton = ((MainActivity)context).findViewById(R.id.minusButton);
                Button plusButton = ((MainActivity)context).findViewById(R.id.plusButton);

                plusButton.setOnClickListener(plusAction -> {
                    double preHours = timeStringToDouble((String) timeLabel.getText());
                    double timeInterval = timeStringToDouble((String) pickerLabel.getText());
                    double postHours = preHours + timeInterval;
                    
                    timeLabel.setText(timeDoubleToString(postHours));
//------------ERROR NEXT LINE------------
                    countersDatabase.updateTimeOnData(counterPosition, timeDoubleToString(postHours)); //Line 212
                    counterDiffHours = timeDoubleToString(maxHours - postHours);
                    if (postHours/maxHours == 0) {
                            txtUnderTime.setText(((MainActivity)context).getResources().getString(R.string.text_under_time_ini, counterDiffHours));
                    } else if (postHours/maxHours <= 0.25) {
                            txtUnderTime.setText(((MainActivity)context).getResources().getString(R.string.text_under_time_00, counterDiffHours));
                    } else if (postHours/maxHours <= 0.50) {
                            txtUnderTime.setText(((MainActivity)context).getResources().getString(R.string.text_under_time_25, counterDiffHours));
                    } else if (postHours/maxHours <= 0.75) {
                            txtUnderTime.setText(((MainActivity)context).getResources().getString(R.string.text_under_time_50, counterDiffHours));
                    } else {
                            txtUnderTime.setText(((MainActivity)context).getResources().getString(R.string.text_under_time_75, counterDiffHours));
                    }
                }
            });

                
            }
        });
    }

    public void bindCounter(Counter counter) {
        (...)
    }

    public double timeStringToDouble(String time) {
        String hoursString = time.substring(0,2);
        String minutesString = time.substring(3);

        double hours = Double.parseDouble(hoursString);
        double minutes = Double.parseDouble(minutesString);

        return hours + minutes/60;
    }

    public String timeDoubleToString(double time) {
        BigDecimal bigDecimal = new BigDecimal(String.valueOf(time));
        int hours = bigDecimal.intValue();
        double decimalHours = bigDecimal.subtract(new BigDecimal(hours)).doubleValue();
        int minutes = (int) (decimalHours * 60);

        String hoursString;
        String minutesString;
        if (String.valueOf(hours).length() == 2) {
            hoursString = String.valueOf(hours);
        } else {
            hoursString = "0" + hours;
        }
        if (String.valueOf(minutes).length() == 2) {
            minutesString = String.valueOf(minutes);
        } else {
            minutesString = "0" + minutes;
        }

        return hoursString + ":" + minutesString;
    }
}

我收到一个错误:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: mycounter, PID: 32064
    java.lang.NullPointerException: Attempt to invoke virtual method 'void mycounter.countersDatabase.updateTimeOnData(int, java.lang.String)' on a null object reference
        at mycounter.Adapters.CounterHolder.lambda$null$3$CounterHolder(CounterHolder.java:212)
        at mycounter.Adapters.-$$Lambda$CounterHolder$gWMz9kyJKjdWTqootaS6M3fBw7M.onClick(Unknown Source:8)
        at android.view.View.performClick(View.java:7870)
        at android.widget.TextView.performClick(TextView.java:14970)
        at android.view.View.performClickInternal(View.java:7839)
        at android.view.View.access$3600(View.java:886)
        at android.view.View$PerformClick.run(View.java:29363)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:237)
        at android.app.ActivityThread.main(ActivityThread.java:7948)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1075)

我也尝试编码updateTimeOnData()如下:

public void updateTimeOnData(int position, String time) {
        SQLiteDatabase db = getWritableDatabase();
        ContentValues cv = new ContentValues();
        cv.put(USINGTIME, time);
        db.update(DB_TABLE, cv, ITEM_INDEX + "= ?", new String[] {String.valueOf(position)});
        db.close();
    }

但是出现了同样的错误...

有谁知道哪里可能是错误?因为如果我登录counterPosition并且timeDoubleToString(postHours)我得到正确的值......

标签: androidsqliteandroid-sqlite

解决方案


您永远不会在 中初始化countersDatabaseCounterHolder因此NullPointerException.


推荐阅读