请求网络接口出错:android.os.NetworkOnMainThreadException

调试了好久,才发现是因为Http请求写在了主线程里,在4.0之后在主线程里面执行Http请求都会报这个错,大概是怕Http请求时间太长造成程序假死的情况吧。

//于是我改写了函数,在函数里面创建了线程调用网络请求,但函数return值返回是空的,估计是线程还未执行完就返回了,我是一名android初学者,想请教一下各位,怎样改写下面这个函数,我想在程序其它地方直接调用 GetJSonData(),就得到我想要的返回结果。

public String GetJSonData() {
            String responseJSON = "";
    new Thread(new Runnable() {
        @Override
        public void run() {
            responseJSON =  TO DO http request.
        }
    }).start();
    return responseJSON;
     }

你的分析是对的,这里需要异步返回。线程内完成后,给ui线程post一个event。new Handler(Looper.mainLooper()).postRunnable(...)

异步任务想要使用直接返回,可以使用kotlin的协程。
java无法做到,java只能等到异步任务结束后,通过接口或者其它方式回调

网络请求等耗时操作需要花一定时间才能得到结果,所以用返回值的方式是不行的。一般都在请求成功后通过回调函数将结果传递出来。

这里涉及一个同步与异步的问题,开启线程执行网络请求,java是按照顺序从上往下执行的,除非使用 Thread.sleep(); 等函数卡住主线程,不然的话,如同上图代码,启动线程,然后下一步就到了 return responseJSON;这里了,这时候线程里没执行完,结果还没返回赋值给 responseJSON,所以导致返回时空的。这里应该改造一下,等网络请求结束再返回数据。
可以使用Handler 或者 接口回调等,例如:

  public interface OnResultCallBack {
        void onResultCallBack(String responseJSON);
    }
    public void GetJSonData(OnResultCallBack callBack) {

        new Thread(new Runnable() {
            @Override
            public void run() {
              String  responseJSON =  TO DO http request;
                callBack. onResultCallBack(responseJSON);
            }
        }).start();

    }