OkHttp的坑:response.body().string() 只能調用一次

發現:

在接微信登錄時,通過構造 OkHttpClient 對象發起一次請求並加入隊列,待服務端響應後,回調 Callback 接口觸發 onResponse() 方法,然後在該方法中通過 Response 對象處理返回結果、實現業務邏輯。

大致代碼如下:

  private void getUserInfo() {
        String path = "https://api.weixin.qq.com/sns/userinfo?access_token=" + accessToken + "&openid=" + openid;
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url(path)
                .build();
        Call call = client.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.d(TAG, "onFailure: userinfo" + e.getMessage());
                finish();
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
//                Log.d(TAG, "onResponse: userinfo" + response.body().string());    //okhttp中 response.body().string()只允許調用一次

                final String result = response.body().string();
                try {
                    JSONObject jsonObject = new JSONObject(result);
                    unionId = jsonObject.getString("unionid");
                    headImgUrl = jsonObject.getString("headimgurl");
                    nickname = jsonObject.getString("nickname");
                    Log.d(TAG,"getUserInfo: unionId = "+unionId+"  headImgUrl = "+ headImgUrl + "  nickname = "+ nickname);
                } catch (JSONException e) {
                    e.printStackTrace();
                }
                finish();
            }
        });
    }

在 onResponse() 中,爲便於調試,我打印了返回體,然後通過 parseResponseStr() 方法解析返回體(注意:這兒兩次調用了 response.body().string())。

這段看起來沒有任何問題的代碼,實際運行後卻出了問題,,通過debug發現result在轉換成jsonObject時爲null。

那爲什麼result會變爲null呢?通過網上資料查閱發現,response.body().string()只能調用一次,調用完就會釋放掉資源,恍然大悟。。。然後我點進源碼看了一下:

public final String string() throws IOException {
    BufferedSource source = source();
    try {
      Charset charset = Util.bomAwareCharset(source, charset());
      return source.readString(charset);
    } finally {
      Util.closeQuietly(source);
    }
  }

Util.closeQuietly(source);
很棒,原來在我們調用了response.body的String()方法之後OkHttp 將響應體的緩衝資源返回的同時,調用 closeQuietly() 方法默默釋放了資源。就是這個原因了。Get√

參考:OkHttp踩坑記:爲何 response.body().string() 只能調用一次?

多問多看吧!

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章