【问题标题】:can't get Json from AsyncTask无法从 AsyncTask 获取 Json
【发布时间】:2016-08-16 14:07:03
【问题描述】:

问题是我无法从我的 doInBackground 获取 JSON 结果。我知道我需要一个处理程序并使用 onPostExecute,但我无法使其工作。我有一个控制器负责从 AsyncTask 扩展连接。我在主线程上调用了 controller.execute(),它给了我一个 AsyncTask 对象而不是 JSON。 这是控制器:

final MediaType JSON
        = MediaType.parse("application/json; charset=utf-8");

@Override
protected String doInBackground(String... params){
    try {
        JSONObject newJson = new JSONObject(params.toString());

        String dirArchivo =  "http://10.0.2.2/SoulStoreProject/"+newJson.get("dir");

        OkHttpClient client = new OkHttpClient();

        RequestBody body = RequestBody.create(JSON, newJson.toString());
        Request request = new Request.Builder()
            .url(dirArchivo)
            .post(body)
            .build();
        Response response = client.newCall(request).execute();
        return response.body().string();
    } catch (IOException e) {
        return e.getMessage().toString();
    } catch (JSONException e) {
        return e.getMessage().toString();
    }
}

这是主类:

JSONObject requestObject = new JSONObject();
     requestObject.put("nick", txtNicklog.getText().toString());
     requestObject.put("password", txtPasslog.getText().toString());
     requestObject.put("dir", "devolverJugador.php");

String result = Controller.execute(requestObject);

JSONObject resultFromAsyncTask= new JSONObject(result);

我不知道在哪里编写处理程序以及如何从 onPostExecute 调用它。或者如果有其他方法可以解决它,我愿意接受建议

【问题讨论】:

    标签: android json android-asynctask handler okhttp3


    【解决方案1】:

    这里的问题是关于了解异步任务的工作原理。当您调用Controller.execute(requestObject) 时,它将在后台线程中运行(脱离主线程),控制权将传递到下一行。

    因此,当控制到达 JSONObject resultFromAsyncTask= new JSONObject(result); 时,您的 response尚未被获取。

    除此之外,我不知道你是如何编译这个的:

    String result = Controller.execute(requestObject);
    

    无论如何,我建议你不要使用AsyncTask,而是使用OkHttp的异步调用来发出网络请求。

    OkHttpClient client = new OkHttpClient();
    
    RequestBody body = RequestBody.create(JSON, newJson.toString());
    Request request = new Request.Builder()
                .url(dirArchivo)
                .post(body)
                .build();
    client.newCall(request).enqueue(new Callback() {
          @Override
          public void onFailure(Call call, IOException e) {
               e.printStackTrace();
          }
    
          @Override
          public void onResponse(Call call, final Response response) throws IOException {
               if(resonse.isSuccessful(){
                    //Running on UI thread, because response received is NOT on UI thread.
                    new Handler(Looper.getMainLooper()).post(new Runnable() {
                       @Override
                       public void run() {
                          //use response to update any UI component
                       }
                    });
               }
            }
        });
    

    注意:我假设您使用的是最新版本的OkHttp,即3.2.0

    【讨论】:

    • 我认为您不需要 new Handler 片段在主线程上运行。回调返回到正确的位置,但如果您确实需要处理程序,则应在参数中将response 设为final
    • @cricket_007,我已将Response 更改为final,感谢您指出。但我不同意你的第一点。 OkHttp对主线程和onResponseruns on background thread一无所知。
    • 我通常坚持使用 Volley,所以我可能错了,但我确实在 Square 的 Github 上找到了这个 sample code for asynchronous GET
    • 问题是我需要控制器是通用的,我需要经常使用它,所以我不能在那里更新 UI 组件,这就是我在 Main 上使用变量的原因。我无法编译它,这就是返回 AsyncTask 对象的问题,我需要一个 String 或 Json 对象。但我喜欢使用 okhttp 的想法,谢谢
    • @MartinChocho,你把它当作一个通用函数,使用interface获取数据
    【解决方案2】:

    AsyncTask 实例的方法 execute() 不会返回 json 开始异步执行。因此,这一行String result = Controller.execute(requestObject); 不会等到 AsynTask 完成才将 json 返回到 result 变量,asynctask 正在第二个线程中运行。

    如果你想停止一切并等待异步任务完成,你必须调用方法get:String result = Controller.execute(requestObject).get();。但是,请记住,您将冻结您的 UI,这并不好!最好的方法是异步运行 AsynTask 并在 onPostExecute() 方法中处理 json。

    【讨论】:

      猜你喜欢
      • 2012-05-21
      • 2016-10-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-17
      • 2013-11-18
      • 2013-03-02
      相关资源
      最近更新 更多