简体   繁体   中英

Passing an object through Activities (Android)

For my software engineering class, we have to incorporate an SQLite database into our application project.

For our application this database class has to be accessible from multiple activities. I have turned the Database class into a singleton and then call

DBInterface database = Database.getInstance(this)

to set a variable to reference the database in order to access its methods in each necessary class and it works. However, we are supposed to utilize dependency injections into our code and my professor has specifically told us that it should be possible to switch from our database class to a stub database we used in a previous iteration by only changing one line of code.

Obviously this means changing the above to

DBInterface database = StubDB.getInstance(this)

However in doing this I still have to make this change in each of the activities that uses the database methods.

So my question is this: is there a way to initialize my database in our init activity and then pass a reference to each necessary activity without the assignment code above?

Relevant Code

Singleton Database Class

public class RecipeDatabase extends Activity implements DBInterface {
    private dbHelper Helper;
    private static RecipeDatabase sInstance;
    private static Context sContext;

    public static synchronized RecipeDatabase getInstance(Context context){
        if(sInstance == null){
            sInstance = new RecipeDatabase(context.getApplicationContext());
        }
        return sInstance;
    }

    private RecipeDatabase(Context context){
        Helper = new dbHelper(context);
        sContext = context;
    }

    @Override
    public void addRecipe(Recipe recipe)
    {
        String ingredients = recipe.ingredientString();
        String directions = recipe.directionString();


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

        values.put(Recipe.KEY_rID, recipe.getrID());
        values.put(Recipe.KEY_mealtype, recipe.getMealType());
        values.put(Recipe.KEY_mainingredient, recipe.getMainIngredient());
        values.put(Recipe.KEY_description, recipe.getDescription());
        values.put(Recipe.KEY_ingredients, ingredients);
        values.put(Recipe.KEY_directions, directions);
        values.put(Recipe.KEY_notes, recipe.getNotes());
        values.put(Recipe.KEY_rating, recipe.getRating());
        values.put(Recipe.KEY_cooktime, recipe.getCooktime());

        db.insert(Recipe.TABLE, null, values);

        db.close();
    }

    @Override
    public void editRecipe(Recipe recipe)
    {
        SQLiteDatabase db = Helper.getWritableDatabase();
        ContentValues values = new ContentValues();
        String ingredients = recipe.ingredientString();
        String directions = recipe.directionString();

        values.put(Recipe.KEY_rID, recipe.getrID());
        values.put(Recipe.KEY_mealtype, recipe.getMealType());
        values.put(Recipe.KEY_mainingredient, recipe.getMainIngredient());
        values.put(Recipe.KEY_description, recipe.getDescription());
        values.put(Recipe.KEY_ingredients, ingredients);
        values.put(Recipe.KEY_directions, directions);
        values.put(Recipe.KEY_notes, recipe.getNotes());
        values.put(Recipe.KEY_rating, recipe.getRating());
        values.put(Recipe.KEY_cooktime, recipe.getCooktime());

        db.update(Recipe.TABLE, values, Recipe.KEY_rID + " = ?", new String[]{String.valueOf(recipe.getrID())});
        db.close();
    }

    @Override
    public void deleteRecipe(Recipe recipe)
    {
        SQLiteDatabase db = Helper.getWritableDatabase();

        db.delete(Recipe.TABLE, Recipe.KEY_rID + " = ", new String[]{String.valueOf(recipe.getrID())});
        db.close();
    }

    public ArrayList<Recipe> getList()
    {
        ArrayList<Recipe> result = new ArrayList<>();

        SQLiteDatabase db = Helper.getReadableDatabase();

        String selectQuery = "SELECT " + Recipe.KEY_rID + ", " +
                Recipe.KEY_name + ", " +
                Recipe.KEY_mealtype + ", " +
                Recipe.KEY_mainingredient + ", " +
                Recipe.KEY_description + ", " +
                Recipe.KEY_ingredients + ", " +
                Recipe.KEY_directions + ", " +
                Recipe.KEY_notes + ", " +
                Recipe.KEY_rating + ", " +
                Recipe.KEY_cooktime + " FROM " + Recipe.TABLE;

        Cursor cursor = db.rawQuery(selectQuery, null);

        if(cursor.moveToFirst()) {
            do {
                ArrayList<String> ingredients = new ArrayList<>(); // Temp Storage
                ArrayList<String> directions = new ArrayList<>(); // Temp Storage

                String tempIngredient = cursor.getString(cursor.getColumnIndex(Recipe.KEY_ingredients));
                String[] temp = tempIngredient.split("- "); //Split up ingredients to individual strings

                for(int x=0; x < temp.length; x++) {
                    ingredients.add(temp[x]);
                }

                String tempDirection = cursor.getString(cursor.getColumnIndex(Recipe.KEY_ingredients));
                temp = tempDirection.split("- ");//split up directions into individual strings

                for(int x=0; x < temp.length; x++) {
                    directions.add(temp[x]);
                }
                //Get Values for Recipe Object
                int rID = cursor.getInt(cursor.getColumnIndex(Recipe.KEY_rID));
                String name = cursor.getString(cursor.getColumnIndex(Recipe.KEY_name));
                String mealType = cursor.getString(cursor.getColumnIndex(Recipe.KEY_mealtype));
                String mainIngredient = cursor.getString(cursor.getColumnIndex(Recipe.KEY_mainingredient));
                int rating = cursor.getInt(cursor.getColumnIndex(Recipe.KEY_rating));
                String description = cursor.getString(cursor.getColumnIndex(Recipe.KEY_description));
                int cooktime = cursor.getInt(cursor.getColumnIndex(Recipe.KEY_cooktime));
                String notes = cursor.getString(cursor.getColumnIndex(Recipe.KEY_notes));

                //Create new Recipe from Row
                Recipe tempRecipe = new Recipe(rID, name, description, mealType, mainIngredient,
                rating, cooktime, notes, ingredients, directions);

                //Add the recipe to the ArrayList
                result.add(tempRecipe);

            }while (cursor.moveToNext());
        }
        //Return the populated ArrayList for use
        return result;
    }
}

