AsyncTask冻结了它的线程和UI thrad

时间:2017-08-14 15:12:57

标签: java android multithreading android-asynctask

我已经创建了一个扩展AsyncTask的类,以便从我的应用程序向我的服务器发送POST请求。它一直在努力。我没有改变任何东西,但是当我尝试执行它时,它突然冻结了UI线程和它自己的线程。

我尝试使用Log.d()找出它在冻结前的位置,结果发现它在doInBackground()被调用后立即冻结。

我也试过改变这个......

String result = new AsyncPost().execute(params).get();

对此...

AsyncTask task = new AsyncPost();
task.execute();
String result = task.get();

它与我提供的参数无关,因为无论传递给它的参数是什么,它都会冻结。

我也尝试使用Postman来检查我的服务器是否正常工作(并且确实如此),因此它也不是服务器端问题。

这是我的AsyncTask课程。很抱歉代码过多,但我无法弄清楚它的哪个特定部分是坏的,因为它到目前为止一切正常。

public class AsyncPost extends AsyncTask<Object, Integer, String> {
    @Override
    protected String doInBackground(Object ... params){
        //android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_MORE_FAVORABLE);

        Object urlObj = params[0];
        Object argsObj = params[1];

        String urlStr = (String) urlObj;
        Map<String, String> args = (Map<String, String>) argsObj;

        URL url;
        HttpsURLConnection http = null;

        byte[] out = null;
        int len = 0;
        Log.d("POST", "STARTED");

        try {
            url = new URL(urlStr);

            http = (HttpsURLConnection) url.openConnection();
            http.setRequestMethod("POST");
            http.setDoOutput(true);

            StringJoiner sj = new StringJoiner("&");

            for (Map.Entry<String, String> entry : args.entrySet()) {
                sj.add(URLEncoder.encode(entry.getKey(), "UTF-8") + "="
                        + URLEncoder.encode(entry.getValue(), "UTF-8"));
            }

            out = sj.toString().getBytes(StandardCharsets.UTF_8);
            len = out.length;

            http.setFixedLengthStreamingMode(len);
            http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");

            http.connect();
            Log.d("POST", "CONNECTED");
        }

        catch (Exception e){
            e.printStackTrace();
            return null;
        }

        try (OutputStream os = http.getOutputStream()){
            os.write(out);
        }

        catch (Exception e){
            e.printStackTrace();
            return null;
        }

        try {
            Log.d("POST_RESPONSECODE", Integer.toString(http.getResponseCode()));
            BufferedReader responseReader = new BufferedReader(new InputStreamReader(http.getInputStream()));
            StringBuilder responseBuilder = new StringBuilder();
            String response;

            while ((response = responseReader.readLine()) != null){
                responseBuilder.append(response);
            }

            Log.d("POST", responseBuilder.toString());

            return responseBuilder.toString();
        }

        catch (Exception e){
            e.printStackTrace();
            return null;
        }

        finally{
            http.disconnect();
        }
    }

    @Override
    public void onProgressUpdate(Integer ... progress){
        Log.d("POST", "PROGRESS = " + Integer.toString(progress[0]));
    }
}

我该怎么做才能解决这个问题?

我是否应该使用AsyncTask完成此任务。我尝试过使用Thread,但也冻结了我的用户界面。

我看过其他问题,但他们似乎都在这样做......

Object result = new AsyncTask().get();

这是导致他们出现问题的原因,而这些问题并不适用于我。

2 个答案:

答案 0 :(得分:2)

在AsyncTask上调用get()基本上会阻塞该线程的执行,在你的情况下是主线程。 而不是你想要做的是在你的AsyncTask onPostExecute()方法(https://developer.android.com/reference/android/os/AsyncTask.html#onPostExecute(Result))中实现

答案 1 :(得分:1)

如果您不想在主线程上等待结果,则需要使用覆盖deployer.customProcessor.count=8方法中AsyncPost类使用的接口。不要忘记让接收类实现它:

AsyncPostListener

onPostExecute

MainActivity

interface AsyncPostListener {
    void continueWith(String result);
}

AsyncPost

@Override
public void continueWith(String results) {
    //continue your logic here
}

用法:

 public class AsyncPost extends AsyncTask<Object, Integer, String> {
    private AsyncPostListener listener;
    ....
    public AsyncPost(AsyncPostListener listener){
        this.listener = listener;
    }

    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);
        if(listener != null)
            listener.continueWith(s);
    }
}