简体   繁体   中英

How to implement ASyncTask in my code for database operations

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM