使用RequestFuture.get()时Android排名超时异常 [英] Android volley Timeout Exception when using RequestFuture.get()

查看:384
本文介绍了使用RequestFuture.get()时Android排名超时异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的片段中,我正在尝试使用TMDB的开放电影数据库来获取有关正在播放电影的详细信息。

In my Fragment, i am trying to use TMDB's open movie DB to get details about "Now Playing" Movies.

如果我使用RequestFuture.get(时间,执行此齐射请求的TimeUnit方法总是会出现超时错误。如果我在Safari中手动测试相同的Url,我会立即得到结果。

If i use RequestFuture.get(time, TimeUnit) method to execute this volley request i always get a timeout error. If i manually test the same Url in Safari, i get the results instantaneously.

我所知道的:

1。)这不是任何JSON解析错误。(程序甚至没有进展到解析步骤)

1.) It is not any JSON Parsing error.(the program doesnt even progress to the parsing steps)

2。)没有互联网问题与AVD。 (后面解释的原因)。

2.) No internet issues with AVD. (Reason explained later).

3。)我的排球单件类或我的请求队列不是问题。 (原因后来解释)。

3.) Not an issue with my volley singleton class or my Request Queue. (Reason explained Later).

所以我假设我在排球/请求未来的使用方面犯了另一个错误。

So im presuming that i am making someother kind of mistake regarding the usages of volley/Request Future.

下面的片段代码:

public class BoxOffice extends android.support.v4.app.Fragment {
    private VolleySingleton volleySingleton;
    private RequestQueue requestQueue;
    private ImageLoader imageLoader;
    private ArrayList<MyMovie> movieList;
    private MyUriBuilder mBuilder;

