Koumintang
Koumintang

Reputation: 13

Need Help Refreshing my database ListView in my app

My app layout apparently isn't a normal layout so I a having trouble setting my List Adapter to auto updated when an edit is made.

I make my edits to my database in this Java File which is controlled in its own activity and layout.

    public void onClick(View view){
    if (view == findViewById(R.id.addsave)) {
        RecipeRepo repo = new RecipeRepo(this);
        Recipe recipe = new Recipe();
        if (editTextName.getText().toString().equals("")) {
            editTextName.setError("Recipe name required!");
            return;
        } else {
            recipe.name = editTextName.getText().toString();
        }
        if (textImagePath.getText().toString().equals("") ) {
            recipe.image = ("");
        }else{
            recipe.image = textImagePath.getText().toString();
        }
        recipe.category = staticSpinner.getSelectedItem().toString();
        if (editTextIngredients.getText().toString().equals("")) {
            editTextIngredients.setError("Ingredient required!");
            return;
        } else {
            recipe.ingredients = editTextIngredients.getText().toString();
        }
        if (editTextInstruct.getText().toString().equals("")) {
            editTextIngredients.setError("Instruction required!");
            return;
        } else {
            recipe.instructions = editTextInstruct.getText().toString();
        }
        recipe.cooktemp = editTextCookTemp.getText().toString();
        recipe.cooktime = editTextCookTime.getText().toString();
        recipe.serves = editTextServings.getText().toString();
        recipe.recipe_Id = _Recipe_Id;

        if (_Recipe_Id == 0) {
            _Recipe_Id = repo.insert(recipe);

            Toast.makeText(this, "New Recipe Added", Toast.LENGTH_SHORT).show();
            finish();

it actually inserts and updates in this java file

    int insert(Recipe recipe){

    //Open connection to write data
    SQLiteDatabase db = dbHelper.getWritableDatabase();
    ContentValues values = new ContentValues();
    values.put(Recipe.KEY_SERVES, recipe.serves);
    values.put(Recipe.KEY_COOKTIME, recipe.cooktime);
    values.put(Recipe.KEY_COOKTEMP, recipe.cooktemp);
    values.put(Recipe.KEY_INSTRUCT, recipe.instructions);
    values.put(Recipe.KEY_INGREDIENTS, recipe.ingredients);
    values.put(Recipe.KEY_CATEGORY, recipe.category);
    values.put(Recipe.KEY_IMAGE, recipe.image);
    values.put(Recipe.KEY_NAME, recipe.name);

    //Inserting Row
    long recipe_Id = db.insert(Recipe.TABLE, null, values);
    db.close();// Closing database connection
    return (int) recipe_Id;
}

void delete(int recipe_Id){

    SQLiteDatabase db = dbHelper.getWritableDatabase();
    db.delete(Recipe.TABLE, Recipe.KEY_ID + "=?", new String[] {String.valueOf(recipe_Id)});
    db.close();
}

void update(Recipe recipe){

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

    values.put(Recipe.KEY_SERVES, recipe.serves);
    values.put(Recipe.KEY_COOKTIME, recipe.cooktime);
    values.put(Recipe.KEY_COOKTEMP, recipe.cooktemp);
    values.put(Recipe.KEY_INSTRUCT, recipe.instructions);
    values.put(Recipe.KEY_INGREDIENTS, recipe.ingredients);
    values.put(Recipe.KEY_CATEGORY, recipe.category);
    values.put(Recipe.KEY_IMAGE, recipe.image);
    values.put(Recipe.KEY_NAME, recipe.name);

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

and lastly it gets put into the list view from this Java file and separate layout. Which is where my adapters are but i cannot get the notifyDataSetChanged() to work here at all... as in it wont even come up.

     public boolean onNavigationItemSelected(MenuItem item) {
    // Handle navigation view item clicks here.
    int id = item.getItemId();
    RecipeRepo repo = new RecipeRepo(this);

    if (id == R.id.nav_meat) {

        final ArrayList<HashMap<String, String>> recipeList = repo.getRecipeMeat();


        if(recipeList.size()!=0) {
            ListView lv = (ListView) findViewById(R.id.list);
            lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                    recipe_Id = (TextView) view.findViewById(R.id.recipe_Id);
                    String recipeId = recipe_Id.getText().toString();
                    Intent objIndent = new Intent(getApplicationContext(), RecipeDetail.class);
                    objIndent.putExtra("recipe_Id", Integer.parseInt(recipeId));
                    startActivity(objIndent);
                }
            });
            ListAdapter adapter = new SimpleAdapter(SousChef.this, recipeList, R.layout.view_recipe_entry, new String[]{"id", "category", "name"}, new int[]{R.id.recipe_Id, R.id.recipe_list_category, R.id.recipe_list_name});
            lv.setAdapter(adapter);
        }else {
            Toast.makeText(this, "No recipe!", Toast.LENGTH_SHORT).show();
        }
    } else if (id == R.id.nav_veg) {

        final ArrayList<HashMap<String, String>> recipeList = repo.getRecipeVeg();
        if(recipeList.size()!=0) {
            ListView lv = (ListView) findViewById(R.id.list);
            lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                    recipe_Id = (TextView) view.findViewById(R.id.recipe_Id);
                    String recipeId = recipe_Id.getText().toString();
                    Intent objIndent = new Intent(getApplicationContext(), RecipeDetail.class);
                    objIndent.putExtra("recipe_Id", Integer.parseInt(recipeId));
                    startActivity(objIndent);
                }
            });
            ListAdapter adapter = new SimpleAdapter(SousChef.this, recipeList, R.layout.view_recipe_entry, new String[]{"id", "category", "name"}, new int[]{R.id.recipe_Id, R.id.recipe_list_category, R.id.recipe_list_name});
            lv.setAdapter(adapter);

        }else {
            Toast.makeText(this, "No recipe!", Toast.LENGTH_SHORT).show();
        }

