├── app ├── .gitignore ├── src │ └── main │ │ ├── res │ │ ├── mipmap-hdpi │ │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ │ └── ic_launcher.png │ │ ├── values │ │ │ ├── dimens.xml │ │ │ ├── colors.xml │ │ │ ├── styles.xml │ │ │ └── strings.xml │ │ ├── drawable │ │ │ └── priority_circle.xml │ │ ├── values-w820dp │ │ │ └── dimens.xml │ │ └── layout │ │ │ ├── activity_main.xml │ │ │ ├── task_layout.xml │ │ │ └── activity_add_task.xml │ │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── android │ │ │ └── todolist │ │ │ ├── database │ │ │ ├── DateConverter.java │ │ │ ├── TaskDao.java │ │ │ ├── AppDatabase.java │ │ │ └── TaskEntry.java │ │ │ ├── AddTaskViewModel.java │ │ │ ├── MainViewModel.java │ │ │ ├── AddTaskViewModelFactory.java │ │ │ ├── AppExecutors.java │ │ │ ├── MainActivity.java │ │ │ ├── TaskAdapter.java │ │ │ └── AddTaskActivity.java │ │ └── AndroidManifest.xml └── build.gradle ├── settings.gradle ├── .gitignore ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── README.md ├── gradle.properties ├── gradlew.bat └── gradlew /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea 5 | .DS_Store 6 | /build 7 | /captures 8 | .externalNativeBuild 9 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/udacity/android-architecture-components_toy_app/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/udacity/android-architecture-components_toy_app/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/udacity/android-architecture-components_toy_app/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/udacity/android-architecture-components_toy_app/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/udacity/android-architecture-components_toy_app/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/udacity/android-architecture-components_toy_app/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Dec 28 17:22:38 GMT 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 16dp 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/priority_circle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/android/todolist/database/DateConverter.java: -------------------------------------------------------------------------------- 1 | package com.example.android.todolist.database; 2 | 3 | import android.arch.persistence.room.TypeConverter; 4 | 5 | import java.util.Date; 6 | 7 | public class DateConverter { 8 | @TypeConverter 9 | public static Date toDate(Long timestamp) { 10 | return timestamp == null ? null : new Date(timestamp); 11 | } 12 | 13 | @TypeConverter 14 | public static Long toTimestamp(Date date) { 15 | return date == null ? null : date.getTime(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | #3F51B5 5 | #303F9F 6 | #C5CAE9 7 | #303F9F 8 | 9 | 10 | #E74C3C 11 | #E67E22 12 | #F1C40F 13 | 14 | 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Archival Note 3 | This repository is deprecated; therefore, we are going to archive it. However, learners will be able to fork it to their personal Github account but cannot submit PRs to this repository. If you have any issues or suggestions to make, feel free to: 4 | - Utilize the https://knowledge.udacity.com/ forum to seek help on content-specific issues. 5 | - Submit a support ticket along with the link to your forked repository if (learners are) blocked for other reasons. Here are the links for the [retail consumers](https://udacity.zendesk.com/hc/en-us/requests/new) and [enterprise learners](https://udacityenterprise.zendesk.com/hc/en-us/requests/new?ticket_form_id=360000279131). -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | org.gradle.jvmargs=-Xmx1536m 13 | 14 | # When configured, Gradle will run in incubating parallel mode. 15 | # This option should only be used with decoupled projects. More details, visit 16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 17 | # org.gradle.parallel=true 18 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | To-Do List 3 | All Tasks 4 | Add a New Task 5 | 6 | 7 | 1 8 | 2 9 | 3 10 | 11 | 12 | 13 | Describe your taskEntry… 14 | Priority 15 | 16 | High 17 | Medium 18 | Low 19 | 20 | Add 21 | Update 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/android/todolist/database/TaskDao.java: -------------------------------------------------------------------------------- 1 | package com.example.android.todolist.database; 2 | 3 | import android.arch.lifecycle.LiveData; 4 | import android.arch.persistence.room.Dao; 5 | import android.arch.persistence.room.Delete; 6 | import android.arch.persistence.room.Insert; 7 | import android.arch.persistence.room.OnConflictStrategy; 8 | import android.arch.persistence.room.Query; 9 | import android.arch.persistence.room.Update; 10 | 11 | import java.util.List; 12 | 13 | @Dao 14 | public interface TaskDao { 15 | 16 | @Query("SELECT * FROM task ORDER BY priority") 17 | LiveData> loadAllTasks(); 18 | 19 | @Insert 20 | void insertTask(TaskEntry taskEntry); 21 | 22 | @Update(onConflict = OnConflictStrategy.REPLACE) 23 | void updateTask(TaskEntry taskEntry); 24 | 25 | @Delete 26 | void deleteTask(TaskEntry taskEntry); 27 | 28 | @Query("SELECT * FROM task WHERE id = :id") 29 | LiveData loadTaskById(int id); 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/android/todolist/AddTaskViewModel.java: -------------------------------------------------------------------------------- 1 | package com.example.android.todolist; 2 | 3 | import android.arch.lifecycle.LiveData; 4 | import android.arch.lifecycle.ViewModel; 5 | 6 | import com.example.android.todolist.database.AppDatabase; 7 | import com.example.android.todolist.database.TaskEntry; 8 | 9 | // COMPLETED (5) Make this class extend ViewModel 10 | public class AddTaskViewModel extends ViewModel { 11 | 12 | // COMPLETED (6) Add a task member variable for the TaskEntry object wrapped in a LiveData 13 | private LiveData task; 14 | 15 | // COMPLETED (8) Create a constructor where you call loadTaskById of the taskDao to initialize the tasks variable 16 | // Note: The constructor should receive the database and the taskId 17 | public AddTaskViewModel(AppDatabase database, int taskId) { 18 | task = database.taskDao().loadTaskById(taskId); 19 | } 20 | 21 | // COMPLETED (7) Create a getter for the task variable 22 | public LiveData getTask() { 23 | return task; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/android/todolist/MainViewModel.java: -------------------------------------------------------------------------------- 1 | package com.example.android.todolist; 2 | 3 | import android.app.Application; 4 | import android.arch.lifecycle.AndroidViewModel; 5 | import android.arch.lifecycle.LiveData; 6 | import android.util.Log; 7 | 8 | import com.example.android.todolist.database.AppDatabase; 9 | import com.example.android.todolist.database.TaskEntry; 10 | 11 | import java.util.List; 12 | 13 | public class MainViewModel extends AndroidViewModel { 14 | 15 | // Constant for logging 16 | private static final String TAG = MainViewModel.class.getSimpleName(); 17 | 18 | private LiveData> tasks; 19 | 20 | public MainViewModel(Application application) { 21 | super(application); 22 | AppDatabase database = AppDatabase.getInstance(this.getApplication()); 23 | Log.d(TAG, "Actively retrieving the tasks from the DataBase"); 24 | tasks = database.taskDao().loadAllTasks(); 25 | } 26 | 27 | public LiveData> getTasks() { 28 | return tasks; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/android/todolist/AddTaskViewModelFactory.java: -------------------------------------------------------------------------------- 1 | package com.example.android.todolist; 2 | 3 | import android.arch.lifecycle.ViewModel; 4 | import android.arch.lifecycle.ViewModelProvider; 5 | 6 | import com.example.android.todolist.database.AppDatabase; 7 | 8 | // COMPLETED (1) Make this class extend ViewModel ViewModelProvider.NewInstanceFactory 9 | public class AddTaskViewModelFactory extends ViewModelProvider.NewInstanceFactory { 10 | 11 | // COMPLETED (2) Add two member variables. One for the database and one for the taskId 12 | private final AppDatabase mDb; 13 | private final int mTaskId; 14 | 15 | // COMPLETED (3) Initialize the member variables in the constructor with the parameters received 16 | public AddTaskViewModelFactory(AppDatabase database, int taskId) { 17 | mDb = database; 18 | mTaskId = taskId; 19 | } 20 | 21 | // COMPLETED (4) Uncomment the following method 22 | @Override 23 | public T create(Class modelClass) { 24 | //noinspection unchecked 25 | return (T) new AddTaskViewModel(mDb, mTaskId); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 10 | 11 | 12 | 18 | 19 | 20 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/android/todolist/database/AppDatabase.java: -------------------------------------------------------------------------------- 1 | package com.example.android.todolist.database; 2 | 3 | import android.arch.persistence.room.Database; 4 | import android.arch.persistence.room.Room; 5 | import android.arch.persistence.room.RoomDatabase; 6 | import android.arch.persistence.room.TypeConverters; 7 | import android.content.Context; 8 | import android.util.Log; 9 | 10 | @Database(entities = {TaskEntry.class}, version = 1, exportSchema = false) 11 | @TypeConverters(DateConverter.class) 12 | public abstract class AppDatabase extends RoomDatabase { 13 | 14 | private static final String LOG_TAG = AppDatabase.class.getSimpleName(); 15 | private static final Object LOCK = new Object(); 16 | private static final String DATABASE_NAME = "todolist"; 17 | private static AppDatabase sInstance; 18 | 19 | public static AppDatabase getInstance(Context context) { 20 | if (sInstance == null) { 21 | synchronized (LOCK) { 22 | Log.d(LOG_TAG, "Creating new database instance"); 23 | sInstance = Room.databaseBuilder(context.getApplicationContext(), 24 | AppDatabase.class, AppDatabase.DATABASE_NAME) 25 | .build(); 26 | } 27 | } 28 | Log.d(LOG_TAG, "Getting the database instance"); 29 | return sInstance; 30 | } 31 | 32 | public abstract TaskDao taskDao(); 33 | 34 | } 35 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 27 5 | buildToolsVersion '27.0.1' 6 | defaultConfig { 7 | applicationId "com.example.android.todolist" 8 | minSdkVersion 15 9 | targetSdkVersion 27 10 | versionCode 1 11 | versionName "1.0" 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | compile fileTree(dir: 'libs', include: ['*.jar']) 23 | compile 'com.android.support:appcompat-v7:27.0.2' 24 | 25 | //add Recycler view dependencies; must match SDK version 26 | compile 'com.android.support:recyclerview-v7:27.0.2' 27 | 28 | //FAB dependencies 29 | compile 'com.android.support:design:27.0.2' 30 | 31 | compile "android.arch.persistence.room:runtime:1.0.0" 32 | annotationProcessor "android.arch.persistence.room:compiler:1.0.0" 33 | 34 | implementation "android.arch.lifecycle:extensions:1.1.0" 35 | annotationProcessor "android.arch.lifecycle:compiler:1.1.0" 36 | 37 | //Testing 38 | // Instrumentation dependencies use androidTestCompile 39 | // (as opposed to testCompile for local unit tests run in the JVM) 40 | androidTestCompile 'junit:junit:4.12' 41 | androidTestCompile 'com.android.support:support-annotations:27.0.2' 42 | androidTestCompile 'com.android.support.test:runner:1.0.1' 43 | androidTestCompile 'com.android.support.test:rules:1.0.1' 44 | } 45 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/android/todolist/database/TaskEntry.java: -------------------------------------------------------------------------------- 1 | package com.example.android.todolist.database; 2 | 3 | import android.arch.persistence.room.ColumnInfo; 4 | import android.arch.persistence.room.Entity; 5 | import android.arch.persistence.room.Ignore; 6 | import android.arch.persistence.room.PrimaryKey; 7 | 8 | import java.util.Date; 9 | 10 | @Entity(tableName = "task") 11 | public class TaskEntry { 12 | 13 | @PrimaryKey(autoGenerate = true) 14 | private int id; 15 | private String description; 16 | private int priority; 17 | @ColumnInfo(name = "updated_at") 18 | private Date updatedAt; 19 | 20 | @Ignore 21 | public TaskEntry(String description, int priority, Date updatedAt) { 22 | this.description = description; 23 | this.priority = priority; 24 | this.updatedAt = updatedAt; 25 | } 26 | 27 | public TaskEntry(int id, String description, int priority, Date updatedAt) { 28 | this.id = id; 29 | this.description = description; 30 | this.priority = priority; 31 | this.updatedAt = updatedAt; 32 | } 33 | 34 | public int getId() { 35 | return id; 36 | } 37 | 38 | public void setId(int id) { 39 | this.id = id; 40 | } 41 | 42 | public String getDescription() { 43 | return description; 44 | } 45 | 46 | public void setDescription(String description) { 47 | this.description = description; 48 | } 49 | 50 | public int getPriority() { 51 | return priority; 52 | } 53 | 54 | public void setPriority(int priority) { 55 | this.priority = priority; 56 | } 57 | 58 | public Date getUpdatedAt() { 59 | return updatedAt; 60 | } 61 | 62 | public void setUpdatedAt(Date updatedAt) { 63 | this.updatedAt = updatedAt; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/res/layout/task_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 18 | 19 | 20 | 27 | 28 | 29 | 36 | 37 | 38 | 39 | 40 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/android/todolist/AppExecutors.java: -------------------------------------------------------------------------------- 1 | package com.example.android.todolist; 2 | 3 | /* 4 | * Copyright (C) 2017 The Android Open Source Project 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import android.os.Handler; 20 | import android.os.Looper; 21 | import android.support.annotation.NonNull; 22 | 23 | import java.util.concurrent.Executor; 24 | import java.util.concurrent.Executors; 25 | 26 | /** 27 | * Global executor pools for the whole application. 28 | *

29 | * Grouping tasks like this avoids the effects of task starvation (e.g. disk reads don't wait behind 30 | * webservice requests). 31 | */ 32 | public class AppExecutors { 33 | 34 | // For Singleton instantiation 35 | private static final Object LOCK = new Object(); 36 | private static AppExecutors sInstance; 37 | private final Executor diskIO; 38 | private final Executor mainThread; 39 | private final Executor networkIO; 40 | 41 | private AppExecutors(Executor diskIO, Executor networkIO, Executor mainThread) { 42 | this.diskIO = diskIO; 43 | this.networkIO = networkIO; 44 | this.mainThread = mainThread; 45 | } 46 | 47 | public static AppExecutors getInstance() { 48 | if (sInstance == null) { 49 | synchronized (LOCK) { 50 | sInstance = new AppExecutors(Executors.newSingleThreadExecutor(), 51 | Executors.newFixedThreadPool(3), 52 | new MainThreadExecutor()); 53 | } 54 | } 55 | return sInstance; 56 | } 57 | 58 | public Executor diskIO() { 59 | return diskIO; 60 | } 61 | 62 | public Executor mainThread() { 63 | return mainThread; 64 | } 65 | 66 | public Executor networkIO() { 67 | return networkIO; 68 | } 69 | 70 | private static class MainThreadExecutor implements Executor { 71 | private Handler mainThreadHandler = new Handler(Looper.getMainLooper()); 72 | 73 | @Override 74 | public void execute(@NonNull Runnable command) { 75 | mainThreadHandler.post(command); 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_add_task.xml: -------------------------------------------------------------------------------- 1 | 5 | 15 | 16 | 17 | 24 | 25 | 26 | 35 | 36 | 37 | 45 | 46 | 55 | 56 | 64 | 65 | 73 | 74 | 75 | 76 | 77 |