Search code examples
javaandroidandroid-recyclerviewsharedpreferences

After deleting item 1 in the recyclerview when clicking on item 2 it doesn't show anything ( onClick opens Activity where there is a recyclerv items)


So I'm trying to make an app where there is a button + and when clicking it , it shows an AlertDialog with a text "Workout Name:" and EditText with hint " Enter workout name ". When writing down the workout name and clicking the positive button " Add ", it adds an item to the recyclerview. There is onClick method for the items in the recyclerview and when clicking on a "Workout" it opens similar activity , but this time when clicking the " + " you are adding an exercise associated to this " Workout ". I've added some exercises and then created another "workout" and added different exercises to it, when deleting the first "workout" i want to delete only the exercises associated to it and to not touch the second one , unfortunatelly when i delete "Workout 1" it deletes the exercises in "Workout 2" aswell. I'm using SharedPreferences for saving the information and tried to use HashMap for the exercises , it's now day 2 and I really can't find the answer by myself. This is the code of the first activity:

public class FitNotes extends AppCompatActivity implements WorkoutInterface {
RecyclerView recyclerView;
Button btnAddWorkout;
TextView txtViewInstructions;
List<WorkoutItem> workoutList;
WorkoutAdapter recyclerViewAdapter;

private static final String WORKOUT_LIST_KEY = "workoutList";

private Map<String, List<WorkoutExerciseItem>> exercisesMap;

private static final String EXERCISES_MAP_KEY = "EXERCISES_MAP"; // Define the key for exercisesMap


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    getSupportActionBar().hide();
    setContentView(R.layout.activity_fit_notes);

    recyclerView = findViewById(R.id.recycler_workout);
    btnAddWorkout = findViewById(R.id.btnAddWorkout);
    txtViewInstructions = findViewById(R.id.txtViewInstructions);

    workoutList = new ArrayList<>();

    recyclerViewAdapter = new WorkoutAdapter(this, workoutList, this);

    recyclerView.setAdapter(recyclerViewAdapter);
    recyclerView.setLayoutManager(new LinearLayoutManager(this));

    ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new FitNotes.SwipeToDeleteCallback());
    itemTouchHelper.attachToRecyclerView(recyclerView);

    updateInstructionsVisibility();

    loadData();
    loadExercisesMap();
    btnAddWorkout.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            showAddWorkoutDialog();
        }
    });
}
private void showAddWorkoutDialog() {
    AlertDialog.Builder builder = new AlertDialog.Builder(this, R.style.AlertDialogBackground);
    LayoutInflater inflater = getLayoutInflater();
    View dialogView = inflater.inflate(R.layout.dialog_add_workout, null);
    builder.setView(dialogView);

    final EditText workoutNameEditText = dialogView.findViewById(R.id.editText_workout_name);

    builder.setPositiveButton("Add", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            String workoutName = workoutNameEditText.getText().toString().trim();
            
            if (!workoutName.isEmpty()) {
                workoutList.add(new WorkoutItem(workoutName)); 
                Log.d("WorkoutList", "Workout added: " + workoutName);
                recyclerViewAdapter.notifyDataSetChanged(); 


                exercisesMap.put(workoutName, new ArrayList<>());

                saveData();
                saveExercisesMap();

                updateInstructionsVisibility();
            }
            dialog.dismiss();
        }
    });

    builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            dialog.dismiss();
        }
    });

    AlertDialog dialog = builder.create();
    dialog.setOnShowListener(new DialogInterface.OnShowListener() {
        @Override
        public void onShow(DialogInterface dialogInterface) {
            Button positiveButton = ((AlertDialog) dialog).getButton(DialogInterface.BUTTON_POSITIVE);
            Button negativeButton = ((AlertDialog) dialog).getButton(DialogInterface.BUTTON_NEGATIVE);

            positiveButton.setTextColor(getResources().getColor(R.color.white)); 
            negativeButton.setTextColor(getResources().getColor(R.color.white));


        }
    });
    WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
    layoutParams.copyFrom(dialog.getWindow().getAttributes());
    layoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT; 
    layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT; 
    dialog.getWindow().setAttributes(layoutParams);

    dialog.show();
}

