英文:
How to implement ASyncTask in my code for database operations
问题
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();
}
});
}
}
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 {
// ... (other code)
//---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;
}
}
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);
}
}
英文:
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.
答案1
得分: 0
这就是异步任务(async task)的工作原理。
假设您想要从编辑文本框发送姓名、用户名和密码到按钮点击时的 PHP 脚本
在主活动中:
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) {
// ...
}
});
deleteBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// ...
}
});
}
public class BackgroundThread extends AsyncTask<String, Void, Void> {
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected Void doInBackground(String... strings) {
// ...
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
}
}
}
请查看此链接,它将帮助您深入了解异步任务操作:点击查看链接
我向您展示了如何从主线程发送数据到扩展异步任务的类。因此,您需要在 doInBackground
方法中处理数据。如果要将数据存储在数据库中,可以在其中进行处理,并监听事件,例如成功或失败。然后将事件传递到 onPostExecute
方法以更新主线程。例如,如果我要将数据发送到数据库,我首先会在主线程中从编辑文本框获取值,然后将这些值从主线程传递给异步任务,然后在异步任务中执行与数据库的连接、数据存储、监听成功或失败事件以及从数据库获取响应(布尔值、JSON 或字符串),然后将其传递给 postExecute
以更新界面。希望这解释清楚了一切。还有一件事,请确保您了解如何从主线程传递值到异步任务,例如对象、ArrayList、字符串等,因为一旦您理解了这一点,异步任务会变得更加容易。
英文:
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 e.g 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. e.g OBJECTS, ARRAYLIST STRINgs and etc.. because its easier on async task once you understand
专注分享java语言的经验与见解,让所有开发者获益!
评论