From ce2c548e5b93dbc39b7baa6f48c4a66beb64e3c0 Mon Sep 17 00:00:00 2001 From: Geoffroy Bonneville Date: Thu, 21 Dec 2023 14:46:53 +0100 Subject: [PATCH] Replace AsyncTasks with TaskRunner Some refactoring --- .../fragments/TaskListsDialogFragment.java | 66 +++++++++--------- .../fragments/TodayFormDialogFragment.java | 56 +++++++-------- .../donext/helpers/TaskTouchHelper.java | 17 ++--- .../donext/repositories/TaskRepository.java | 68 ------------------- .../geoffroy/donext/utils/TaskRunner.java | 29 ++++++++ 5 files changed, 94 insertions(+), 142 deletions(-) delete mode 100644 app/src/main/java/com/wismna/geoffroy/donext/repositories/TaskRepository.java create mode 100644 app/src/main/java/com/wismna/geoffroy/donext/utils/TaskRunner.java diff --git a/app/src/main/java/com/wismna/geoffroy/donext/fragments/TaskListsDialogFragment.java b/app/src/main/java/com/wismna/geoffroy/donext/fragments/TaskListsDialogFragment.java index 85bc28e..ea8d079 100644 --- a/app/src/main/java/com/wismna/geoffroy/donext/fragments/TaskListsDialogFragment.java +++ b/app/src/main/java/com/wismna/geoffroy/donext/fragments/TaskListsDialogFragment.java @@ -2,7 +2,6 @@ package com.wismna.geoffroy.donext.fragments; import android.content.Context; import android.content.SharedPreferences; -import android.os.AsyncTask; import android.os.Bundle; import android.view.View; import android.widget.Button; @@ -21,9 +20,10 @@ import com.wismna.geoffroy.donext.adapters.TaskListRecyclerViewAdapter; import com.wismna.geoffroy.donext.dao.TaskList; import com.wismna.geoffroy.donext.database.TaskListDataAccess; import com.wismna.geoffroy.donext.helpers.TaskListTouchHelper; +import com.wismna.geoffroy.donext.utils.TaskRunner; -import java.lang.ref.WeakReference; import java.util.List; +import java.util.concurrent.Callable; /** * A fragment representing a list of Items. @@ -64,7 +64,24 @@ public class TaskListsDialogFragment extends DynamicDialogFragment implements mContentLayoutId = R.layout.content_tasklists; taskListDataAccess = new TaskListDataAccess(getContext(), TaskListDataAccess.MODE.WRITE); - new GetTaskListsTask(this).execute(taskListDataAccess); + + Context context = getContext(); + TaskRunner taskRunner = new TaskRunner(); + taskRunner.executeAsync(new GetTaskLists(context), (taskLists) -> { + taskListRecyclerViewAdapter = new TaskListRecyclerViewAdapter(taskLists, this); + + // Set the adapter + RecyclerView recyclerView = findViewById(R.id.task_lists_view); + recyclerView.setLayoutManager(new LinearLayoutManager(context)); + recyclerView.setAdapter(taskListRecyclerViewAdapter); + + // Set the Touch Helper + ItemTouchHelper.Callback callback = new TaskListTouchHelper(taskListRecyclerViewAdapter); + mItemTouchHelper = new ItemTouchHelper(callback); + mItemTouchHelper.attachToRecyclerView(recyclerView); + + toggleVisibleCreateNewTaskListLayout(); + }); } @Override @@ -122,7 +139,7 @@ public class TaskListsDialogFragment extends DynamicDialogFragment implements private void toggleVisibleCreateNewTaskListLayout() { LinearLayout layout = findViewById(R.id.new_task_list_layout); int taskListCount = taskListRecyclerViewAdapter.getItemCount(); - SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getContext()); + SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(requireContext()); String maxTaskListsString = sharedPref.getString("pref_conf_max_lists", "5"); int maxTaskLists = Integer.parseInt(maxTaskListsString); if (taskListCount >= maxTaskLists) layout.setVisibility(View.GONE); @@ -137,7 +154,7 @@ public class TaskListsDialogFragment extends DynamicDialogFragment implements @Override public void onClickDeleteButton(int position, long id) { - SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getContext()); + SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(requireContext()); if(sharedPref.getBoolean("pref_conf_tasklist_del", true)) { String title = getResources().getString(R.string.task_list_confirmation_delete); @@ -160,7 +177,7 @@ public class TaskListsDialogFragment extends DynamicDialogFragment implements CheckBox neverAskAgainCheckBox = dialog.getDialog().findViewById(R.id.task_confirmation_never); if (neverAskAgainCheckBox.isChecked()) { - SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getContext()); + SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(requireContext()); SharedPreferences.Editor editor = sharedPref.edit(); editor.putBoolean("pref_conf_tasklist_del", false); @@ -192,39 +209,18 @@ public class TaskListsDialogFragment extends DynamicDialogFragment implements toggleVisibleCreateNewTaskListLayout(); } - private static class GetTaskListsTask extends AsyncTask> { - private final WeakReference fragmentReference; + static class GetTaskLists implements Callable> { + private final Context context; - GetTaskListsTask(TaskListsDialogFragment context) { - fragmentReference = new WeakReference<>(context); + public GetTaskLists(Context context) { + this.context = context; } @Override - protected List doInBackground(TaskListDataAccess... params) { - TaskListDataAccess taskListDataAccess = params[0]; - return taskListDataAccess.getTaskLists(false); - } - - @Override - protected void onPostExecute(List taskLists) { - super.onPostExecute(taskLists); - TaskListsDialogFragment fragment = fragmentReference.get(); - if (fragment == null) return; - fragment.taskListRecyclerViewAdapter = - new TaskListRecyclerViewAdapter(taskLists, fragment); - - // Set the adapter - Context context = fragment.getContext(); - RecyclerView recyclerView = fragment.findViewById(R.id.task_lists_view); - recyclerView.setLayoutManager(new LinearLayoutManager(context)); - recyclerView.setAdapter(fragment.taskListRecyclerViewAdapter); - - // Set the Touch Helper - ItemTouchHelper.Callback callback = new TaskListTouchHelper(fragment.taskListRecyclerViewAdapter); - fragment.mItemTouchHelper = new ItemTouchHelper(callback); - fragment.mItemTouchHelper.attachToRecyclerView(recyclerView); - - fragment.toggleVisibleCreateNewTaskListLayout(); + public List call() { + try(TaskListDataAccess taskListDataAccess = new TaskListDataAccess(context)) { + return taskListDataAccess.getTaskLists(false); + } } } } diff --git a/app/src/main/java/com/wismna/geoffroy/donext/fragments/TodayFormDialogFragment.java b/app/src/main/java/com/wismna/geoffroy/donext/fragments/TodayFormDialogFragment.java index 07efce8..3e846c0 100644 --- a/app/src/main/java/com/wismna/geoffroy/donext/fragments/TodayFormDialogFragment.java +++ b/app/src/main/java/com/wismna/geoffroy/donext/fragments/TodayFormDialogFragment.java @@ -1,25 +1,26 @@ package com.wismna.geoffroy.donext.fragments; import android.content.Context; -import android.os.AsyncTask; import android.os.Bundle; -import androidx.annotation.Nullable; import android.text.Editable; import android.text.TextWatcher; import android.view.View; import android.widget.EditText; import android.widget.ListView; +import androidx.annotation.Nullable; + import com.wismna.geoffroy.donext.R; import com.wismna.geoffroy.donext.adapters.TodayArrayAdapter; import com.wismna.geoffroy.donext.dao.Task; import com.wismna.geoffroy.donext.database.TaskDataAccess; +import com.wismna.geoffroy.donext.utils.TaskRunner; import org.joda.time.LocalDate; -import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.Callable; /** * Created by bg45 on 2017-03-21. @@ -53,7 +54,9 @@ public class TodayFormDialogFragment extends DynamicDialogFragment { mNegativeButtonString = getString(R.string.new_task_cancel); mContentLayoutId = R.layout.content_today_form; // Load the tasks asynchronously - new LoadTasks(this).execute(getActivity()); + //new LoadTasks(this).execute(getActivity()); + TaskRunner taskRunner = new TaskRunner(); + taskRunner.executeAsync(new LoadTasks(getContext()), this::setLayoutValues); } private void setLayoutValues(List tasks) { @@ -94,7 +97,8 @@ public class TodayFormDialogFragment extends DynamicDialogFragment { protected void onPositiveButtonClick(View view) { mListener.onTodayTaskDialogPositiveClick(view); // Only commit the updated tasks to DB - new UpdateTasks(this).execute(mUpdatedTasks.toArray(new Task[0])); + TaskRunner taskRunner = new TaskRunner(); + taskRunner.executeAsync(new UpdateTasks(getContext(), mUpdatedTasks.toArray(new Task[0])), (position) -> mListener.onTodayTasksUpdated()); dismiss(); } @@ -108,50 +112,40 @@ public class TodayFormDialogFragment extends DynamicDialogFragment { dismiss(); } - static class LoadTasks extends AsyncTask> { - private final WeakReference fragmentReference; + static class LoadTasks implements Callable> { + private final Context context; - LoadTasks(TodayFormDialogFragment context) { - fragmentReference = new WeakReference<>(context); + public LoadTasks(Context context) { + this.context = context; } @Override - protected List doInBackground(Context... params) { - try(TaskDataAccess taskDataAccess = new TaskDataAccess(params[0])) { + public List call() { + try(TaskDataAccess taskDataAccess = new TaskDataAccess(context)) { return taskDataAccess.getAllTasks(); } } - - @Override - protected void onPostExecute(List tasks) { - super.onPostExecute(tasks); - fragmentReference.get().setLayoutValues(tasks); - } } - private static class UpdateTasks extends AsyncTask { - private final WeakReference fragmentReference; + static class UpdateTasks implements Callable { + private final Context context; + private final Task[] tasks; - UpdateTasks(TodayFormDialogFragment context) { - fragmentReference = new WeakReference<>(context); + public UpdateTasks(Context context, Task[] tasks) { + this.context = context; + this.tasks = tasks; } @Override - protected Integer doInBackground(Task... params) { + public Integer call() { int position; - try (TaskDataAccess taskDataAccess = new TaskDataAccess(fragmentReference.get().getActivity(), TaskDataAccess.MODE.WRITE)) { - for (position = 0; position < params.length; position ++) { - Task task = params[position]; + try (TaskDataAccess taskDataAccess = new TaskDataAccess(context, TaskDataAccess.MODE.WRITE)) { + for (position = 0; position < tasks.length; position ++) { + Task task = tasks[position]; taskDataAccess.updateTodayTasks(task.getId(), task.isToday(), position); } } return position; } - - @Override - protected void onPostExecute(Integer integer) { - super.onPostExecute(integer); - fragmentReference.get().mListener.onTodayTasksUpdated(); - } } } diff --git a/app/src/main/java/com/wismna/geoffroy/donext/helpers/TaskTouchHelper.java b/app/src/main/java/com/wismna/geoffroy/donext/helpers/TaskTouchHelper.java index 50524ea..cee3bdf 100644 --- a/app/src/main/java/com/wismna/geoffroy/donext/helpers/TaskTouchHelper.java +++ b/app/src/main/java/com/wismna/geoffroy/donext/helpers/TaskTouchHelper.java @@ -4,14 +4,15 @@ import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; -import androidx.annotation.NonNull; -import androidx.recyclerview.widget.RecyclerView; -import androidx.recyclerview.widget.ItemTouchHelper; import android.text.Layout; import android.text.StaticLayout; import android.text.TextPaint; import android.view.View; +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.ItemTouchHelper; +import androidx.recyclerview.widget.RecyclerView; + import com.wismna.geoffroy.donext.R; /** @@ -24,8 +25,8 @@ public class TaskTouchHelper extends ItemTouchHelper.SimpleCallback { } private final TaskTouchHelperAdapter mAdapter; - private int colorRight; - private int colorLeft; + private final int colorRight; + private final int colorLeft; public TaskTouchHelper(TaskTouchHelperAdapter adapter, int colorRight, int colorLeft){ // No drag moves, no swipes (except for 1st element, see getSwipeDirs method) @@ -37,8 +38,8 @@ public class TaskTouchHelper extends ItemTouchHelper.SimpleCallback { @Override public int getSwipeDirs(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) { - // Allow both directions swiping on first item, only left on the others - if (viewHolder.getAdapterPosition() == 0) + // Allow both directions swiping on first item, none on the others + if (viewHolder.getAbsoluteAdapterPosition() == 0) return ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT; else return super.getSwipeDirs(recyclerView, viewHolder); } @@ -50,7 +51,7 @@ public class TaskTouchHelper extends ItemTouchHelper.SimpleCallback { @Override public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) { - mAdapter.onItemSwiped(viewHolder.getAdapterPosition(), direction); + mAdapter.onItemSwiped(viewHolder.getAbsoluteAdapterPosition(), direction); } @Override diff --git a/app/src/main/java/com/wismna/geoffroy/donext/repositories/TaskRepository.java b/app/src/main/java/com/wismna/geoffroy/donext/repositories/TaskRepository.java deleted file mode 100644 index bccff95..0000000 --- a/app/src/main/java/com/wismna/geoffroy/donext/repositories/TaskRepository.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.wismna.geoffroy.donext.repositories; - -import android.app.Application; -import android.os.AsyncTask; - -import com.wismna.geoffroy.donext.data.AppDatabase; -import com.wismna.geoffroy.donext.data.Task; -import com.wismna.geoffroy.donext.data.TaskDao; - -import java.util.List; - -import androidx.lifecycle.LiveData; - -public class TaskRepository { - private TaskDao mTaskDao; - - TaskRepository(Application application) { - AppDatabase db = AppDatabase.getDatabase(application); - mTaskDao = db.taskDao(); - } - - public void insert(Task task) { - new insertAsyncTask(mTaskDao).execute(task); - } - - public void update(Task task) { - new updateAsyncTask(mTaskDao).execute(task); - } - - public LiveData> getTasksInList(long taskId) { - return mTaskDao.getAllTasksFromList(taskId); - } - - public LiveData> getTodayTasks() { - return mTaskDao.getTodayTasks(); - } - - // Async tasks - private static class insertAsyncTask extends AsyncTask { - - private TaskDao mAsyncTaskDao; - - insertAsyncTask(TaskDao dao) { - mAsyncTaskDao = dao; - } - - @Override - protected Void doInBackground(final Task... params) { - mAsyncTaskDao.createTask(params[0]); - return null; - } - } - - private static class updateAsyncTask extends AsyncTask { - - private TaskDao mAsyncTaskDao; - - updateAsyncTask(TaskDao dao) { - mAsyncTaskDao = dao; - } - - @Override - protected Void doInBackground(final Task... params) { - mAsyncTaskDao.updateTask(params[0]); - return null; - } - } -} diff --git a/app/src/main/java/com/wismna/geoffroy/donext/utils/TaskRunner.java b/app/src/main/java/com/wismna/geoffroy/donext/utils/TaskRunner.java new file mode 100644 index 0000000..bf92f33 --- /dev/null +++ b/app/src/main/java/com/wismna/geoffroy/donext/utils/TaskRunner.java @@ -0,0 +1,29 @@ +package com.wismna.geoffroy.donext.utils; + +import android.os.Handler; +import android.os.Looper; + +import java.util.concurrent.Callable; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; + +public class TaskRunner { + private final Executor executor = Executors.newSingleThreadExecutor(); + private final Handler handler = new Handler(Looper.getMainLooper()); + + public interface Callback { + void onComplete(R result); + } + + public void executeAsync(Callable callable, Callback callback) { + executor.execute(() -> { + final R result; + try { + result = callable.call(); + } catch (Exception e) { + throw new RuntimeException(e); + } + handler.post(() -> callback.onComplete(result)); + }); + } +}