I have an Android Studio program (in Java) that collects data from the user and then allows them to either a) input that data into a table by pressing the Add button, or b) Delete that information from the table (if it's already in there) by pressing the Delete button. It's not amazing, but it's practice and it works. The issue is that I want to make those operations happen in a background thread instead of the UI thread.
I can't seem to figure out how exactly to go about doing that. All of the proposed solutions I've found either aren't applicable to my situation or I tried to implement them and failed (or they didn't work; I can't tell the difference with my current skill level). Help would be greatly appreciated. Relevant files below. (Note that I removed the package names from the code here because they have my real name in them, but they are in the actual files).
DataEntryForm.java (this is where my Add and Delete buttons are, as well as their onClick methods)
import android.app.Activity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.Spinner;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class DataEntryForm extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_data_entry_form);
final Spinner spinner = findViewById(R.id.categorySelect);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,
R.array.categories_Array, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
final DBAdapter db = new DBAdapter(this);
db.open();
final EditText recipeNameInput = findViewById(R.id.recipeNameInput);
final Spinner categorySelect = findViewById(R.id.categorySelect);
final EditText ingredientsInput = findViewById(R.id.ingredientsInput);
final EditText instructionsInput = findViewById(R.id.instructionsInput);
Button addBtn = findViewById(R.id.addBtn);
Button deleteBtn = findViewById(R.id.deleteBtn);
addBtn.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v) {
new BackgroundThread().execute();
String editRecipeName = recipeNameInput.getText().toString();
String chooseCategory = categorySelect.getSelectedItem().toString();
String editIngredients = ingredientsInput.getText().toString();
String editInstructions = instructionsInput.getText().toString();
db.insertRecipeChoice(editRecipeName, chooseCategory, editIngredients, editInstructions);
Toast.makeText(DataEntryForm.this, "Recipe added!", Toast.LENGTH_LONG).show();
}
});
deleteBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new BackgroundThread().execute();
if (db.deleteChoice(1))
Toast.makeText(DataEntryForm.this, "Recipe deleted!", Toast.LENGTH_LONG).show();
else
Toast.makeText(DataEntryForm.this, "Recipe deletion failed!",
Toast.LENGTH_LONG).show();
}
}
);
}
}
Notice that there's a "new BackgroundThread.execute()" line in there from one of my previous attempts to make this work. I left it in for now in case it turns out that was the right idea. I don't want it to slip away.
DBAdapter.java
import android.content.ContentValues;
import android.content.Context;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
public class DBAdapter extends AppCompatActivity{
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.adapter_db);
}
static final String KEY_ROWID = "_id";
static final String KEY_RECIPENAME = "RecipeName";
static final String KEY_CATEGORY = "Category";
static final String KEY_INGREDIENTS = "Ingredients";
static final String KEY_INSTRUCTIONS = "Instructions";
static final String TAG = "DBAdapter";
static final String DATABASE_NAME = "MyDB";
static final String DATABASE_TABLE = "MyChoices";
static final int DATABASE_VERSION = 1;
static final String DATABASE_CREATE = "create table MyChoices (_id integer primary key autoincrement, " + "RecipeName text not null, category text not null, ingredients text not null, instructions text not null);";
final Context context;
DatabaseHelper DBHelper;
SQLiteDatabase db;
public DBAdapter(Context ctx) {
this.context = ctx;
DBHelper = new DatabaseHelper(context);
}
private static class DatabaseHelper extends SQLiteOpenHelper {
DatabaseHelper(Context context)
{
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
try {
db.execSQL(DATABASE_CREATE);
} catch (SQLException e) {
e.printStackTrace();
}
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.w(TAG, "Upgrading database from version " + oldVersion + " to " + newVersion + ", which will destroy all old data");
db.execSQL("DROP TABLE IF EXISTS MyChoices");
onCreate(db);
}
}
//---opens the database----
public DBAdapter open() throws SQLException {
db = DBHelper.getWritableDatabase();
return this;
}
//---closes the database----
public void close() {
DBHelper.close();
}
//---insert a recipe choice into the database---
public long insertRecipeChoice(String recipeName, String category, String ingredients, String instructions) {
ContentValues initialValues = new ContentValues();
initialValues.put(KEY_RECIPENAME, recipeName);
initialValues.put(KEY_CATEGORY, category);
initialValues.put(KEY_INGREDIENTS, ingredients);
initialValues.put(KEY_INSTRUCTIONS, instructions);
return db.insert(DATABASE_TABLE, null, initialValues);
}
//---deletes a particular recipe choice---
public boolean deleteChoice(long rowId) {
return db.delete(DATABASE_TABLE, KEY_ROWID + "=" + rowId, null) > 0;
}
}
BackgroundThread.java This is mostly empty because I just got lost trying to figure out whether I need this separate class or not, and if so, what I'm supposed to put here.
import android.content.Context;
import android.os.AsyncTask;
public class BackgroundThread extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... voids) {
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
}
}
Please let me know if there's anything else I need to include to get an answer to this question, but I think those are the relevant files. Everything else doesn't touch or affect the table or data.
so this is how async task work
lets say you want to send a name, username, and password from editTexts to php script on action of button click
In the In the Main Activity
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.Spinner;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class DataEntryForm extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_data_entry_form);
final Spinner spinner = findViewById(R.id.categorySelect);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,
R.array.categories_Array, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
final DBAdapter db = new DBAdapter(this);
db.open();
final EditText recipeNameInput = findViewById(R.id.recipeNameInput);
final Spinner categorySelect = findViewById(R.id.categorySelect);
final EditText ingredientsInput = findViewById(R.id.ingredientsInput);
final EditText instructionsInput = findViewById(R.id.instructionsInput);
Button addBtn = findViewById(R.id.addBtn);
Button deleteBtn = findViewById(R.id.deleteBtn);
addBtn.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v) {
String editRecipeName = recipeNameInput.getText().toString();
String chooseCategory = categorySelect.getSelectedItem().toString();
String editIngredients = ingredientsInput.getText().toString();
String editInstructions = instructionsInput.getText().toString();
// declare an array of string
String[] edittextdata = new String[4];
edittextdata[0] = editRecipeName;
edittextdata[1] = chooseCategory;
edittextdata[2] = editIngredients;
edittextdata[3] = editInstructions;
new BackgroundThread().execute(edittextdata);
db.insertRecipeChoice(editRecipeName, chooseCategory, editIngredients, editInstructions);
Toast.makeText(DataEntryForm.this, "Recipe added!", Toast.LENGTH_LONG).show();
}
});
deleteBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new BackgroundThread().execute();
if (db.deleteChoice(1))
Toast.makeText(DataEntryForm.this, "Recipe deleted!", Toast.LENGTH_LONG).show();
else
Toast.makeText(DataEntryForm.this, "Recipe deletion failed!",
Toast.LENGTH_LONG).show();
}
}
);
}
//to send data or add data to your databse be it sqlite or mysql sql script via Async task
public class BackgroundThread extends AsyncTask<String, Void, Void>{
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected Void doInBackground(String... strings) {
//inside on do in background get the data passed from above contained inside editxt data
String recipeName = strings[0];
/*.
.
.
. get all the arguments
*/
//Here you can do anything with the strings be it calculations and return results on post execute
//or network operations
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
}
}
Check out this link..it will help you alot on understanding the async task operations check this one out
what i have showed you upto there is just sending data you want to process from from the Main thread to class extending async task. So what you need to do is in the doinbackground method process the data, if you are storing it in the DB do it there and listen for events eg if success or failed then pass the events either in boolean string i or integer to the onpostexecute to update the Main thread. For example if i was sending data to db, i would first get the values from edit texts in the Main thread, then pass those value from main to async task, then in the async task, perfom the connections to databse, store data,listen for success or fail event and get the response from DB either boolean or JSOn or string, then pass that to postExecute to update the UI. hoope that clears everything. and one more thing, please make sure you understand on how to pass value from main to async task. eg OBJECTS, ARRAYLIST STRINgs and etc.. because its easier on async task once you understand
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.