Reputation: 4277
I'm trying to build a "Random Article" Object, which means a random parsed article from Wikipedia. I need the process of getting this article to be synchronous, in order to control the order of the running code.
This is my class:
import android.content.Context;
import android.os.AsyncTask;
import android.os.Handler;
import android.util.Log;
import android.widget.Toast;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.RequestFuture;
import com.android.volley.toolbox.Volley;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.json.JSONObject;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import static android.content.ContentValues.TAG;
public class RandomArticle {
private RequestQueue requestQueue;
private Gson gson;
private String linkForRandomArticle="https://he.wikipedia.org/w/api.php?%20format=json&action=query&prop=extracts&exsentences=2&exintro=&explaintext=&generator=random&grnnamespace=0";
private String title, firstParagraph, id, link;
private JSONObject result;
static Context context;
public RandomArticle(final Context context){
requestQueue = Volley.newRequestQueue(context);
GsonBuilder gsonBuilder = new GsonBuilder();
gson = gsonBuilder.create();
new Handler().post(new Runnable() {
public void run() {
ThreadA threadA = new ThreadA();
try{
try {
try{
result=threadA.execute().get(10, TimeUnit.SECONDS);
}
catch (TimeoutException e){
Log.e(TAG,Log.getStackTraceString(e));
}
}
catch (InterruptedException e){
Log.e(TAG,Log.getStackTraceString(e));
}
}
catch (ExecutionException e) {
Log.e(TAG,Log.getStackTraceString(e));
}
}
});
protected class ThreadA extends AsyncTask<Void, Void, JSONObject> {
public ThreadA() {
}
@Override
protected JSONObject doInBackground(Void... params) {
RequestFuture<JSONObject> future = RequestFuture.newFuture();
final JsonObjectRequest request = new JsonObjectRequest(Request.Method.POST,
linkForRandomArticle,
new JSONObject(),
future, future);
requestQueue.add(request);
try {
try {
int REQUEST_TIMEOUT = 10;
try{
return future.get(REQUEST_TIMEOUT, TimeUnit.SECONDS);
}
catch (TimeoutException e){
Log.e(TAG,Log.getStackTraceString(e));
}
} catch (ExecutionException e) {
Log.e(TAG,Log.getStackTraceString(e));
}
}
catch (InterruptedException e){
Log.e(TAG,Log.getStackTraceString(e));
}
return null;
}
}
}
This is the problematic line:
return future.get(REQUEST_TIMEOUT, TimeUnit.SECONDS);
It's just timing out, and then the result becomes null.
This is the error I get:
05-05 15:55:39.912 25444-25519/com.example.barda.wikirace E/ContentValues:
java.util.concurrent.TimeoutException
at com.android.volley.toolbox.RequestFuture.doGet(RequestFuture.java:121)
at com.android.volley.toolbox.RequestFuture.get(RequestFuture.java:97)
at com.example.barda.wikirace.RandomArticle$Thread.doInBackground(RandomArticle.java:73)
at com.example.barda.wikirace.RandomArticle$Thread.doInBackground(RandomArticle.java:58)
at android.os.AsyncTask$2.call(AsyncTask.java:305)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
at java.lang.Thread.run(Thread.java:761)
I have searched online a lot in order to find something that is similar to what I need. This answer was the best match: https://stackoverflow.com/a/30569997/7483311
I have tried to go through this answer and implement it in my code.
I would like to know how to fix it. Thanks.
Upvotes: 0
Views: 1746
Reputation: 357
Use the below code snippet just changed a bit and am getting the response
public class RandomArticle {
private RequestQueue requestQueue;
private Gson gson;
private String linkForRandomArticle = "https://he.wikipedia.org/w/api.php?%20format=json&action=query&prop=extracts&exsentences=2&exintro=&explaintext=&generator=random&grnnamespace=0";
private String title, firstParagraph, id, link;
private JSONObject result;
static Context context;
public RandomArticle(final Context context) {
this.context = context;
}
public JSONObject getRamdomArticle(){
requestQueue = Volley.newRequestQueue(context);
GsonBuilder gsonBuilder = new GsonBuilder();
gson = gsonBuilder.create();
ThreadA threadA = new ThreadA();
try {
try {
try {
result = threadA.execute().get(100, TimeUnit.SECONDS);
assert result != null;
} catch (TimeoutException e) {
Log.e(TAG, Log.getStackTraceString(e));
}
} catch (InterruptedException e) {
Log.e(TAG, Log.getStackTraceString(e));
}
} catch (ExecutionException e) {
Log.e(TAG, Log.getStackTraceString(e));
}
return result;
}
class ThreadA extends AsyncTask<Void, Void, JSONObject> {
public ThreadA() {
}
@Override
protected JSONObject doInBackground(Void... params) {
RequestFuture<JSONObject> future = RequestFuture.newFuture();
final JsonObjectRequest request = new JsonObjectRequest(Request.Method.POST,
linkForRandomArticle,
new JSONObject(),
future, future);
requestQueue.add(request);
try {
try {
int REQUEST_TIMEOUT = 100;
try {
return future.get(REQUEST_TIMEOUT, TimeUnit.SECONDS);
} catch (TimeoutException e) {
Log.e(TAG, Log.getStackTraceString(e));
}
} catch (ExecutionException e) {
Log.e(TAG, Log.getStackTraceString(e));
}
} catch (InterruptedException e) {
Log.e(TAG, Log.getStackTraceString(e));
}
return null;
}
}
}
Upvotes: 0
Reputation: 4277
The problem was using this:
new Handler().post(new Runnable() {
public void run() {
ThreadA threadA = new ThreadA();
try{
try {
try{
result=threadA.execute().get(10, TimeUnit.SECONDS);
}
catch (TimeoutException e){
Log.e(TAG,Log.getStackTraceString(e));
}
}
catch (InterruptedException e){
Log.e(TAG,Log.getStackTraceString(e));
}
}
catch (ExecutionException e) {
Log.e(TAG,Log.getStackTraceString(e));
}
}
});
Instead of this:
Thread t = new Thread(new Runnable() {
@Override
public void run() {
Log.d("RT", "Thread t Begins");
ThreadA threadA = new ThreadA();
try{
try {
try{
result=threadA.execute().get(10, TimeUnit.SECONDS);
}
catch (TimeoutException e){
Log.e(TAG,Log.getStackTraceString(e));
}
}
catch (InterruptedException e){
Log.e(TAG,Log.getStackTraceString(e));
}
}
catch (ExecutionException e) {
Log.e(TAG,Log.getStackTraceString(e));
}
}
});
t.start();
It's probably has to be new thread.
Upvotes: 0
Reputation: 25573
Since get()
blocks until there is a result, there are two possibilities considering your code:
JsonObjectRequest
timed out or failed with an exception. Without seeing your log output it is impossible to say if this happened. Furthermore you're not logging the cause of that failure so even if the log includes the line "Failed" the exact cause is still unclear.null
, however it seems like this only occurs if an error happens during parsing, which should cause the ExecutionException
to be thrown.Its a good idea to improve your logging so you know exactly where and why failures occur.
Upvotes: 1