Методы динамического пользовательского ввода для базы данных в SQLite - PullRequest
0 голосов
/ 24 мая 2019

Как я могу создать динамический формат SQLite для пользователей, чтобы создавать и удалять столбцы базы данных

Например, скажем, на экране активности это изначально:

Trial 1:   Input 1   Input 2

Но послеПри нажатии кнопки «Добавить строку» добавляется еще одна строка, как показано ниже

Trial 1:   Input 1   Input 2
Trial 2:   Input 1   Input 2

Но если пользователь захочет удалить вторую строку, он вернется в исходное состояние.Я добавил изображения внизу, чтобы показать, что я имею в виду.

Я только начал изучать, как использовать Android Studio, поэтому подумал, что можно просто установить исходные объекты SQLite на 20 столбцов, предполагая, что двастолбцы будут представлять каждый вход каждого испытания, а также предполагать, что они не будут делать ничего, кроме 10 испытаний.Но так как я не знаю, сколько испытаний пользователь будет вводить, если бы у пользователя было больше 10, это было бы проблемой.

Было бы это правильно?Или есть способ для нажатия кнопки «Добавить строку», чтобы динамически добавить два дополнительных столбца в базе данных для каждого ввода.Или мне нужны две разные базы данных, которые сохраняют каждый вход в каждую базу данных с одинаковым идентификатором и получают значения через один и тот же идентификатор первичного ключа?Вот изображения:

Первоначально:

Image 1

После нажатия кнопки:

Image 2

1 Ответ

0 голосов
/ 25 мая 2019

Это было бы правильно? Или есть способ для нажатия кнопки «добавить строку», чтобы динамически добавить два дополнительных столбца в базу данных для каждого ввода.

Возможно, вы захотите рассмотреть не попытку динамического управления списком, а использование ListView для отображения текущих данных вместе с одним набором EditTexts для ввода новых данных.

Или мне нужно два различные базы данных, которые сохраняют каждый вход в каждую базу данных с тот же идентификатор и получить значения через тот же идентификатор первичного ключа?

Между столбцами и базой данных есть таблицы. Таким образом, проблема заключается в добавлении переменного числа испытаний в эксперименты. Затем испытание проводится в эксперименте, так что вы, вероятно, имеете таблицу эксперимента и таблицу испытаний, причем последняя ссылается на эксперимент с одним родителем, к которому относится исследование.

Несколько баз данных. Скорее всего, вы не хотите осложнений, и в этом нет никакой необходимости.

Пример

Вот рабочий пример (хотя он очень простой, особенно в плане компоновки), в котором есть ряд экспериментов, к которым можно добавить испытания. Код добавляет 3 эксперимента для демонстрации, названных Эксперимент 1, Эксперимент 2 и Эксперимент 3.

При первом запуске не будет никаких испытаний ни для одного из экспериментов. Их можно добавить после ввода данных (2 Edit Texts) и нажатия кнопки ADD. Вверху отображается название эксперимента, и при нажатии кнопки СЛЕДУЮЩАЯ будет проходить цикл экспериментов и показываться испытания для эксперимента (если есть).

Количество испытаний на эксперимент не ограничено.

Код

Компоновка

Первый макет activity_main.xml , который имеет

  • название (вездесущий Hello World)
  • два EditTexts и кнопка для добавления новых данных.
  • a ListView для перечисления данных в базе данных.

Код: -

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    >
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        />
    <LinearLayout
        android:layout_marginTop="10dp"
        android:id="@+id/experimentsection"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#FFAAAAFF">

        <TextView
            android:id="@+id/currentexperiment"
            android:layout_width="0dp"
            android:layout_weight="8"
            android:layout_height="wrap_content"
            android:text="No Experiment"/>
        <Button
            android:id="@+id/nextexperiment"
            android:layout_width="0dp"
            android:layout_weight="2"
            android:layout_height="wrap_content"
            android:text="NEXT"/>
    </LinearLayout>
    <LinearLayout
        android:id="@+id/inputsection"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <EditText
            android:id="@+id/input1"
            android:layout_width="0dp"
            android:layout_weight="4"
            android:layout_height="wrap_content"/>
        <EditText
            android:id="@+id/input2"
            android:layout_width="0dp"
            android:layout_weight="4"
            android:layout_height="wrap_content"/>
        <Button
            android:id="@+id/add"
            android:layout_width="0dp"
            android:layout_weight="2"
            android:layout_height="wrap_content"
            android:text="ADD"/>
    </LinearLayout>
    <ListView
        android:id="@+id/currentdata"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    </ListView>
