Replace AsyncTasks with TaskRunner

Some refactoring
This commit is contained in:
Geoffroy Bonneville
2023-12-21 14:46:53 +01:00
parent 9471318a8a
commit ce2c548e5b
5 changed files with 94 additions and 142 deletions

View File

@@ -2,7 +2,6 @@ package com.wismna.geoffroy.donext.fragments;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.view.View; import android.view.View;
import android.widget.Button; 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.dao.TaskList;
import com.wismna.geoffroy.donext.database.TaskListDataAccess; import com.wismna.geoffroy.donext.database.TaskListDataAccess;
import com.wismna.geoffroy.donext.helpers.TaskListTouchHelper; 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.List;
import java.util.concurrent.Callable;
/** /**
* A fragment representing a list of Items. * A fragment representing a list of Items.
@@ -64,7 +64,24 @@ public class TaskListsDialogFragment extends DynamicDialogFragment implements
mContentLayoutId = R.layout.content_tasklists; mContentLayoutId = R.layout.content_tasklists;
taskListDataAccess = new TaskListDataAccess(getContext(), TaskListDataAccess.MODE.WRITE); 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 @Override
@@ -122,7 +139,7 @@ public class TaskListsDialogFragment extends DynamicDialogFragment implements
private void toggleVisibleCreateNewTaskListLayout() { private void toggleVisibleCreateNewTaskListLayout() {
LinearLayout layout = findViewById(R.id.new_task_list_layout); LinearLayout layout = findViewById(R.id.new_task_list_layout);
int taskListCount = taskListRecyclerViewAdapter.getItemCount(); int taskListCount = taskListRecyclerViewAdapter.getItemCount();
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getContext()); SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(requireContext());
String maxTaskListsString = sharedPref.getString("pref_conf_max_lists", "5"); String maxTaskListsString = sharedPref.getString("pref_conf_max_lists", "5");
int maxTaskLists = Integer.parseInt(maxTaskListsString); int maxTaskLists = Integer.parseInt(maxTaskListsString);
if (taskListCount >= maxTaskLists) layout.setVisibility(View.GONE); if (taskListCount >= maxTaskLists) layout.setVisibility(View.GONE);
@@ -137,7 +154,7 @@ public class TaskListsDialogFragment extends DynamicDialogFragment implements
@Override @Override
public void onClickDeleteButton(int position, long id) { 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)) { if(sharedPref.getBoolean("pref_conf_tasklist_del", true)) {
String title = getResources().getString(R.string.task_list_confirmation_delete); 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); CheckBox neverAskAgainCheckBox = dialog.getDialog().findViewById(R.id.task_confirmation_never);
if (neverAskAgainCheckBox.isChecked()) { if (neverAskAgainCheckBox.isChecked()) {
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getContext()); SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(requireContext());
SharedPreferences.Editor editor = sharedPref.edit(); SharedPreferences.Editor editor = sharedPref.edit();
editor.putBoolean("pref_conf_tasklist_del", false); editor.putBoolean("pref_conf_tasklist_del", false);
@@ -192,39 +209,18 @@ public class TaskListsDialogFragment extends DynamicDialogFragment implements
toggleVisibleCreateNewTaskListLayout(); toggleVisibleCreateNewTaskListLayout();
} }
private static class GetTaskListsTask extends AsyncTask<TaskListDataAccess, Void, List<TaskList>> { static class GetTaskLists implements Callable<List<TaskList>> {
private final WeakReference<TaskListsDialogFragment> fragmentReference; private final Context context;
GetTaskListsTask(TaskListsDialogFragment context) { public GetTaskLists(Context context) {
fragmentReference = new WeakReference<>(context); this.context = context;
} }
@Override @Override
protected List<TaskList> doInBackground(TaskListDataAccess... params) { public List<TaskList> call() {
TaskListDataAccess taskListDataAccess = params[0]; try(TaskListDataAccess taskListDataAccess = new TaskListDataAccess(context)) {
return taskListDataAccess.getTaskLists(false); return taskListDataAccess.getTaskLists(false);
} }
@Override
protected void onPostExecute(List<TaskList> 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();
} }
} }
} }

View File

@@ -1,25 +1,26 @@
package com.wismna.geoffroy.donext.fragments; package com.wismna.geoffroy.donext.fragments;
import android.content.Context; import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.Nullable;
import android.text.Editable; import android.text.Editable;
import android.text.TextWatcher; import android.text.TextWatcher;
import android.view.View; import android.view.View;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ListView; import android.widget.ListView;
import androidx.annotation.Nullable;
import com.wismna.geoffroy.donext.R; import com.wismna.geoffroy.donext.R;
import com.wismna.geoffroy.donext.adapters.TodayArrayAdapter; import com.wismna.geoffroy.donext.adapters.TodayArrayAdapter;
import com.wismna.geoffroy.donext.dao.Task; import com.wismna.geoffroy.donext.dao.Task;
import com.wismna.geoffroy.donext.database.TaskDataAccess; import com.wismna.geoffroy.donext.database.TaskDataAccess;
import com.wismna.geoffroy.donext.utils.TaskRunner;
import org.joda.time.LocalDate; import org.joda.time.LocalDate;
import java.lang.ref.WeakReference;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.Callable;
/** /**
* Created by bg45 on 2017-03-21. * Created by bg45 on 2017-03-21.
@@ -53,7 +54,9 @@ public class TodayFormDialogFragment extends DynamicDialogFragment {
mNegativeButtonString = getString(R.string.new_task_cancel); mNegativeButtonString = getString(R.string.new_task_cancel);
mContentLayoutId = R.layout.content_today_form; mContentLayoutId = R.layout.content_today_form;
// Load the tasks asynchronously // 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<Task> tasks) { private void setLayoutValues(List<Task> tasks) {
@@ -94,7 +97,8 @@ public class TodayFormDialogFragment extends DynamicDialogFragment {
protected void onPositiveButtonClick(View view) { protected void onPositiveButtonClick(View view) {
mListener.onTodayTaskDialogPositiveClick(view); mListener.onTodayTaskDialogPositiveClick(view);
// Only commit the updated tasks to DB // 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(); dismiss();
} }
@@ -108,50 +112,40 @@ public class TodayFormDialogFragment extends DynamicDialogFragment {
dismiss(); dismiss();
} }
static class LoadTasks extends AsyncTask<Context, Void, List<Task>> { static class LoadTasks implements Callable<List<Task>> {
private final WeakReference<TodayFormDialogFragment> fragmentReference; private final Context context;
LoadTasks(TodayFormDialogFragment context) { public LoadTasks(Context context) {
fragmentReference = new WeakReference<>(context); this.context = context;
} }
@Override @Override
protected List<Task> doInBackground(Context... params) { public List<Task> call() {
try(TaskDataAccess taskDataAccess = new TaskDataAccess(params[0])) { try(TaskDataAccess taskDataAccess = new TaskDataAccess(context)) {
return taskDataAccess.getAllTasks(); return taskDataAccess.getAllTasks();
} }
} }
@Override
protected void onPostExecute(List<Task> tasks) {
super.onPostExecute(tasks);
fragmentReference.get().setLayoutValues(tasks);
}
} }
private static class UpdateTasks extends AsyncTask<Task, Void, Integer> { static class UpdateTasks implements Callable<Integer> {
private final WeakReference<TodayFormDialogFragment> fragmentReference; private final Context context;
private final Task[] tasks;
UpdateTasks(TodayFormDialogFragment context) { public UpdateTasks(Context context, Task[] tasks) {
fragmentReference = new WeakReference<>(context); this.context = context;
this.tasks = tasks;
} }
@Override @Override
protected Integer doInBackground(Task... params) { public Integer call() {
int position; int position;
try (TaskDataAccess taskDataAccess = new TaskDataAccess(fragmentReference.get().getActivity(), TaskDataAccess.MODE.WRITE)) { try (TaskDataAccess taskDataAccess = new TaskDataAccess(context, TaskDataAccess.MODE.WRITE)) {
for (position = 0; position < params.length; position ++) { for (position = 0; position < tasks.length; position ++) {
Task task = params[position]; Task task = tasks[position];
taskDataAccess.updateTodayTasks(task.getId(), task.isToday(), position); taskDataAccess.updateTodayTasks(task.getId(), task.isToday(), position);
} }
} }
return position; return position;
} }
@Override
protected void onPostExecute(Integer integer) {
super.onPostExecute(integer);
fragmentReference.get().mListener.onTodayTasksUpdated();
}
} }
} }

View File

@@ -4,14 +4,15 @@ import android.graphics.Canvas;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.Rect; 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.Layout;
import android.text.StaticLayout; import android.text.StaticLayout;
import android.text.TextPaint; import android.text.TextPaint;
import android.view.View; import android.view.View;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.RecyclerView;
import com.wismna.geoffroy.donext.R; import com.wismna.geoffroy.donext.R;
/** /**
@@ -24,8 +25,8 @@ public class TaskTouchHelper extends ItemTouchHelper.SimpleCallback {
} }
private final TaskTouchHelperAdapter mAdapter; private final TaskTouchHelperAdapter mAdapter;
private int colorRight; private final int colorRight;
private int colorLeft; private final int colorLeft;
public TaskTouchHelper(TaskTouchHelperAdapter adapter, int colorRight, int colorLeft){ public TaskTouchHelper(TaskTouchHelperAdapter adapter, int colorRight, int colorLeft){
// No drag moves, no swipes (except for 1st element, see getSwipeDirs method) // No drag moves, no swipes (except for 1st element, see getSwipeDirs method)
@@ -37,8 +38,8 @@ public class TaskTouchHelper extends ItemTouchHelper.SimpleCallback {
@Override @Override
public int getSwipeDirs(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) { public int getSwipeDirs(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
// Allow both directions swiping on first item, only left on the others // Allow both directions swiping on first item, none on the others
if (viewHolder.getAdapterPosition() == 0) if (viewHolder.getAbsoluteAdapterPosition() == 0)
return ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT; return ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
else return super.getSwipeDirs(recyclerView, viewHolder); else return super.getSwipeDirs(recyclerView, viewHolder);
} }
@@ -50,7 +51,7 @@ public class TaskTouchHelper extends ItemTouchHelper.SimpleCallback {
@Override @Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) { public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
mAdapter.onItemSwiped(viewHolder.getAdapterPosition(), direction); mAdapter.onItemSwiped(viewHolder.getAbsoluteAdapterPosition(), direction);
} }
@Override @Override

View File

@@ -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<List<Task>> getTasksInList(long taskId) {
return mTaskDao.getAllTasksFromList(taskId);
}
public LiveData<List<Task>> getTodayTasks() {
return mTaskDao.getTodayTasks();
}
// Async tasks
private static class insertAsyncTask extends AsyncTask<Task, Void, Void> {
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<Task, Void, Void> {
private TaskDao mAsyncTaskDao;
updateAsyncTask(TaskDao dao) {
mAsyncTaskDao = dao;
}
@Override
protected Void doInBackground(final Task... params) {
mAsyncTaskDao.updateTask(params[0]);
return null;
}
}
}

View File

@@ -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<R> {
void onComplete(R result);
}
public <R> void executeAsync(Callable<R> callable, Callback<R> callback) {
executor.execute(() -> {
final R result;
try {
result = callable.call();
} catch (Exception e) {
throw new RuntimeException(e);
}
handler.post(() -> callback.onComplete(result));
});
}
}