【问题标题】:kills an Android AsyncTask with a timeout用超时杀死一个 Android AsyncTask
【发布时间】:2015-09-03 09:47:51
【问题描述】:

所以我的问题是我有一个 AsyncTask 从服务器上的页面中删除 html,所以我使用 Jsoup 作为库。 所以问题是如果我没有从页面接收到任何数据并显示吐司上存在“通信错误”,我想设置一个超时来取消任务

是否有办法杀死或停止其中的异步任务并在 onPostExecute 上返回结果

{
private class getPageTitle extends AsyncTask<Void, Void, String> {
        String title;

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            connectServerProgressDialog = new ProgressDialog(LoginScreen.this);
            connectServerProgressDialog.setTitle("CheckingServer");
            connectServerProgressDialog.setMessage("Loading...");
            connectServerProgressDialog.setIndeterminate(true);

            connectServerProgressDialog.show();
        }

        @Override
        protected String doInBackground(Void... params) {


            try {

                // Connect to the web site
                                Document document = Jsoup.connect(CONNECT_URL).get();

                            title = document.title();

                           } catch (IOException e) {

                e.printStackTrace();
            }

            return null ;
        }

        @Override
        protected void onPostExecute(String result) {

            if(result!=null){

            switch (title) {
                case "0":
                    Toast.makeText(LoginScreen.this,"offline",Toast.LENGTH_SHORT).show();
                    connectServerProgressDialog.dismiss();
                    break;
                case "1":
                    connectServerProgressDialog.dismiss();
                     Toast.makeText(LoginScreen.this,"Connected",Toast.LENGTH_SHORT).show();
                    break;

            }}else{
                Toast.makeText(LoginScreen.this,"Communication error",Toast.LENGTH_SHORT).show();
            }

            }
        }}

【问题讨论】:

标签: java android android-asynctask timeout jsoup


【解决方案1】:

我有一个用于AsyncTask 子类的约定。

  • 定义供客户端使用的内部接口。这将客户端类解耦,以便可以重用AsyncTask。该接口以blahblahListener 的形式命名。
  • 接口有blahblahCompleted()blahblahException()形式的两种方法。
  • 接受作为该接口实现的回调对象(侦听器)。这可以在 AsyncTask 构造函数中传递,也可以通过 setListener() 方法设置。
  • 将该侦听器引用保存在 WeakReference 字段中,以便如果侦听器在任务完成之前离开,侦听器仍然可以被垃圾回收。
  • 定义一个字段来保存Exception。如果后台方法发生异常,该字段会记住该异常以便向客户端报告。
  • onPostExecute()方法中,检查Exception字段是否为空。如果是,请使用结果调用blahblahCompleted()。如果不是,请致电blahblahException(),但有例外。还要检查WeakReference 是否仍然有效。

为了终止任务,您可以在连接上设置超时。然后当你的连接超时时,你会得到一个异常,它会被记住并报告。

因此,使用该约定,您的代码将如下所示:

public class WebPageTitleRemoteTask extends AsyncTask<URL, Void, String> {

    private WeakReference<WebPageTitleRetrievalListener> mListener;

    private Exception mException;

    public WebPageTitleRemoteTask(WebPageTitleRetrievalListener listener) {
        super();
        mListener = new WeakReference<WebPageTitleRetrievalListener>(listener);
    }

    @Override
    protected String doInBackground(URL... params) {

        String title = null;

        try {
            // Connect to the web site
            Document document = Jsoup.connect(params[0]).get();
            title = document.title();

        } catch (IOException e) {
            mException = e;
        }

        return title;
    }

    @Override
    protected void onPostExecute(String result) {

        WebPageTitleRetrievalListener listener = mListener.get();
        if (listener != null) {
            if (mException == null) {
                listener.webPageTitleRetrieved(result);
            } else {
                listener.webPageTitleRetrievalException(mException);
            }
        }
    }

    public static interface WebPageTitleRetrievalListener {

        public void webPageTitleRetrieved(String title);

        public void webPageTitleRetrievalException(Exception e);
    }

}

您的客户端代码看起来像这样,您的 Activity 实现了该内部接口:

    .
    .
    .
    connectServerProgressDialog = new ProgressDialog(LoginScreen.this);
    connectServerProgressDialog.setTitle("CheckingServer");
    connectServerProgressDialog.setMessage("Loading...");
    connectServerProgressDialog.setIndeterminate(true);

    connectServerProgressDialog.show();

    new WebPageTitleRemoteTask(this).execute(url);
    .
    .
    .

@Override
public void webPageTitleRetrieved(String title) {

    if (isFinishing()) return;
    connectServerProgressDialog.dismiss();
    Toast.makeText(this, "title = " + title, Toast.LENGTH_SHORT).show();
}

@Override
public void webPageTitleRetrievalException(Exception e) {

    if (isFinishing()) return;
    connectServerProgressDialog.dismiss();
    Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT).show();
}

注意:由于侦听器保存在 WeakReference 中,因此您不能为侦听器使用匿名内部类,因为引用几乎会立即消失并有资格进行垃圾回收。

我一直使用这个约定,AsyncTask 子类中的额外样板代码使其在客户端类中使用起来更加简洁。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-13
    • 2012-05-03
    • 1970-01-01
    相关资源
    最近更新 更多