在我的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帧,这对我来说是一个完全的谜。这个想法来源于这个repo:
https://github.com/levinotik/ReusableAsyncTask/tree/master/src/com/example所以在执行了一些基准测试之后,我得出结论,挂起的线程是由makeJson()
内部的加密设置引起的。
在我看来,唯一可以消耗大量时间的UI线程在你的代码是makeJson()方法。
但是你不应该在你的AsyncTask中保持对Activity的强引用,当Activity被重新创建(或销毁)时,你的AsyncTask可能仍在运行并持有对"死"Activity的引用。简单的解决方案是取消AsyncTask时,活动销毁。