</LinearLayout>

База данных Помощник

Помощник по базам данных DBHelper.java , который определяет одну таблицу с 3 столбцами

  • столбец идентификатора, который однозначно идентифицирует строку.
    • (обратите внимание, что адаптер ListView требует, чтобы это было названо _id)
  • столбцы data1 и data1 для 2 значений будут сохранены

Код: -

public class DBHelper extends SQLiteOpenHelper {

    public static final String DBNAME = "mydb";
    public static final int DBVERSION = 1;

    public static final String TBL_EXPERIMENT = "experiment";
    public static final String COL_ID = BaseColumns._ID;
    public static final String COL_EXPERIMENT_NAME = "experiment_name";

    public static final String TBL_MYTABLE1 = "mytable1";
    public static final String COL_EXPERIMENT_REF = "experiment_ref";
    public static final String COl_DATA1 = "data1";
    public static final String COL_DATA2 = "data2";

    SQLiteDatabase mDB;

    public DBHelper(Context context) {
        super(context, DBNAME, null, DBVERSION);
        mDB = this.getWritableDatabase();
    }

    @Override
    public void onConfigure(SQLiteDatabase db) {
        super.onConfigure(db);
        db.setForeignKeyConstraintsEnabled(true);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("CREATE TABLE IF NOT EXISTS " + TBL_EXPERIMENT + "(" +
                COL_ID + " INTEGER PRIMARY KEY," +
                COL_EXPERIMENT_NAME + " TEXT UNIQUE" +
                ")"
        );
        db.execSQL("CREATE TABLE IF NOT EXISTS " + TBL_MYTABLE1 + "(" +
                COL_ID + " INTEGER PRIMARY KEY," +

                COL_EXPERIMENT_REF + " INTEGER " +
                " REFERENCES " + TBL_EXPERIMENT + "(" +
                COL_ID +
                ")," +

                COl_DATA1 + " TEXT," +
                COL_DATA2 + " TEXT" +
                ")"
        );
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }

    public long addExperiment(String name) {
        ContentValues cv = new ContentValues();
        cv.put(COL_EXPERIMENT_NAME,name);
        return mDB.insert(TBL_EXPERIMENT,null,cv);
    }

    public long addTrial(long expermientId, String data1, String data2) {
        ContentValues cv = new ContentValues();
        cv.put(COL_EXPERIMENT_REF,expermientId);
        cv.put(COl_DATA1,data1);
        cv.put(COL_DATA2,data2);
        return mDB.insert(TBL_MYTABLE1,null ,cv);
    }

    public Cursor getAllRowsForAnExperiment(long experimentId) {
        String whereclause = COL_EXPERIMENT_REF + "=?";
        String[] whereargs = new String[]{String.valueOf(experimentId)};
        return mDB.query(TBL_MYTABLE1,null,whereclause,whereargs,null,null,null);
    }


    public Cursor getAllExperiments() {
        return mDB.query(TBL_EXPERIMENT,null,null,null,null,null,null);
    }

    public int deleteTrial(long id) {
        String whereclause = COL_ID + "=?";
        String[] whereargs = new String[]{String.valueOf(id)};
        return mDB.delete(TBL_MYTABLE1,whereclause,whereargs);
    }
}
  • addRow - метод, используемый для добавления строки данных.
  • getAllRows - метод, используемый для извлечения всех данных.

Активность

Наконец, собрать все вместе - MainActivity.java

public class MainActivity extends AppCompatActivity {

    //Define Class variables
    DBHelper mDBHlpr;
    Cursor mCursor, mExperiments;
    SimpleCursorAdapter mSCA;
    EditText mInput1, mInput2;
    TextView mExperimentName;
    Button mAdd, mNextExperiment;
    ListView mListView;

