Volley使用时InterruptedIOException,NoConnectionError

类似问题链接random com.android.volley.NoConnection error, java.io.InterruptedIOException
在项目中使用了Volley,做了一下简单封装,然后犯了个错误。。。
代码如下:

 /**
     * @param tag              标识
     * @param networkLostTouch 无网络访问时的回调接口
     */
    public static  void addQueue(Request request, String tag, OnNetworkLostTouch networkLostTouch) {
        //如果request为空,则不予加入请求队列
        if (request == null) {
            return;
        }
        //如果tag标识为空或者空字符串,那么应给予warn,但是仍能继续请求网络
        if (StringUtils.isBlank(tag)) {
            LogCus.w("此次的网络请求未设置有效的tag,将无法通过cancleRequest取消网络请求");
        }

        //先检查网络是否可用
        if (!NetWorkUtils.isNetworkConnected()) {
            networkLostTouch.lostTouch(ResourceUtils.getString(R.string.network_not_avaliable));
            return;
        }

        request.setRetryPolicy(
                new DefaultRetryPolicy(
                        DEFAULT_TIMEOUT_MS,//默认超时时间
                        DefaultRetryPolicy.DEFAULT_MAX_RETRIES,//默认最大尝试次数
                        DefaultRetryPolicy.DEFAULT_BACKOFF_MULT
                )
        );

        request.setTag(tag);
        mTags.add(tag);
        mRequestQueue.add(request);

        //我去,妹的纠结了很久的"com.android.volley.NoConnectionError: java.io.InterruptedIOException"原来就是因为增加了这句话
//        mRequestQueue.start();
    }

错误就是在最后调用了RequestQueue.start()方法,引起的问题“经常会报com.android.volley.NoConnectionError: java.io.InterruptedIOException”,然后就内容加载失败。。。
最后在stackoverflow中找到Michael Cheng的答案,就是应该去掉start方法的调用。

以下内容是看了下源码,分析下为什么调用了此方法之后会经常出现InterruptedIOException

实际上volley在初始化RequestQueue时,已经调用了start方法,代码如下:

public static RequestQueue newRequestQueue(Context context, HttpStack stack) {
    File cacheDir = new File(context.getCacheDir(), DEFAULT_CACHE_DIR);

    String userAgent = "volley/0";
    try {
        String packageName = context.getPackageName();
        PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0);
        userAgent = packageName + "/" + info.versionCode;
    } catch (NameNotFoundException e) {
    }

    if (stack == null) {
        if (Build.VERSION.SDK_INT >= 9) {
            stack = new HurlStack();
        } else {
            // Prior to Gingerbread, HttpUrlConnection was unreliable.
            // See: http://android-developers.blogspot.com/2011/09/androids-http-clients.html
            stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
        }
    }

    Network network = new BasicNetwork(stack);

    RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network);
    queue.start();

    return queue;
}

而调用start方法时, volley will call stop to “make sure any currently running dispatchers are stopped”,in stop method volley does this below:

public void stop() {
    if (mCacheDispatcher != null) {
        mCacheDispatcher.quit();
    }
    for (int i = 0; i < mDispatchers.length; i++) {
        if (mDispatchers[i] != null) {
            mDispatchers[i].quit();
        }
    }
}

and the quit method does this below:

 public void quit() {
    mQuit = true;
    interrupt();
}

maybe you can see the reason,why interrupted.
More, interrupt method does this below:

public void interrupt() {
    // Interrupt this thread before running actions so that other
    // threads that observe the interrupt as a result of an action
    // will see that this thread is in the interrupted state.
    nativeInterrupt();

    synchronized (interruptActions) {
        for (int i = interruptActions.size() - 1; i >= 0; i--) {
            interruptActions.get(i).run();
        }
    }
}

the reason maybe this as metioned above:

Interrupt this thread before running actions so that other threads that observe the interrupt as a result of an action will see that this thread is in the interrupted state.

也可以直接在stackoverflow中查看我写的答案,我的名字是xiaoyee

你可能感兴趣的:(android,volley,exception)