Как вставить строку в SQLite в другом потоке и вернуть результат с помощью обработчика? - PullRequest
2 голосов
/ 02 июля 2019

У меня есть операция SQLite DatabaseHelper, которая вставляет строку в локальную базу данных.Я хочу сделать это в другом потоке и использовать обработчик для возврата результата в поток пользовательского интерфейса.Как я могу это сделать?Вот операция:

public void insertEmployee(String employeeType, String employeeName, Double employeeConvRate, String employeeDesc) {

    new Thread(() -> {
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues values = new ContentValues();

        values.put(EXPENSE_C_TYPE, employeeType);
        values.put(EXPENSE_C_NAME, employeeName);
        values.put(EXPENSE_C_CR, employeeConvRate);
        values.put(EXPENSE_C_DESC, employeeDesc);

        long id = db.insert(EXPENSE_TABLE_NAME, null, values);
        db.close();

    }).start();
}

Обычно эта функция является публичной длинной, которая возвращает переменную id.

РЕДАКТИРОВАТЬ - КАК Я ЭТО СДЕЛАЛ:

Я создал этот интерфейс с универсальным параметром:

public interface OnDatabaseResult<T> {
    void onResult(T result);
}

Затем я изменил обработчик внутри операции базы данных:

public void insertEmployee(String employeeType, String employeeName, Double employeeConvRate, String employeeDesc) {

    new Thread(() -> {
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues values = new ContentValues();

        values.put(EXPENSE_C_TYPE, employeeType);
        values.put(EXPENSE_C_NAME, employeeName);
        values.put(EXPENSE_C_CR, employeeConvRate);
        values.put(EXPENSE_C_DESC, employeeDesc);

        long id = db.insert(EXPENSE_TABLE_NAME, null, values);
        db.close();

    handler.post(()) -> onDatabaseResult.onResult(id)

    }).start();
}

Затем в основное действие я добавил функцию, которая создает строку:

public void createEmploye(String employeeType, String employeeName, Double employeeConvRate, String employeeDesc){

     DatabaseHelper databaseHelper = new DatabaseHelper(this);

     databaseHelper.insertEmployee(type, name, rate, desc, new OnDatabaseResult<Long>(){

     @Override
     public void onResult(Long result){
            Employee employee = databaseHelper.getEmployee(result);
            if(employee!=null){
                  employeeList.add(o, employee);
                  employeeAdapter.notifyDataSetChanged();
            }
     }
     });
}

А теперь работает без нареканий.

Ответы [ 2 ]

0 голосов
/ 03 июля 2019

Вы можете использовать Интерфейс .

Ниже приведен пример, основанный на вашем коде, который вставляет строку «Расход» (хотя и в ту же строку, но с другим идентификатором) в другой поток.и отображает вставленный идентификатор.

Интерфейс MyInterface.java просто: -

public interface MyInterface {
    void changeID(long newid);
}

Помощник по базам данных DatabaseHelper.java :-

public class DatabaseHelper extends SQLiteOpenHelper {

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

    public static final String EXPENSE_TABLE_NAME = "expense";
    public static final String EXPENSE_C_ID = BaseColumns._ID;
    public static final String EXPENSE_C_TYPE = "type";
    public static final String EXPENSE_C_NAME = "name";
    public static final String EXPENSE_C_CR = "cr";
    public static final String EXPENSE_C_DESC = "description";


    public DatabaseHelper(Context context) {
        super(context, DBNAME, null, DBVERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("CREATE TABLE IF NOT EXISTS " + EXPENSE_TABLE_NAME + "(" +
                EXPENSE_C_ID + " INTEGER PRIMARY KEY, " +
                EXPENSE_C_TYPE + " TEXT, " +
                EXPENSE_C_NAME + " TEXT," +
                EXPENSE_C_CR + " REAL, " +
                EXPENSE_C_DESC + " TEXT" +
                ")");
    }

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

    }

    public long insertEmployee(String employeeType, String employeeName, Double employeeConvRate, String employeeDesc) {

            SQLiteDatabase db = this.getWritableDatabase();
            ContentValues values = new ContentValues();

            values.put(EXPENSE_C_TYPE, employeeType);
            values.put(EXPENSE_C_NAME, employeeName);
            values.put(EXPENSE_C_CR, employeeConvRate);
            values.put(EXPENSE_C_DESC, employeeDesc);

            long id = db.insert(EXPENSE_TABLE_NAME, null, values);
            db.close();
            return id;
    }
}
  • Обратите внимание, что метод insertEmployee специально не запускается в другом потоке (таким образом, он более гибкий).

Макетдля действия activity_main.xml является очень простым TextView для отображения идентификатора (изначально установленного в Hello World) и имеет кнопку, которая при нажатии вставляет новую строку: -

<?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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/result"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!" />

    <Button
        android:id="@+id/doit"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="DO IT"/>

</LinearLayout>

Наконец MainActivity.java : -

public class MainActivity extends AppCompatActivity implements MyInterface {

    TextView mShowResult;       // TextView to display the latest id (initially Hello World)
    Button mDoIt;               // The Button, when clicked inserts a new row
    DatabaseHelper mDBHlpr;     // The Database Helper

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mShowResult = this.findViewById(R.id.result); // Get the TextView for the dispaly
        mDoIt = this.findViewById(R.id.doit); // Get the Button

        mDBHlpr = new DatabaseHelper(this); // Instantiate the Database Helper
        // Set the Buttons onClick Listener
        mDoIt.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                doItInAnotherThread("Full time", "Fred",32.897,"Worker"); //<<<<<<<<<<<
            }
        });
    }

    /**
     * As MainActivity implements MyInterface which has the changeID template
     * the changeID method must be implemented. This will be called when the doItInAnotherThread calls
     * changeID(?).
     *
     * As this is updating a view then it must be run on the UI thread
     */
    public void changeID(final long newid) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                mShowResult.setText(String.valueOf(newid));
            }
        });
    }

    /**
     * Do the work in another thread returning changed id via the interface MyInterface
     */
    private void doItInAnotherThread(final String employeeType, final String employeeName, final Double employeeConvRate, final String employeeDesc) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                long id = mDBHlpr.insertEmployee(employeeType, employeeName, employeeConvRate, employeeDesc);
                changeID(id);
            }
        }).start();
    }
}

Результаты

1.При первом запуске: -

enter image description here

2.При нажатии кнопки DO IT (вместо Hello World на дисплее отображается 1 )

enter image description here

0 голосов
/ 02 июля 2019

попробуйте это

        new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    SQLiteDatabase db = this.getWritableDatabase();
                    ContentValues values = new ContentValues();

                    values.put(EXPENSE_C_TYPE, employeeType);
                    values.put(EXPENSE_C_NAME, employeeName);
                    values.put(EXPENSE_C_CR, employeeConvRate);
                    values.put(EXPENSE_C_DESC, employeeDesc);

                    long id = db.insert(EXPENSE_TABLE_NAME, null, values);
                    db.close();
                }
            }, 100);
...