Init Class

public class init extends ListActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_init);

        //The code to change to switch from stub to database
        DBInterface repository = RecipeDatabase.getInstance(this);
        //DBInterface repository = new StubDB(this);

        ArrayList<Recipe> recipes = repository.getList();
        ArrayList<String> recipeDisplay = new ArrayList<>();
        for(int i=0; i<recipes.size(); i++) {
            recipeDisplay.add(recipes.get(i).getName());
        }

        ArrayAdapter<String> myArrayAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, recipeDisplay);
        ListView lv = this.getListView();
        lv.setAdapter(myArrayAdapter);
    }

    @Override
    protected void onListItemClick(ListView l, View v, int pos, long id){
        super.onListItemClick(l, v, pos, id);

        Intent myIntent = new Intent(this, Details.class);
        myIntent.putExtra("recipePosition", pos);
        startActivity(myIntent);
    }

    public void shoppingListButton(View view){
        startActivity(new Intent(this, ShoppingList.class));
    }

    public void addRecipeButton(View view){
        Intent myIntent = new Intent(this, Edit.class);
        myIntent.putExtra("editType", 1); // 1 corresponds to add recipe
        startActivity(myIntent);
    }
}

One of the Activity Classes that needs the DB methods

public class Details extends ListActivity {
    int recipePosition = 0;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_details);
        //want to avoid this call 
        DBInterface repository = RecipeDatabase.getInstance(this);
        recipePosition = getIntent().getIntExtra("recipePosition", 0);
        Recipe clickedRecipe = repository.getList().get(recipePosition);
        ArrayList<String> recipeDetails = new ArrayList<>();
        recipeDetails.add(clickedRecipe.getName());
        recipeDetails.add(clickedRecipe.getDescription());
        recipeDetails.add("Ingredients:");
        for(int i=0; i<clickedRecipe.getIngredients().size(); i++){
            recipeDetails.add(clickedRecipe.getIngredients().get(i));
        }
        recipeDetails.add("Instructions:");
        for(int i=0; i<clickedRecipe.getDirections().size(); i++){
            recipeDetails.add(clickedRecipe.getDirections().get(i));
        }
        ArrayAdapter<String> myArrayAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, recipeDetails);
        ListView lv = this.getListView();
        lv.setAdapter(myArrayAdapter);
    }
    public void editButton(View view){
        Intent myIntent = new Intent(this, Edit.class);
        myIntent.putExtra("recipePosition", recipePosition);
        myIntent.putExtra("editType", 2); // 2 corresponds to modify recipe
        startActivity(myIntent);
    }
}

Database Helper Class

public class dbHelper extends SQLiteOpenHelper {

    private static final int DATABASE_VERSION = 1;

    private static final String DATABASE_NAME = "ROSE.db";

    public dbHelper(Context context){
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db){
        //Creates the Recipe Table which stores recipes
        String CREATE_TABLE_RECIPES = "CREATE TABLE " + Recipe.TABLE  +
                "(" + Recipe.KEY_rID + " INTEGER PRIMARY KEY, " +
                Recipe.KEY_name + " TEXT, " +
                Recipe.KEY_mealtype + " TEXT, " +
                Recipe.KEY_mainingredient + " TEXT, " +
                Recipe.KEY_description + " TEXT, " +
                Recipe.KEY_ingredients + " TEXT, " +
                Recipe.KEY_directions + " TEXT, " +
                Recipe.KEY_notes + " TEXT, " +
                Recipe.KEY_rating + " INTEGER, " +
                Recipe.KEY_cooktime + " INTEGER )";
        db.execSQL(CREATE_TABLE_RECIPES);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
    {
        db.execSQL("DROP TABLE IF EXISTS recipes" );
        onCreate(db);
    }
}

Dagger2 is the perfect thing for you. It's really easy to use, just follow the instructions they provide in the docs and you'll love it once you figure it out.

Basically you're going to use

@Inject
DBInterface database;

In every activity, fragment, service, or anywhere you wanna use the database. Then you will create a DatabaseModule which will have a method that provides the database for injection.

@Singleton
@Provides static DBInterface provideDatabase() {
      return new WhateverDatabaseImplementsDBInterface();
}

As you can see, just adding @Singleton will make it a singleton. And now changing the database you use is truly a one line change.

Dagger2 is the greatest thing you will encounter for dependency injection for sure, just setup it correctly, write if you have any trouble (but you shouldn't, with their thorough instructions).

You can use the SQLiteOpenHelper . It will make sure all your activities access the same database. Even if you have different database helper objects in each Activity, they all access the same database.

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