    long mCurrentExperimentId = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main); // Set the layout to be displayed

        //Instaniate the layout objects to be used
        mExperimentName = this.findViewById(R.id.currentexperiment);
        mNextExperiment = this.findViewById(R.id.nextexperiment);
        mInput1 = this.findViewById(R.id.input1);
        mInput2 = this.findViewById(R.id.input2);
        mAdd = this.findViewById(R.id.add);
        mListView = this.findViewById(R.id.currentdata);

        //Instantiate the Database helper
        mDBHlpr = new DBHelper(this);
        addSomeExperiments();
        mExperiments = mDBHlpr.getAllExperiments();

        // Do the work
        manageExperimentButton();
        manageListView();
        manageAddButton();
    }

    /**
     * Manage the list view,
     * call this anytime the list is to be created (only once)
     * or the list is changed (e.g. after adding)
     */
    private void manageListView() {
        mCursor = mDBHlpr.getAllRowsForAnExperiment(mCurrentExperimentId); // Get the current data

        // If the Adapter hasn't been instantiated do so
        if (mSCA == null) {
            mSCA = new SimpleCursorAdapter(
                    this,
                    android.R.layout.simple_list_item_2,
                    mCursor,
                    new String[]{DBHelper.COl_DATA1, DBHelper.COL_DATA2},
                    new int[]{android.R.id.text1, android.R.id.text2},
                    0
            );
            mListView.setAdapter(mSCA); // Tie the adpater to the listview
            //<<<<<<<<< EXTRA DELETE A ROW WHEN LONG CLICKED >>>>>>>>>>
            mListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
                @Override
                public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
                    if(mDBHlpr.deleteTrial(id) > 0) {
                        Toast.makeText(view.getContext(),"Deleted",Toast.LENGTH_SHORT).show();
                        manageListView();
                    } else {
                        Toast.makeText(view.getContext(),"NOT deleted????",Toast.LENGTH_SHORT).show();
                    }
                    return true; // set this event as having been actioned
                }
            });
        } else {
            // If adapter has been instantiated tell it that the data has changed
            mSCA.swapCursor(mCursor);
        }
    }

    //Handle the Add button by adding an onClick listener
    private void manageAddButton() {
        mAdd.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                //First thing check if there is data to be added
                if (mInput1.getText().toString().length() < 1) {
                    Toast.makeText(v.getContext(),"No data in Input1. Try again",Toast.LENGTH_SHORT).show();
                    mInput1.requestFocus();
                    return;
                }
                if (mInput2.getText().toString().length() < 1) {
                    Toast.makeText(v.getContext(),"No data in Input2. Try again",Toast.LENGTH_SHORT).show();
                    mInput2.requestFocus();
                    return;
                }
                // If there is data to be added, try adding it
                // if the value returned from addRow is less than 1 or more then data was added
                if (mDBHlpr.addTrial(mCurrentExperimentId, mInput1.getText().toString(),mInput2.getText().toString()) > 0) {
                    Toast.makeText(v.getContext(),"Added",Toast.LENGTH_SHORT).show();
                    // As data has been added refresh the ListView
                    manageListView();
                    // and clear the input fields
                    mInput1.setText("");
                    mInput2.setText("");
                    // and finally position the focus on the first input
                    mInput1.requestFocus();
                } else {
                    // Ooops something went wrong (very unlikely with the current db schema)
                    Toast.makeText(v.getContext(),"Not Added????",Toast.LENGTH_SHORT).show();
                }
            }
        });
    }
    private void manageExperimentButton() {
        mExperiments = mDBHlpr.getAllExperiments();
        mExperiments.moveToFirst();
        handleCurrentExperiment();
        mNextExperiment.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
               if(!mExperiments.moveToNext()) {
                   mExperiments.moveToFirst();
               }
                handleCurrentExperiment();
            }
        });
    }

    private void handleCurrentExperiment() {
        mCurrentExperimentId = mExperiments.getLong(mExperiments.getColumnIndex(DBHelper.COL_ID));
        mExperimentName.setText(mExperiments.getString(mExperiments.getColumnIndex(DBHelper.COL_EXPERIMENT_NAME)));
        manageListView();
    }

    //When the activity finishes close the cursor
    @Override
    protected void onDestroy() {
        super.onDestroy();
        mCursor.close();
    }

    //If returning to the activity refresh the ListView
    @Override
    protected void onResume() {
        super.onResume();
        manageListView();
    }

    private void addSomeExperiments() {
        // Add some experiments if none exist
        if(DatabaseUtils.queryNumEntries(mDBHlpr.getWritableDatabase(),DBHelper.TBL_EXPERIMENT) > 0 ) return;
        mDBHlpr.addExperiment("Experiment 1");
        mDBHlpr.addExperiment("Experiment 2");
        mDBHlpr.addExperiment("Experiment 3");
    }
}

Результат

Снимок экрана эксперимента с более чем 20 испытаниями (были добавлены A-Z) (хотя и бесполезная информация). Код также включает в себя удаление испытаний путем длительного нажатия на них в списке (как видно, некоторые из них были удалены, например, пробная версия E была удалена):

enter image description here

Нажав на СЛЕДУЮЩИЙ, вы попадете в Эксперимент 1, в котором меньше испытаний: -

enter image description here

...