So any advise on setting this up to automatically update would be a huge help. I have been racking my brain over this for a couple days now looking at different examples and what not, but no setup is quite like this one which doesnt allow me to have everything in one file.

And thank you in advance.

category picking image: Category picking Image

Upvotes: 0

Views: 61

Answers (2)

ArtiomLK
ArtiomLK

Reputation: 2260

There are for sure more answers but this is one that might help,

Quick Example for the proposed solution

SHORT EXPLANATION

inside MainActivity

//create a public static adapter
public static ListAdapter adapter

inside onCreateView()

//Create your adapter and set it to the right ListView
ListView lv = findViewById(R.id.listView_in_xml);
adapter = new SimpleAdapter(...)
lv.setAdapter(adapter)

inside CustomAdapter which in your case I assume is SimpleAdapter

//add a public method to be called so that the Adapter updates and displays the new data
public void updateMethod(){
   //update your List<Recipe> that I would guess you have calling the database again 
   //if needed update your getCount() return value so that it returns the number of childs in your ListView which most of the cases is just the List<Recipe>.size()
   //notifyDataSetChanged()
}

inside your DB HANDLER CLASS

//in every update, add, delete or any method that requires the ListView to Update just call the created method,
MainActivity.CustomAdapter.updateMethod();

PROBLEMS

You will have to make sure the public static adapter has been initialized and is not null, or simply check whether the adapter is not null and update, because if the adapter is null that activity has not launched yet thus no need to trigger the updateMethod().

OTHER SOLUTIONS

Instead of creating a public static adapter create a public static boolean, then whenever data changes set that boolean to true from the database. Finally, whenever you resume your activity check against that boolean and update your ListViewAdapter if needed.

MORE COMPLICATED SOLUTIONS WHICH I KNOW WORK CAUSE I USE IT

Use TaskAsyncTaskLoader which utilizes a Loader in your MainActivity and implements LoaderManager.LoaderCallbacks.

Optionally, you can make the Loader be, public static Loaderand inside your DBHandler you trigger the loader to load the data again or use any other logic you want.

Proofs of Working suggested solution, enter image description here

Upvotes: 1

phpdroid
phpdroid

Reputation: 1663

You can Broadcast Intent from the change database file after you get the response in the onCreate() of adapter loading class

    Intent intent = new Intent("key_to_identify_the_broadcast");
    Bundle bundle = new Bundle();
    bundle.putString("edttext", "changed");
    intent.putExtra("bundle_key_for_intent", bundle);
    context.sendBroadcast(intent);

and then you can receive the bundle in your fragment by using the BroadcastReceiver class

private final BroadcastReceiver mHandleMessageReceiver = new 
BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        Bundle bundle = 
            intent.getExtras().getBundle("bundle_key_for_intent");
            if(bundle!=null){
                String edttext = bundle.getString("edttext");
            }
            //you can call any of your methods for using this bundle for your use case
    }
};

in onCreate() of your adapter adding class you need to register the broadcast receiver first otherwise this broadcast receiver will not be triggered

IntentFilter filter = new IntentFilter("key_to_identify_the_broadcast");
getActivity().getApplicationContext().
               registerReceiver(mHandleMessageReceiver, filter);

Finally you can unregister the receiver to avoid any exceptions

@Override
public void onDestroy() {
    try {

         getActivity().getApplicationContext().
             unregisterReceiver(mHandleMessageReceiver);

    } catch (Exception e) {
        Log.e("UnRegister Error", "> " + e.getMessage());
    }
    super.onDestroy();
}

Upvotes: 0

Related Questions