private class SwipeToDeleteCallback extends ItemTouchHelper.SimpleCallback {
    SwipeToDeleteCallback() {
        super(0, ItemTouchHelper.LEFT);
    }
    @Override
    public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
        return false;
    }
    @Override
    public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
        
        int position = viewHolder.getAdapterPosition();

        
        WorkoutItem deletedWorkout = workoutList.get(position);
        Log.d("SwipedWorkout", "Deleting workout: " + deletedWorkout.getName()); 

        workoutList.remove(position);
        recyclerViewAdapter.notifyItemRemoved(position);
        deleteWorkout(deletedWorkout.getName());
        saveData();
        saveExercisesMap();
        recyclerViewAdapter.notifyItemRangeChanged(position, workoutList.size());
        updateInstructionsVisibility();
    }
}
public void deleteWorkout(String workoutName) {
    Iterator<WorkoutItem> iterator = workoutList.iterator();
    while (iterator.hasNext()) {
        WorkoutItem workoutItem = iterator.next();
        if (workoutItem.getName().equals(workoutName)) {
            iterator.remove();

            if (exercisesMap.containsKey(workoutName)) {
                exercisesMap.remove(workoutName); 
                Log.d("deleteWorkout", "Exercises removed for workout: " + workoutName);
            } else {
                Log.e("deleteWorkout", "No exercises found for workout: " + workoutName);
            }

            saveData();
            saveExercisesMap();
            updateInstructionsVisibility();
            break;
        }
    }
}

private void saveData() {
    SharedPreferences sharedPreferences = getSharedPreferences("MyUserPrefs", MODE_PRIVATE);
    SharedPreferences.Editor editor = sharedPreferences.edit();

    Gson gson = new Gson();
    String json = gson.toJson(workoutList);

    editor.putString(WORKOUT_LIST_KEY, json);
    editor.apply();
    Log.d("SaveData", "WorkoutList saved to SharedPreferences: " + json);

}

private void loadData() {
    SharedPreferences sharedPreferences = getSharedPreferences("MyUserPrefs", MODE_PRIVATE);
    Gson gson = new Gson();
    String json = sharedPreferences.getString(WORKOUT_LIST_KEY, "");

    Type type = new TypeToken<List<WorkoutItem>>(){}.getType();
    workoutList = gson.fromJson(json, type);

    if (workoutList == null) {
        workoutList = new ArrayList<>();
    }
    recyclerViewAdapter = new WorkoutAdapter(this, workoutList, this);

    recyclerView.setAdapter(recyclerViewAdapter);
    updateInstructionsVisibility();
    Log.d("LoadData", "WorkoutList loaded from SharedPreferences: " + json);

}
private void updateInstructionsVisibility() {
    if (workoutList.isEmpty()) {
        txtViewInstructions.setVisibility(View.VISIBLE); // Show textViewInstructions
    } else {
        txtViewInstructions.setVisibility(View.GONE); // Hide textViewInstructions
    }
}

private void loadExercisesMap() {
    SharedPreferences sharedPreferences = getSharedPreferences("MyUserPrefs", MODE_PRIVATE);
    Gson gson = new Gson();
    String json = sharedPreferences.getString(EXERCISES_MAP_KEY, "");

    Type type = new TypeToken<Map<String, List<WorkoutExerciseItem>>>(){}.getType();
    exercisesMap = gson.fromJson(json, type);

    if (exercisesMap == null) {
        exercisesMap = new HashMap<>();
    }
    Log.d("LoadExercisesMap", "ExercisesMap loaded from SharedPreferences: " + json);

}

private void saveExercisesMap() {
    SharedPreferences sharedPreferences = getSharedPreferences("MyUserPrefs", MODE_PRIVATE);
    SharedPreferences.Editor editor = sharedPreferences.edit();

    Gson gson = new Gson();
    String json = gson.toJson(exercisesMap);

    editor.putString(EXERCISES_MAP_KEY, json);
    editor.apply();
}

