当我尝试 return http 响应时应用程序崩溃

App crashing when I try and return http response

我做了一个 java class 来处理 HTTP post 请求,它以字符串形式发回结果。出于某种原因,当我发送请求时,我可以将响应打印到日志中,但是当 return 响应字符串更新 UI 时,我的应用程序崩溃了。任何人都可以解释这里发生了什么吗?我正努力在 java 方面做得更好,因此请指出任何其他不良做法,我们将不胜感激。

日志:

I/OpenGLRenderer: Initialized EGL, version 1.4
D/OpenGLRenderer: Swap behavior 1
D/NetworkSecurityConfig: No Network Security Config specified, using     platform default
D/OKHTTP3: Request body created
D/OKHTTP3: Request body created 2
D/OKHTTP3: Got Response
D/OKHTTP3: {
             "failed": "Asset already exists"
           }
E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1
              Process: com.example.john.okhttp, PID: 3166
              java.lang.RuntimeException: An error occurred while executing doInBackground()
                  at android.os.AsyncTask.done(AsyncTask.java:318)
                  at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354)
                  at java.util.concurrent.FutureTask.setException(FutureTask.java:223)
                  at java.util.concurrent.FutureTask.run(FutureTask.java:242)
                  at android.os.AsyncTask$SerialExecutor.run(AsyncTask.java:243)
                  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
                  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
                  at java.lang.Thread.run(Thread.java:761)
               Caused by: java.lang.IllegalStateException: closed
                  at okhttp3.internal.http.Http1xStream$FixedLengthSource.read(Http1xStream.java:374)
                  at okio.Buffer.writeAll(Buffer.java:993)
                  at okio.RealBufferedSource.readByteArray(RealBufferedSource.java:106)
                  at okhttp3.ResponseBody.bytes(ResponseBody.java:128)
                  at okhttp3.ResponseBody.string(ResponseBody.java:154)
                  at com.example.john.okhttp.PostEx.doPostRequest(PostEx.java:40)
                  at com.example.john.okhttp.MainActivity$Requesting.doInBackground(MainActivity.java:59)
                  at com.example.john.okhttp.MainActivity$Requesting.doInBackground(MainActivity.java:51)
                  at android.os.AsyncTask.call(AsyncTask.java:304)
                  at java.util.concurrent.FutureTask.run(FutureTask.java:237)
                  at android.os.AsyncTask$SerialExecutor.run(AsyncTask.java:243) 
                  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133) 
                  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) 
                  at java.lang.Thread.run(Thread.java:761) 
Application terminated.

来自两个 java 文件的代码将被 post 编辑如下:

MainActivity.java:

package com.example.john.okhttp;


import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import org.json.JSONObject;
import okhttp3.OkHttpClient;
import okhttp3.Request;



public class MainActivity extends AppCompatActivity {
    private Button btnSendHttpRequest;
    private EditText etJsonResponse;
    private TextView View;
    private TextView View2;
    private OkHttpClient okHttpClient;
    private Request request;
    public final String URL = "http://www.mocky.io/v2/582ac99c280000d50953c316";


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //set button and text view values
        btnSendHttpRequest = (Button) findViewById(R.id.btnSendRequest);
        View = (TextView) findViewById(R.id.view1);
        View2 = (TextView) findViewById(R.id.textView4);
        etJsonResponse = (EditText) findViewById(R.id.etjson);
        //response for button
        btnSendHttpRequest.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //http request
                PostEx example = new PostEx();
                new Requesting().execute();
            }
        });

    }

    public class Requesting extends AsyncTask<String, String, String> {
        // post request stuff
        @Override
        protected String doInBackground(String... params) {
            String id = "444454";
            String userName = "john";
            PostEx example = new PostEx();
            String jsonstr = example.makeJsonForUser(id, userName);
            if(example.doPostRequest(jsonstr)== null){
                Log.d("OKHTTP3", "null pointer");
            }
            String response = example.doPostRequest(jsonstr);
            Log.d("OKHTTP3", "sending response");
            return response;
        }


        @Override
        protected void onPostExecute(String response) {
         super.onPostExecute(response);
        //rewrite text view
         try {
            // create json ob from response
             if(response == null){
                 Log.d("OKHTTP3", "null pointer");
             }
            JSONObject jsonObj = new JSONObject(response);
            //get the values from the json key value pairs
            String id = jsonObj.toString();
            //update the text views
            TextView textView = (TextView) findViewById(R.id.view1);
            textView.setText(id);
         } catch (Exception e) {

           }
        }
    }
}

PostEx.java:

import android.util.Log;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;



public class PostEx  {
    public String doPostRequest(String jsonstr) {
        String url = "http://45.55.92.243/newuser";
        OkHttpClient client = new OkHttpClient();
        MediaType JSON = MediaType.parse("application/json; charset=utf-8");

       RequestBody body = RequestBody.create(JSON,jsonstr);
        Log.d("OKHTTP3","Request body created");
        Request newReq = new Request.Builder()
                .url(url)
                .post(body)
                .build();
        Log.d("OKHTTP3","Request body created 2");
        try {
           Response response = client.newCall(newReq).execute();
            Log.d("OKHTTP3","Got Response");
            Log.d("OKHTTP3",response.body().string());
            String Fresponse = response.body().string();
            response.close();
            return  Fresponse;
        } catch (IOException e) {
            Log.d("OKHTTP3","Got Exception");
            e.printStackTrace();
            return null;
        }

    }
  public String makeJsonForUser(String id, String Username){
        JSONObject data = new JSONObject();
        try {
            data.put("id", id);
            data.put("name", Username);
            return data.toString();
        } catch (JSONException e) {
            Log.d("OKHTTP3", "JSON Exeption");
            e.printStackTrace();
            return null;
        }
    }

 }

在 okhttp3.ResponseBody.string(ResponseBody.java:154):

  public final String string() throws IOException {
    return new String(bytes(), charset().name());
  }

在 okhttp3.internal.http.Http1xStream$FixedLengthSource.read(Http1xStream.java:374):

@Override public long read(Buffer sink, long byteCount) throws IOException {
      if (byteCount < 0) throw new IllegalArgumentException("byteCount < 0: " + byteCount);
      if (closed) throw new IllegalStateException("closed");
      if (bytesRemaining == 0) return -1;

      long read = source.read(sink, Math.min(bytesRemaining, byteCount));
      if (read == -1) {
        endOfInput(false); // The server didn't supply the promised content length.
        throw new ProtocolException("unexpected end of stream");
      }

      bytesRemaining -= read;
      if (bytesRemaining == 0) {
      endOfInput(true);
      }
      return read;
    }        

到目前为止,您的代码大部分都有效

D/OKHTTP3: Request body created
D/OKHTTP3: Request body created 2
D/OKHTTP3: Got Response

我记得读书,you can only receive the body string once

 //   Log.d("OKHTTP3",response.body().string());
String Fresponse = response.body().string();
// log Fresponse here 

并在捕获

之后关闭 finally 块中的资源

更重要的是你在使用 Okhttp。你不需要异步任务!在客户端调用对象

上使用 enqueue 方法而不是 execute
client.newCall(newReq).enqueue(new Callback() {
  // handle response here 
});

并且您正在处理 JSON,因此 Retrofit 将帮助您实现您已经尝试做的事情

问题是您可以调用 string() 一次。但是不知道为什么