    public BoxOffice() {
        // Required empty public constructor
        volleySingleton = VolleySingleton.getInstance();
        requestQueue = volleySingleton.getRequestQueue();
        mBuilder = new MyUriBuilder();
        movieList = new ArrayList<>();
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mParam1 = getArguments().getString(ARG_PARAM1);
            mParam2 = getArguments().getString(ARG_PARAM2);
        }
        StepA();
    }

    public void StepA() {
        String url = mBuilder.getURL("box");
        Log.d("RT", "StepA initiated - "+ url); // Url is perfect - works when copied in Safari.
        RequestFuture<JSONObject> futureA = RequestFuture.newFuture();
        JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, url, (String) null, futureA, futureA);
        requestQueue.add(request);

        try {
            JSONObject response = futureA.get(30, TimeUnit.SECONDS);
            Log.d("RT", "StepA - response received"); //Never reaches this step
            parseJsonFeed(response);
        } catch (InterruptedException e) {
            Log.e("RT", "StepA - InterruptedException - " + e);
            e.printStackTrace();
        } catch (ExecutionException e) {
            Log.e("RT", "StepA - ExecutionException - " + e);
            e.printStackTrace();
        } catch (TimeoutException e) {
            Log.e("RT", "StepA - TimeoutException - " + e);
            e.printStackTrace();
        }
        Log.d("RT", "StepA END");
    }

    public void parseJsonFeed(JSONObject response) {
        Log.d("RT", "StepA - parseFeed Begin");
        if (response == null || response.length() == 0) {
            return;
        }
        MyMovie currentMovie = null;
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");

        try {
            if (response.has("results")) {
                Log.d("RT", "StepA - results");
                JSONArray resultList = response.getJSONArray("results");
                for (int i = 0; i < 3; i++) {
                    Log.d("RT", "movie " + i);
                    JSONObject movieElement = resultList.getJSONObject(i);
                    if (movieElement.has("id") && movieElement.has("title")) {
                        currentMovie = new MyMovie();
                        currentMovie.setTmdb_id(movieElement.getString("id"));
                        currentMovie.setTitle(movieElement.getString("title"));
                        if (movieElement.has("release_date")) {
                            currentMovie.setReleaseDate(dateFormat.parse(movieElement.getString("release_date")));
                        } else {
                            currentMovie.setReleaseDate(dateFormat.parse("0000-00-00"));
                        }
                        movieList.add(i, currentMovie);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        Log.d("RT", "StepA - parseFeed END");
    }
}

带有标签过滤器的Logcat RT:

05-30 15:17:51.710  D/RT﹕ TL - Constructor Called
05-30 15:17:51.800  D/RT﹕ StepA initiated - https://api.themoviedb.org/3/movie/now_playing?api_key=##### (link works fine)
05-30 15:18:21.820  E/RT﹕ StepA - TimeoutException - java.util.concurrent.TimeoutException
05-30 15:18:21.820  D/RT﹕ StepA END

在使用RequestFuture方法之前,我基本上做了同样的事情,在我的Fragment oncreate中实现我自己的Response.Listener和Response.ErrorListener(而不是StepA( );)和它工作!!!

Before using the RequestFuture methods, i basically did the same thing implementing my own Response.Listener and Response.ErrorListener in my Fragment oncreate(instead of the StepA();) and it WORKED!!!

以下是代码片段:

JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, mBuilder.getURL("box"), (String) null, new Response.Listener<JSONObject>() {
            @Override
            public void onResponse(JSONObject response) {
                parseJsonFeed(response);
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Toast.makeText(getActivity(), error.toString(), Toast.LENGTH_LONG).show();
            }
        });
        requestQueue.add(request);

所以我的问题是为什么当我实现请求未来方法时它不起作用?

So my question is why doesn't it work when i implement the request future methods?

如果你问我为什么要进行同步截击实施;这是因为在此之后我必须再有两个截击请求,这些请求完全依赖于此请求,成功完成。而且我也在学习:)

If you ask me why i want to go for synchronous volley implementation; it is because after this i have to have two more volley requests which depend on this request being fully, successfully completed. And also i'm learning :)

推荐答案

很遗憾没有人可以帮助回答这个问题,但我设法解决了这个问题如下所示:

Sad that no-one could help answer this question but i managed to solve this issue like below:

如果RequestFuture.get()与UI线程在同一个线程上,则会发生超时。我已经更改了请求的机制,以便请求在单独的Asynch线程(而不是UI线程)上完成,并且响应也在请求的单独线程上接收,如下所示:

The timeout will happen to the RequestFuture.get() if it is on the same thread as the UI thread. I have changed the mechanism of the request so that the request is done on a separate Asynch thread(not UI thread) and the response is also received on a separate thread from the request like below:

private void StepA() {
        Log.d("RT", "StepA initiated");
        final CountDownLatch latchA = new CountDownLatch(1);

        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                Log.d("RT", "Thread t Begins");
                ThreadA threadA = new ThreadA();
                try {
                    JSONObject jsonObject = threadA.execute().get(10, TimeUnit.SECONDS);
                    parseA(jsonObject);
                    latchA.countDown();
                    Log.d("RT", "Thread t Ends");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (ExecutionException e) {
                    e.printStackTrace();
                } catch (TimeoutException e) {
                    e.printStackTrace();
                }
            }
        });
        t.start();
        try {
            latchA.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Log.d("RT", "StepA END");
    }

以下是请求的Asynch任务代码:

Below is the Asynch task code for the request:

protected class ThreadA extends AsyncTask<Void, Void, JSONObject> {
    final String url = mBuilder.getURL("box");

    public ThreadA() {
    }

    @Override
    protected JSONObject doInBackground(Void... params) {
        final RequestFuture<JSONObject> future = RequestFuture.newFuture();
        JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, url, (String) null, future, future);
        requestQueue.add(request);
        try {
            return future.get(10, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }
        return null;
    }
}

我添加了倒计时锁存器因为它们很棒而且很棒也导致我在我的程序中有更多这样的请求依赖于这个代码片段的响应。因此,它们可以帮助更加同步地运行程序。

I've added countdown latches cause they are awesome and also cause i have few more requests like this in my program that depend on this snippet's response. Hence they help run the program more synchronously.

这篇关于使用RequestFuture.get()时Android排名超时异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