I have this SQLite DatabaseHelper operation that inserts a row into the local database. I want to do this on a different thread and use handler to take the result back to the UI Thread. How can I do this? Here is the operation:
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();
}
Usually this function is a public long that returns the id variable.
EDIT - HOW I DID IT:
I created this interface with generic parameter:
public interface OnDatabaseResult<T> {
void onResult(T result);
}
Then I aded the handler inside the database operation:
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();
}
Then in main activity I added the function that creates the row:
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();
}
}
});
}
And now it works flawlessly.
You can use an Interface.
The following is an example based upon your code, that inserts an Expense row (albeit the same row but with a different id) on another thread and displays the inserted id.
The interface MyInterface.java is simply :-
public interface MyInterface {
void changeID(long newid);
}
The Database Helper DatabaseHelper.java is :-
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;
}
}
The layout for the activity, activity_main.xml is very simple a TextView for displaying the id (initially set to Hello World) and has a button that when clicked inserts the new row:-
<?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>
Finally 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();
}
}