@Override
public void onWorkoutClick(int position) {
    if (position >= 0 && position < workoutList.size()) {
        String workoutName = workoutList.get(position).getName();

        // Handle the clicked workout
        if (exercisesMap.containsKey(workoutName)) {
            List<WorkoutExerciseItem> exercises = exercisesMap.get(workoutName);
            Log.d("WorkoutClick", "Exercises found for workout: " + workoutName + ", Exercise count: " + exercises.size());


            Intent intent = new Intent(FitNotes.this, Workout.class);
            intent.putExtra("WORKOUT_NAME", workoutName);
            startActivity(intent);
        } else {
            Log.e("FitNotes", "Workout not found in exercisesMap: " + workoutName);
        }
        } else {
        // Handle out-of-bounds index or other scenarios
        Log.e("FitNotes", "Invalid workout item clicked");
        }
     }
}

And this is my next Activity :

public class Workout extends AppCompatActivity {
Button btnAddExercise;
RecyclerView recyclerView;
List<WorkoutExerciseItem> exerciseList;
TextView textViewWorkoutName, textViewInstructions;
WorkoutExerciseAdapter recyclerViewAdapter;
Map<String, List<WorkoutExerciseItem>> exercisesMap;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    getSupportActionBar().hide();
    setContentView(R.layout.activity_workout);

    btnAddExercise = findViewById(R.id.btnAddExercise);
    recyclerView = findViewById(R.id.recycler_workoutExercise);
    textViewWorkoutName = findViewById(R.id.textView_workoutName);
    textViewInstructions = findViewById(R.id.textViewInstructions);

    String selectedWorkoutName = getIntent().getStringExtra("WORKOUT_NAME");

    textViewWorkoutName.setText(selectedWorkoutName);

    exerciseList = new ArrayList<>();


    exercisesMap = loadExercisesMap();
    exercisesMap = loadExercisesMap();

    if (exercisesMap == null) {
        exercisesMap = new HashMap<>();
    }


    exerciseList = exercisesMap.get(selectedWorkoutName);
    if (exerciseList == null) {
        exerciseList = new ArrayList<>();
        exercisesMap.put(selectedWorkoutName, exerciseList);
    }


    recyclerViewAdapter = new WorkoutExerciseAdapter(this, exerciseList);

    recyclerView.setAdapter(recyclerViewAdapter);
    recyclerView.setLayoutManager(new LinearLayoutManager(this));

    ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new Workout.SwipeToDeleteCallback());
    itemTouchHelper.attachToRecyclerView(recyclerView);

    updateInstructionsVisibility(exerciseList);
    loadExercisesMap();
    btnAddExercise.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            showAddExerciseDialog();
        }
    });
}
private void showAddExerciseDialog(){
    AlertDialog.Builder builder = new AlertDialog.Builder(this, R.style.AlertDialogBackground);
    LayoutInflater inflater = getLayoutInflater();
    View dialogView = inflater.inflate(R.layout.dialog_add_workout, null);
    builder.setView(dialogView);

    final EditText exerciseNameEditText = dialogView.findViewById(R.id.editText_workout_name);

    builder.setPositiveButton("Add", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            String exerciseName = exerciseNameEditText.getText().toString().trim();
            if (!exerciseName.isEmpty()){

                exerciseList.add(new WorkoutExerciseItem(exerciseName)); 
                recyclerViewAdapter.notifyDataSetChanged(); 

                saveExercisesMap(exercisesMap);
                updateInstructionsVisibility(exerciseList);

            }
            dialog.dismiss();
        }
    });
    builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener(){
       @Override
       public void onClick(DialogInterface dialog, int which){
           dialog.dismiss();
       }
    });

    AlertDialog dialog = builder.create();
    dialog.setOnShowListener(new DialogInterface.OnShowListener() {
        @Override
        public void onShow(DialogInterface dialogInterface) {
            Button positiveButton = ((AlertDialog) dialog).getButton(DialogInterface.BUTTON_POSITIVE);
            Button negativeButton = ((AlertDialog) dialog).getButton(DialogInterface.BUTTON_NEGATIVE);

            positiveButton.setTextColor(getResources().getColor(R.color.white)); 
            negativeButton.setTextColor(getResources().getColor(R.color.white)); 


        }
    });
    WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
    layoutParams.copyFrom(dialog.getWindow().getAttributes());
    layoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT; 
    layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT; 
    dialog.getWindow().setAttributes(layoutParams);

    dialog.show();
}

