Return A Response for Android Volley When Using WorkManager

While developing my app Afrolang: a bite-sized African language learning app. I ran into a scenario where I needed the result of my Volley Request to be the success or failure result of my Work Manager. Work Manager in itself creates a separate thread to run its operation when the system resources are available and Volley library also spins up a new thread to make a network call. Putting an Async process into another creates two separate processes that do not wait for each other and this can make using Volley in a WorkManager a bit confusing. This post profers a solution and assumes you are familiar with Work Manager and Volley. If you are not, click these links to learn more about work manager and volley
The link to a demo of the project on GitHub is below
Introducing Volley RequestFutures
A RequestFuture is used to make a synchronous HTTP Request using volley.
Setup your Volley Singleton in VolleySingleton.java
private static VolleySingleton mInstance;
private RequestQueue mRequestQueue;
private static Context mContext;private VolleySingleton(Context context){
mContext = context;
//Get the requiest queue
mRequestQueue = getmRequestQueue();
}public static synchronized VolleySingleton getmInstance(Context context){
//If instance is null then initialize new instance
if(mInstance == null){
mInstance = new VolleySingleton(context);
}
//Return MySingleton new instance
return mInstance;
}public RequestQueue getmRequestQueue() {
//If RequestQueue is null the intialize new RequestQueue
if(mRequestQueue == null){
mRequestQueue = Volley.newRequestQueue(mContext.getApplicationContext());
}
return mRequestQueue;
}public<T> void addToRequestQueue(Request<T> request){
//Add the specified request to the request queue
getmRequestQueue().add(request);
}
Setup your worker in TestWorker.java, extend Worker and slot in your request within a Volley RequestFuture
private static final String TAG = TestWorker.class.getSimpleName();
private String url = "https://jsonplaceholder.typicode.com/todos/1";
public TestWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
}@NonNull
@Override
public Result doWork() {//Setup a RequestFuture object
RequestFuture<JSONObject> future = RequestFuture.newFuture();//Pass the future into the JsonObjectRequest
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, url, null, future, future);//Add the request to the Request QueueVolleySingleton.getmInstance(getApplicationContext()).addToRequestQueue(request); try {//Set an interval for the request to timeout. This will block the //worker thread and force it to wait for a response for 60 seconds //before timing out and raising an exceptionJSONObject response = future.get(60, TimeUnit.SECONDS);//Log Response and return Result.success() or your output data to //any observer
Log.d(TAG, response.toString());
return Result.success();
} catch (InterruptedException e) {
e.printStackTrace();
// exception handling
return Result.failure();
} catch (ExecutionException e) {
e.printStackTrace();
return Result.failure();
// exception handling
} catch (TimeoutException e) {
e.printStackTrace();
return Result.failure();
}
}
Call it wherever you need it. For testing purposes, I will call mine in MainActivity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); OneTimeWorkRequest oneTimeWorkRequest = new OneTimeWorkRequest.Builder(TestWorker.class).build();
WorkManager.getInstance().enqueue(oneTimeWorkRequest);
}
If this was helpful, feel free to clap as many times as you deem fit.
I always love new friends so you can follow me on twitter @itzbernoulli
Cheers
