为啥我的 AsyncTask 会冻结我的 UI 线程?

Posted

技术标签:

【中文标题】为啥我的 AsyncTask 会冻结我的 UI 线程?【英文标题】:Why does my AsyncTask freeze my UI Thread?为什么我的 AsyncTask 会冻结我的 UI 线程? 【发布时间】:2020-01-05 06:40:37 【问题描述】:

我有这个问题:当我在表单中插入和提交数据时,我希望 AsyncTask 开始检查一切是否正常。 在我现在面临的具体情况下,我想验证输入的用户名是否尚未使用,所以我希望它去服务器并通过 php 查询用户的数据库。 我希望当整个事情开始时,用户屏幕不被阻塞,也就是说,我希望用户无论如何都可以在屏幕内移动。

附上代码:

public class ControlloUsername extends AsyncTask<String, Void, String> 

AlertDialog a;
Context context;

public ControlloUsername(Context ct) 
    // TODO Auto-generated constructor stub
    context = ct;


@Override
protected void onPreExecute() 
    // TODO Auto-generated method stub


@Override
protected void onPostExecute(String result)  //sync
    // TODO Auto-generated method stub


@Override
protected void onProgressUpdate(Void... values) 
    // TODO Auto-generated method stub


@Override
protected String doInBackground(String... params)  //sync
    // TODO Auto-generated method stub

    String username = params[0];
    String login_url = Connector.db + "script/usercontrol.php";
    String resultado = "";

    URL u = null;
    try 
        u = new URL(login_url);
     catch (MalformedURLException e) 
        Writer writer = new StringWriter();
        e.printStackTrace(new PrintWriter(writer));
        resultado = writer.toString();
    
    HttpURLConnection http = null;
    try 
        http = (HttpURLConnection) u.openConnection();
     catch (IOException e) 
        Writer writer = new StringWriter();
        e.printStackTrace(new PrintWriter(writer));
        resultado = writer.toString();
    
    try 
        http.setRequestMethod("POST");
     catch (ProtocolException e) 
        Writer writer = new StringWriter();
        e.printStackTrace(new PrintWriter(writer));
        resultado = writer.toString();
    
        http.setDoInput(true);
        http.setDoOutput(true);


        http.setConnectTimeout(7000);


    try 
        OutputStream out = http.getOutputStream();
        BufferedWriter bf = new BufferedWriter(new OutputStreamWriter(out, "UTF-8"));
        String post_data = URLEncoder.encode("username", "UTF-8") + "=" + URLEncoder.encode(username, "UTF-8");
        bf.write(post_data);
        bf.flush();
        bf.close();
        out.close();
        InputStream in = http.getInputStream();
        BufferedReader br = new BufferedReader(new InputStreamReader(in, "iso-8859-1"));
        String result = "";
        String line = "";
        while ((line = br.readLine()) != null) 
            result += line;
        
        bf.close();
        in.close();
        http.disconnect();
        return result;
     catch (ConnectException e) 
        Writer writer = new StringWriter();
        e.printStackTrace(new PrintWriter(writer));
        resultado = "CONNECT" + writer.toString();
        Log.d("PRINT", "CONNECT");
     catch (UnsupportedEncodingException e) 
        Writer writer = new StringWriter();
        e.printStackTrace(new PrintWriter(writer));
        resultado = "UNSUPPORTEDENCODING" + writer.toString();
        Log.d("PRINT", "UNSUPPORTEDENCODING");
     catch (ProtocolException e) 
       Writer writer = new StringWriter();
        e.printStackTrace(new PrintWriter(writer));
        resultado = "PROTOCOL" + writer.toString();
        Log.d("PRINT", "PROTOCOL");
     catch (MalformedURLException e) 
        Writer writer = new StringWriter();
        e.printStackTrace(new PrintWriter(writer));
        resultado = "MALFORMEDURL" + writer.toString();
        Log.d("PRINT", "MALFORMEDURL");
     catch (IOException e) 
        Writer writer = new StringWriter();
        e.printStackTrace(new PrintWriter(writer));
        resultado = "IO" + writer.toString();
        Log.d("PRINT", "IO");
    
    return resultado;


注册活动

String u = user.getText().toString();
            ControlloUsername bg = new ControlloUsername(this);
            try 
                String res = bg.execute(u).get();
                Log.d("PRINT", res);
                if (res.contains("...

我读到这是execute().get()和AsyncTask自己的方法的问题。

【问题讨论】:

您可能需要重新考虑您的方法并改用 Kotlin 协程... AsyncTask 是过去的方式... 因为 .get() 使您的 AsyncTask 同步运行。 @OveStoerholt 是否可以使用java @VladyslavMatviienko 我知道。只是想为他指明正确的方向(即 Kotlin);-) @OveStoerholt 这不是正确的方向,而是您的意见。 *** 上没有发表意见的地方。 【参考方案1】:

您可以在AsyncTask 完成后使用接口获取结果。在您的 AsyncTask 中:

onFinishListener mListener; // Create a variable for your interface

// Define the interface & callbacks
public interface onFinishListener
    // Replace 'variableType' with the appropriate type for your result
    void onFinish(variableType myResult);


public void setOnFinishListener(onFinishListener l)
    mListener = l;


@Override
protected void onPostExecute(variableType result)
    if(mListener != null)
        mListener.onFinish(result);
    

然后在您的 Activity 中,确保设置界面:

MyAsyncTask task = new MyAsyncTask();
task.execute();
task.setOnFinishListener(new MyAsyncTask.onFinishListener()
    @Override
    public void onFinish(variableType myResult)
        // The task has finished and you can now use the result
    
);

【讨论】:

如果我不需要妥协任何东西并且可以毫无问题地将它集成到我的代码中,我会稍后尝试。谢谢。 谢谢!这种方法似乎工作正常。我不得不稍作改动,但这很容易:我必须处理全局变量,以前我也可以使用局部变量。我还包括了一个不错的进度对话框!再次感谢你! :)

以上是关于为啥我的 AsyncTask 会冻结我的 UI 线程?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的 pyqt 信号错误会冻结 ui,直到调用另一个 python 函数

为啥我的 QThreads 总是让 Maya 崩溃?

为啥 STDIN 会导致我的 Perl 程序冻结?

为啥Android的AsyncTask不适合执行长时间操作的任务

为啥我的输出在到达这部分代码时会冻结?

异步任务阻塞 UI 线程