private class SwipeToDeleteCallback extends ItemTouchHelper.SimpleCallback {
    SwipeToDeleteCallback() {
        super(0, ItemTouchHelper.LEFT);
    }
    @Override
    public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
        return false;
    }
    @Override
    public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
        int position = viewHolder.getAdapterPosition();

        exerciseList.remove(position);
        recyclerViewAdapter.notifyItemRemoved(position);

        saveExercisesMap(exercisesMap);
        updateInstructionsVisibility(exerciseList);
    }
}

private void saveExercisesMap(Map<String, List<WorkoutExerciseItem>> exercisesMap) {
    SharedPreferences sharedPreferences = getSharedPreferences("MyUserPrefs", MODE_PRIVATE);
    SharedPreferences.Editor editor = sharedPreferences.edit();

    Gson gson = new Gson();
    String json = gson.toJson(exercisesMap);

    editor.putString("EXERCISES_MAP", json);
    editor.apply();
}

private Map<String, List<WorkoutExerciseItem>> loadExercisesMap() {
    SharedPreferences sharedPreferences = getSharedPreferences("MyUserPrefs", MODE_PRIVATE);
    Gson gson = new Gson();
    String json = sharedPreferences.getString("EXERCISES_MAP", "");

    Type type = new TypeToken<Map<String, List<WorkoutExerciseItem>>>() {}.getType();
    return gson.fromJson(json, type);
}
private void updateInstructionsVisibility(List<WorkoutExerciseItem> exerciseList) {
    if (exerciseList.isEmpty()) {
        textViewInstructions.setVisibility(View.VISIBLE);
    } else {
        textViewInstructions.setVisibility(View.GONE);
    }
  }
}

