java - 为什么 HttpURLConnection 的 getInputStream() 方法返回 RealBufferedSource 类型的对象?

标签 java android android-asynctask inputstream httpurlconnection

我正在尝试从 AsyncTask 发送 HTTP 请求在 Android Studio 中,使用下面的代码。

protected Long doInBackground(URL... urls) {
    try {
        HttpURLConnection connection = (HttpURLConnection) urls[0].openConnection();
        connection.setRequestMethod("POST");
        connection.connect();

        byte[] loginRequestBytes = new Gson().toJson(loginRequest, LoginRequest.class).getBytes();
        connection.getOutputStream().write(loginRequestBytes);

        if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
            ResponseBody responseBody = (ResponseBody) connection.getInputStream(); // ResponseBody extends InputStream
            loginResponse = new Gson().fromJson(responseBody.toString(), LoginResponse.class);
        }
    } catch (IOException e) {
        Log.e("HttpClient", e.getMessage(), e);
    }

    return null;
}

我的ResponseBody类(class)扩展InputStream ,所以我认为使用

ResponseBody responseBody = (ResponseBody) connection.getInputStream();

可以,但问题是:

我收到了 ClassCastException在我的代码中,因为 connection.getInputStream()返回 com.android.okhttp.okio.RealBufferedSource$1 类型的对象。为什么是getInputStream不返回InputStream根据Java documentation ?这是 Android 特有的问题吗?

编辑:我自己定义了 ResponseBody 类(如下所示)。它不是 okhttp 中的那个,并且它确实扩展了 InputStream据我所知。

public class ResponseBody extends InputStream {

    @Override
    public String toString() {
        StringBuilder stringBuilder = new StringBuilder();
        String line;

        try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(this, "UTF-8"))) {
            while ((line = bufferedReader.readLine()) != null) {
                stringBuilder.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return stringBuilder.toString();
    }

    @Override
    public int read() throws IOException {
        return 0;
    }
}

最佳答案

getInputStream() 方法确实返回一个InputStream。但您正尝试将结果转换为 ResponseBody。除非结果对象是 ResponseBody 子类型的实例,否则这是行不通的……但事实并非如此。

现在,尚不清楚您要在此处使用哪个 ResponseBody 类,但如果它是 okhttp3.ResponseBody ( javadoc ),那么您就不能通过转换InputStream 来获取它。

<小时/>

I actually defined the ResponseBody class myself. It is a simple extension of InputStream (see edit), so I seems like the downward cast should work

啊。我明白了。

不,那是行不通的。您不能将对象转换为它不是的类型。对于引用类型来说,这不是类型转换的作用。

您有一个匿名内部类的实例

  com.android.okhttp.okio.RealBufferedSource$1

它是InputStream的子类型。您试图将其转换为 ResponseBody,它也是 InputStream 的子类型。但 ResponseBody 不是匿名类的父类(super class)或接口(interface),因此类型转换无法成功。

我建议您将 ResponseBody 重写为 InputStream 的包装类和/或使用此处列出的解决方案之一来提取 InputStream 的内容String:

关于java - 为什么 HttpURLConnection 的 getInputStream() 方法返回 RealBufferedSource 类型的对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53983946/

相关文章:

c# - 如何在 Task.factory.fromAsync 中使用 void 方法

安卓异步任务

java - 如何重置 Eclipse 源/排序成员设置?

java - 删除某些空白

java - 将 Primefaces 从 3.2 更新到 3.4 会抛出 java.lang.NoSuchFieldError : SKIP_ITERATION

android - 当列名相同时,如何表示与 Android Room 的 "many to many"关系?

java - 在 Asynctask 的 onPostExecute() 方法中更改 fragment

Java数组/逆新手

android - 在哪里重新创建 Activity ?

android - C2DM 服务器。我们现在应该使用 OAuth 吗?