【问题标题】:Why does the getInputStream() method of HttpURLConnection return an object of type RealBufferedSource?为什么HttpURLConnection的getInputStream()方法返回的是RealBufferedSource类型的对象?
【发布时间】:2019-05-27 18:42:12
【问题描述】:

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

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 类扩展了InputStream,所以我认为使用

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

可以,但问题是:

我的代码中有一个ClassCastException,因为connection.getInputStream() 返回一个com.android.okhttp.okio.RealBufferedSource$1 类型的对象。为什么getInputStream 没有按照Java documentation 返回InputStream?这是 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;
    }
}

【问题讨论】:

标签: java android android-asynctask inputstream httpurlconnection


【解决方案1】:

getInputStream() 方法确实返回一个InputStream。但是您正试图将结果转换为ResponseBody。除非结果对象是 ResponseBody 的子类型的实例,否则这将不起作用。

现在,不清楚您在这里尝试使用哪个ResponseBody 类,但如果它是okhttp3.ResponseBody (javadoc),那么您无法通过转换InputStream 来获得它。


我实际上自己定义了ResponseBody 类。它是InputStream 的简单扩展(见编辑),所以我觉得向下转换应该可以工作

啊。我明白了。

不,那是行不通的。您不能将对象转换为它不是的类型。这不是类型转换所做的......对于引用类型。

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

  com.android.okhttp.okio.RealBufferedSource$1

这是InputStream 的子类型。您正在尝试将其转换为 ResponseBody,它也是 InputStream 的子类型。但是ResponseBody不是匿名类的超类或接口,所以typecast不能成功。

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

【讨论】:

  • 感谢您的回答!我实际上自己定义了 ResponseBody 类。它是 InputStream 的一个简单扩展(见编辑),所以我似乎向下转换应该可以工作
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-31
相关资源
最近更新 更多