├── LICENSE ├── README.md └── async ├── AdvancedAsyncTask.java ├── AsyncTask.java ├── AsyncWorker.java └── TaskNotExecutedException.java /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AndroidAsync 2 | Replacement for deprecated AsyncTask. This repository contains one simple implementation with just basic functionality (AsyncTask) and one which is slowly being extended to fully replace the original AsyncTask (AdvancedAsyncTask). 3 | 4 | ## Adding this to my project 5 | 1) Create/Open Android Studio project 6 | 2) Drop the ***async*** folder to your package file in the java folder 7 | 8 | ## Using new AsyncTask: 9 | 1) Create custom task extending AsyncTask (similar to the old one) 10 | 11 | ```java 12 | public class ExampleTask extends AsyncTask { 13 | @Override 14 | protected void onPreExecute() { 15 | //Do something before doInBackground() on UI thread 16 | } 17 | 18 | @Override 19 | protected String doInBackground(String s) throws Exception { 20 | //Does some work on background thread 21 | return null; 22 | } 23 | 24 | @Override 25 | protected void onPostExecute(String s) { 26 | //Do something after doInBackground() on UI thread 27 | } 28 | 29 | @Override 30 | protected void onBackgroundError(Exception e) { 31 | //Handle any exception that occured while running doInBackground() 32 | //This is also executed on the UI thread 33 | } 34 | } 35 | ``` 36 | 37 | 2) Execute your task 38 | 39 | ```java 40 | public class MainActivity extends AppCompatActivity { 41 | 42 | @Override 43 | protected void onCreate(Bundle savedInstanceState) { 44 | super.onCreate(savedInstanceState); 45 | setContentView(R.layout.activity_main); 46 | 47 | ExampleTask exampleTask = new ExampleTask(); 48 | exampleTask.execute("Something"); 49 | } 50 | } 51 | ``` 52 | 53 | 3) Implement cancel() (Optional) 54 | ```java 55 | public class ExampleTask extends AsyncTask { 56 | ... 57 | 58 | @Override 59 | protected String doInBackground(String s) throws Exception { 60 | while (true) { 61 | if (isCancelled()) { 62 | onCancelled(); //Triggers OnCancelledListener, which can be set with setOnCancelledListener() 63 | break; 64 | } 65 | } 66 | 67 | return null; 68 | } 69 | 70 | ... 71 | } 72 | ``` 73 | 74 | 4) Implement postProgress() (Optional) 75 | ```java 76 | public class ExampleTask extends AsyncTask { 77 | ... 78 | 79 | @Override 80 | protected String doInBackground(String s) throws Exception { 81 | Integer progress = 0; 82 | while (true) { 83 | progress++; 84 | postProgress(progress); //Triggers OnProgressListener, which can be set with setOnProgressListener() 85 | } 86 | 87 | return null; 88 | } 89 | 90 | ... 91 | } 92 | ``` 93 | -------------------------------------------------------------------------------- /async/AdvancedAsyncTask.java: -------------------------------------------------------------------------------- 1 | package cz.barda.jidelnacz2.async; 2 | 3 | import java.util.concurrent.ExecutorService; 4 | import java.util.concurrent.Future; 5 | import java.util.concurrent.TimeUnit; 6 | 7 | public abstract class AdvancedAsyncTask { 8 | private boolean cancelled = false; 9 | private Future outputFuture; 10 | 11 | public AdvancedAsyncTask() { 12 | 13 | } 14 | 15 | /** 16 | * @see #execute(Object) 17 | */ 18 | public AdvancedAsyncTask execute() { 19 | return execute(null); 20 | } 21 | 22 | /** 23 | * Starts is all 24 | * @param input Data you want to work with in the background 25 | */ 26 | public AdvancedAsyncTask execute(final INPUT input) { 27 | onPreExecute(); 28 | 29 | ExecutorService executorService = AsyncWorker.getInstance().getExecutorService(); 30 | outputFuture = executorService.submit(() -> { 31 | try { 32 | final OUTPUT output = doInBackground(input); 33 | AsyncWorker.getInstance().getHandler().post(() -> onPostExecute(output)); 34 | return output; 35 | } catch (Exception e) { 36 | AsyncWorker.getInstance().getHandler().post(() -> onBackgroundError(e)); 37 | throw e; 38 | } 39 | }); 40 | 41 | return this; 42 | } 43 | 44 | public OUTPUT get() throws Exception { 45 | if (outputFuture == null) { 46 | throw new TaskNotExecutedException(); 47 | } else { 48 | return outputFuture.get(); 49 | } 50 | } 51 | 52 | public OUTPUT get(long timeout, TimeUnit timeUnit) throws Exception { 53 | if (outputFuture == null) { 54 | throw new TaskNotExecutedException(); 55 | } else { 56 | return outputFuture.get(timeout, timeUnit); 57 | } 58 | } 59 | /** 60 | * Call to publish progress from background 61 | * @param progress Progress made 62 | */ 63 | protected void publishProgress(final PROGRESS progress) { 64 | AsyncWorker.getInstance().getHandler().post(() -> { 65 | onProgress(progress); 66 | 67 | if (onProgressListener != null) { 68 | onProgressListener.onProgress(progress); 69 | } 70 | }); 71 | } 72 | 73 | protected void onProgress(final PROGRESS progress) { 74 | 75 | } 76 | 77 | /** 78 | * Call to cancel background work 79 | */ 80 | public void cancel() { 81 | cancelled = true; 82 | } 83 | 84 | /** 85 | * 86 | * @return Returns true if the background work should be cancelled 87 | */ 88 | protected boolean isCancelled() { 89 | return cancelled; 90 | } 91 | 92 | /** 93 | * Call this method after cancelling background work 94 | */ 95 | protected void onCancelled() { 96 | AsyncWorker.getInstance().getHandler().post(() -> { 97 | if (onCancelledListener != null) { 98 | onCancelledListener.onCancelled(); 99 | } 100 | }); 101 | } 102 | 103 | /** 104 | * Work which you want to be done on UI thread before {@link #doInBackground(Object)} 105 | */ 106 | protected void onPreExecute() { 107 | 108 | } 109 | 110 | /** 111 | * Work on background 112 | * @param input Input data 113 | * @return Output data 114 | * @throws Exception Any uncought exception which occurred while working in background. If 115 | * any occurs, {@link #onBackgroundError(Exception)} will be executed (on the UI thread) 116 | */ 117 | protected abstract OUTPUT doInBackground(INPUT input) throws Exception; 118 | 119 | /** 120 | * Work which you want to be done on UI thread after {@link #doInBackground(Object)} 121 | * @param output Output data from {@link #doInBackground(Object)} 122 | */ 123 | protected void onPostExecute(OUTPUT output) { 124 | 125 | } 126 | 127 | /** 128 | * Triggered on UI thread if any uncought exception occurred while working in background 129 | * @param e Exception 130 | * @see #doInBackground(Object) 131 | */ 132 | protected abstract void onBackgroundError(Exception e); 133 | 134 | private OnProgressListener onProgressListener; 135 | public interface OnProgressListener { 136 | void onProgress(PROGRESS progress); 137 | } 138 | 139 | public void setOnProgressListener(OnProgressListener onProgressListener) { 140 | this.onProgressListener = onProgressListener; 141 | } 142 | 143 | private OnCancelledListener onCancelledListener; 144 | public interface OnCancelledListener { 145 | void onCancelled(); 146 | } 147 | 148 | public void setOnCancelledListener(OnCancelledListener onCancelledListener) { 149 | this.onCancelledListener = onCancelledListener; 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /async/AsyncTask.java: -------------------------------------------------------------------------------- 1 | package cz.barda.jidelnacz2.async; 2 | 3 | import java.util.concurrent.ExecutorService; 4 | 5 | public abstract class AsyncTask { 6 | private boolean cancelled = false; 7 | 8 | public AsyncTask() { 9 | 10 | } 11 | 12 | /** 13 | * @see #execute(Object) 14 | */ 15 | public AsyncTask execute() { 16 | return execute(null); 17 | } 18 | 19 | /** 20 | * Starts is all 21 | * @param input Data you want to work with in the background 22 | */ 23 | public AsyncTask execute(final INPUT input) { 24 | onPreExecute(); 25 | 26 | ExecutorService executorService = AsyncWorker.getInstance().getExecutorService(); 27 | executorService.execute(() -> { 28 | try { 29 | final OUTPUT output = doInBackground(input); 30 | AsyncWorker.getInstance().getHandler().post(() -> onPostExecute(output)); 31 | } catch (final Exception e) { 32 | e.printStackTrace(); 33 | 34 | AsyncWorker.getInstance().getHandler().post(() -> onBackgroundError(e)); 35 | } 36 | }); 37 | 38 | return this; 39 | } 40 | 41 | /** 42 | * Call to publish progress from background 43 | * @param progress Progress made 44 | */ 45 | protected void publishProgress(final PROGRESS progress) { 46 | AsyncWorker.getInstance().getHandler().post(() -> { 47 | onProgress(progress); 48 | 49 | if (onProgressListener != null) { 50 | onProgressListener.onProgress(progress); 51 | } 52 | }); 53 | } 54 | 55 | protected void onProgress(final PROGRESS progress) { 56 | 57 | } 58 | 59 | /** 60 | * Call to cancel background work 61 | */ 62 | public void cancel() { 63 | cancelled = true; 64 | } 65 | 66 | /** 67 | * 68 | * @return Returns true if the background work should be cancelled 69 | */ 70 | protected boolean isCancelled() { 71 | return cancelled; 72 | } 73 | 74 | /** 75 | * Call this method after cancelling background work 76 | */ 77 | protected void onCancelled() { 78 | AsyncWorker.getInstance().getHandler().post(() -> { 79 | if (onCancelledListener != null) { 80 | onCancelledListener.onCancelled(); 81 | } 82 | }); 83 | } 84 | 85 | /** 86 | * Work which you want to be done on UI thread before {@link #doInBackground(Object)} 87 | */ 88 | protected void onPreExecute() { 89 | 90 | } 91 | 92 | /** 93 | * Work on background 94 | * @param input Input data 95 | * @return Output data 96 | * @throws Exception Any uncought exception which occurred while working in background. If 97 | * any occurs, {@link #onBackgroundError(Exception)} will be executed (on the UI thread) 98 | */ 99 | protected abstract OUTPUT doInBackground(INPUT input) throws Exception; 100 | 101 | /** 102 | * Work which you want to be done on UI thread after {@link #doInBackground(Object)} 103 | * @param output Output data from {@link #doInBackground(Object)} 104 | */ 105 | protected void onPostExecute(OUTPUT output) { 106 | 107 | } 108 | 109 | /** 110 | * Triggered on UI thread if any uncought exception occurred while working in background 111 | * @param e Exception 112 | * @see #doInBackground(Object) 113 | */ 114 | protected abstract void onBackgroundError(Exception e); 115 | 116 | private OnProgressListener onProgressListener; 117 | public interface OnProgressListener { 118 | void onProgress(PROGRESS progress); 119 | } 120 | 121 | public void setOnProgressListener(OnProgressListener onProgressListener) { 122 | this.onProgressListener = onProgressListener; 123 | } 124 | 125 | private OnCancelledListener onCancelledListener; 126 | public interface OnCancelledListener { 127 | void onCancelled(); 128 | } 129 | 130 | public void setOnCancelledListener(OnCancelledListener onCancelledListener) { 131 | this.onCancelledListener = onCancelledListener; 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /async/AsyncWorker.java: -------------------------------------------------------------------------------- 1 | package cz.barda.jidelnacz2.async; 2 | 3 | import android.os.Handler; 4 | import android.os.Looper; 5 | 6 | import java.util.concurrent.ExecutorService; 7 | import java.util.concurrent.Executors; 8 | 9 | public class AsyncWorker { 10 | private static final AsyncWorker instance = new AsyncWorker(); 11 | private static final int NUMBER_OF_THREADS = 4; 12 | 13 | private ExecutorService executorService; 14 | protected Handler handler; 15 | 16 | private AsyncWorker() { 17 | executorService = Executors.newFixedThreadPool(NUMBER_OF_THREADS); 18 | handler = new Handler(Looper.getMainLooper()); 19 | } 20 | 21 | public static AsyncWorker getInstance() { 22 | return instance; 23 | } 24 | 25 | public ExecutorService getExecutorService() { 26 | return executorService; 27 | } 28 | 29 | public Handler getHandler() { 30 | return handler; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /async/TaskNotExecutedException.java: -------------------------------------------------------------------------------- 1 | package cz.barda.jidelnacz2.async; 2 | 3 | public class TaskNotExecutedException extends Exception { 4 | public TaskNotExecutedException() { 5 | super("Task not executed before calling get()"); 6 | } 7 | } 8 | --------------------------------------------------------------------------------