使用RequestFuture.get()时Android排名超时异常

rap*_*ock 11 java android network-programming future android-volley

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

如果我使用RequestFuture.get(time,TimeUnit)方法来执行此排球请求,我总是会收到超时错误.如果我在Safari中手动测试相同的Url,我会立即得到结果.

我知道的:

1.)它不是任何JSON解析错误.(程序甚至没有进入解析步骤)

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

3.)我的凌空单件类或我的请求队列不是问题.(后来解释的原因).

所以我认为我在排球/请求未来的使用方面犯了另一个错误.

片段代码如下:

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");
    }
}
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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

以下是代码片段:

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);
Run Code Online (Sandbox Code Playgroud)

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

如果你问我为什么要进行同步截击实施; 这是因为在此之后我必须再提出两个完全成功完成的请求.而且我也在学习:)

rap*_*ock 16

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

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

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");
    }
Run Code Online (Sandbox Code Playgroud)

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

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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