【问题标题】:Generic AsyncTask approach interferes with UI thread通用 AsyncTask 方法会干扰 UI 线程
【发布时间】:2016-12-19 14:29:04
【问题描述】:

在我的 Android 应用程序中构建并发 HTTP 服务的过程中,我遇到了一种很好的方法来处理 AsyncTask 生成的结果,该方法使用接口将 UI 活动注册为侦听器:

public interface Activity {
   void callback(String result);
}

AsyncTask 类:

public class HTTP extends AsyncTask<String, Void, String> {

    private Activity activity;

    public HTTP(Activity activity) {
        this.activity = activity;
    }

    @Override
    protected String doInBackground(String... params) {
        try {
            URL url = new URL("http://" + params[0] + ":" + params[1] + "/" + params[2]);
            HttpURLConnection http = (HttpURLConnection) url.openConnection();
            http.setConnectTimeout(TIMEOUT);
            http.setRequestMethod("POST");
            http.setDoOutput(true);
            http.connect();

            ...

            return response;
        } catch (IOException e) {
            return "";
        }
    }

    @Override
    protected void onPostExecute(String result) {
        activity.callback(result);
    }
}

实际活动:

public class CreateActivity extends AppCompatActivity implements Activity {

    public void callback(String result) {
        if (result.isEmpty()) {
            toast(result);
        } else {
            Intent i = new Intent(this, ConfigActivity.class);
            startActivity(i);
            this.finish();
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_create);

    Button mCreateButton = (Button) findViewById(R.id.create_button);
    assert mCreateButton != null;
    mCreateButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            host = mHostEditText.getText().toString();
            port = mPortEditText.getText().toString();
            data = mDataEditText.getText().toString();

            if (host.isEmpty() || port.isEmpty() || data.isEmpty()) {
                toast(ERR_EMPTY_FIELDS);
            } else {
                new HTTP(CreateActivity.this).execute(host, port, "ai", makeJson());
            }
        }
    });
}

根据 logcat,这种方法仍然会阻塞调用线程将近 200 帧,这对我来说完全是个谜。 这个想法来源于这个回购:

https://github.com/levinotik/ReusableAsyncTask/tree/master/src/com/example

提前致谢。

【问题讨论】:

  • makeJson() 需要很长时间吗?
  • 不应该。使用 Google 的 GSON 将一个小对象转换为字符串。

标签: java android user-interface concurrency android-asynctask


【解决方案1】:

所以在执行了一些基准测试后,我得出结论,挂起线程是由makeJson() 内部的加密设置引起的。

因此,AsyncTask 应该没问题。

【讨论】:

  • 如果您将小对象本身而不是 json 表示形式传递给它,您可以将 makeJson() 移动到 AsyncTask 中。
【解决方案2】:

在我看来,唯一会在代码中的 UI 线程上消耗大量时间的是 makeJson() 方法。

但是您不应该在 AsyncTask 中持有对 Activity 的强引用,当重新创建(或销毁)Activity 时,您的 AsyncTask 可能仍在运行并持有对“死”Activity 的引用。 Simples 的解决方案是在 Activity 销毁时取消 AsyncTask。

【讨论】:

    猜你喜欢
    • 2012-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-02
    • 1970-01-01
    • 2014-12-11
    • 2013-02-25
    相关资源
    最近更新 更多