Solution

  • Worked when i changed to ROOM database:

    public class Workout extends AppCompatActivity implements ExerciseInterface {
    Button btnAddExercise;
    RecyclerView recyclerView;
    TextView textViewWorkoutName, textViewInstructions;
    ExerciseAdapter recyclerViewAdapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_workout);
    
        btnAddExercise = findViewById(R.id.btnAddExercise);
        textViewWorkoutName = findViewById(R.id.textView_workoutName);
        textViewInstructions = findViewById(R.id.textViewInstructions);
    
        String selectedWorkoutName = getIntent().getStringExtra("WORKOUT_NAME");
    
        textViewWorkoutName.setText(selectedWorkoutName);
    
        btnAddExercise.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                showAddExerciseDialog();
            }
        });
        initRecyclerView();
        loadExerciseList();
        updateInstructionsVisibility();
        recyclerViewAdapter.setExerciseInterface(this);
    
    }
    @Override
    public void onItemClick(ExerciseItem exerciseItem) {
        Intent intent = new Intent(Workout.this, Exercise.class);
        intent.putExtra("EXERCISE_NAME", exerciseItem.getExerciseName()); // Pass workout details
        intent.putExtra("EXERCISE_ID", exerciseItem.getId());
        startActivity(intent);
    }
    private void showAddExerciseDialog(){
        AlertDialog.Builder builder = new AlertDialog.Builder(this, R.style.AlertDialogBackground);
        LayoutInflater inflater = getLayoutInflater();
        View dialogView = inflater.inflate(R.layout.dialog_add_exercise, null);
        builder.setView(dialogView);
    
        final EditText exerciseNameEditText = dialogView.findViewById(R.id.editText_exercise_name);
    
        builder.setPositiveButton("Add", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                String exerciseName = exerciseNameEditText.getText().toString().trim();
                if (!exerciseName.isEmpty()){
                    int workoutId = getIntent().getIntExtra("WORKOUT_ID",-1);
                    if (workoutId != -1) {
                    saveNewExercise(exerciseName,workoutId);
                    loadExerciseList();
                    recyclerViewAdapter.notifyDataSetChanged();
                    updateInstructionsVisibility();
                    } else {
    
                    }
                }
                dialog.dismiss();
            }
        });
        builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener(){
            @Override
            public void onClick(DialogInterface dialog, int which){
                dialog.dismiss();
            }
        });
    
        AlertDialog dialog = builder.create();
        dialog.setOnShowListener(new DialogInterface.OnShowListener() {
            @Override
            public void onShow(DialogInterface dialogInterface) {
                Button positiveButton = ((AlertDialog) dialog).getButton(DialogInterface.BUTTON_POSITIVE);
                Button negativeButton = ((AlertDialog) dialog).getButton(DialogInterface.BUTTON_NEGATIVE);
    
                positiveButton.setTextColor(getResources().getColor(R.color.white));
                negativeButton.setTextColor(getResources().getColor(R.color.white));
    
    
            }
        });
        WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
        layoutParams.copyFrom(dialog.getWindow().getAttributes());
        layoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
        layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
        dialog.getWindow().setAttributes(layoutParams);
    
        dialog.show();
    }
    private void updateInstructionsVisibility() {
        if (recyclerViewAdapter.getItemCount() == 0) {
            textViewInstructions.setVisibility(View.VISIBLE);
        } else {
            textViewInstructions.setVisibility(View.GONE);
        }
    }
    private void deleteItem(ExerciseItem exerciseItem) {
    
        AppDatabase database = AppDatabase.getInstance(this.getApplicationContext());
        database.exerciseDao().delete(exerciseItem);
        recyclerViewAdapter.removeExerciseItem(exerciseItem);
    
    }
    private void saveNewExercise(String exerciseName, int workoutId) {
        AppDatabase database = AppDatabase.getInstance(this.getApplicationContext());
        workoutId = getIntent().getIntExtra("WORKOUT_ID", -1);
        try {
        WorkoutItem workoutItem = database.workoutDao().getWorkoutById(workoutId);
            if (workoutItem != null) {
            // The workoutId exists, proceed with saving ExerciseItem
            ExerciseItem exerciseItem = new ExerciseItem();
            exerciseItem.exerciseName = exerciseName;
            exerciseItem.workoutId = workoutId;
            database.exerciseDao().insertExerciseItem(exerciseItem);
        } else {
    
        }
        } catch (Exception e) {
            e.printStackTrace();
    
        }
    }
    public void initRecyclerView() {
        recyclerView = findViewById(R.id.recycler_exercise);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(this, DividerItemDecoration.VERTICAL);
        recyclerView.addItemDecoration(dividerItemDecoration);
        recyclerViewAdapter = new ExerciseAdapter(this);
        recyclerView.setAdapter(recyclerViewAdapter);
    
        ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new Workout.SwipeToDeleteCallback());
        itemTouchHelper.attachToRecyclerView(recyclerView);
    }
    private void loadExerciseList() {
        AppDatabase database = AppDatabase.getInstance(this.getApplicationContext());
        int selectedWorkoutId = getIntent().getIntExtra("WORKOUT_ID", -1);
        if (selectedWorkoutId != -1) {
            // Fetch exercises associated with the selected workout ID
            List<ExerciseItem> exercisesForWorkout = database.exerciseDao().getExercisesForWorkout(selectedWorkoutId);
            recyclerViewAdapter.setExerciseList(exercisesForWorkout);
            recyclerViewAdapter.notifyDataSetChanged();
        } else {
            Log.e("WorkoutActivity", "No workout ID found in the intent");
        }
    }
    private class SwipeToDeleteCallback extends ItemTouchHelper.SimpleCallback {
        SwipeToDeleteCallback() {
            super(0, ItemTouchHelper.LEFT);
        }
        @Override
        public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
            return false;
        }
        @Override
        public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
    
            int position = viewHolder.getAdapterPosition();
            ExerciseItem deletedItem = recyclerViewAdapter.getExerciseList().get(position);
            deleteItem(deletedItem);
            updateInstructionsVisibility();
        }
    }
    

    }