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);
}
}
}
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();
}
}
}