尝试弹出一个警告框以响应 AsyncTask

Trying to get an alert box to popup in response to AsyncTask

我有一个应用程序,上面有一个大大的红色投票按钮。现在,我总是要求他们有一个 public IP 地址才能启用投票按钮。

我了解到我需要通过 AsyncTask 获取互联网内容,所以我做了一个新的 class 扩展它,称为 DetermineIP。这个过程有效,我能够获得一个 IP,因为我有一个只提供 IP 的网页。

我现在正在处理他们没有连接的情况。所以,我构建了一个警告框,上面有一个重试按钮。目标是让用户修复他们的连接问题,然后点击重试,直到他们获得 IP。

我想我似乎无法添加点击处理程序,因为它是从 AsyncTask 调用的。我得到: Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

我完全承认自己是个菜鸟,我真的只是想找到一种方法来实现这一目标。

public void fetchIP()
{
    // UPDATE LABELS
    Resources res = getResources();

    TextView textStatus = (TextView) findViewById(R.id.statusMessage);
    textStatus.setText(res.getString(R.string.status_determining_ip_address));

    enableVoteButton(false);

    String stringURL = res.getString(R.string.ip_url);
    URL urlIP = null;
    try {
        urlIP = new URL(stringURL);
    } catch (MalformedURLException e) {
        e.printStackTrace();
    }

    // start AsyncTask to fetch IP in the background
    getIP = new DetermineIP();
    getIP.setParent(this);
    getIP.execute(urlIP);
    m_working = true;

    // show a dialog box with message that we're determining the IP
    status_dialog = new Dialog(MainActivity.this);
    status_dialog.setCancelable(false);
    status_dialog.setContentView(R.layout.activity_ip);
    TextView textDialogStatus = (TextView) status_dialog.findViewById(R.id.textView);
    textDialogStatus.setText(R.string.status_determining_ip_address);
    status_dialog.show();
}

// If we were able to determine the IP address by fetching from a
// public web server then everything's good. Enable everything, and
// move along from there. Called from DetermineIP.onPostExecute.
public void setIP(String theIP)
{
    m_ip = theIP;

    TextView textStatus = (TextView) findViewById(R.id.statusMessage);
    textStatus.setText(m_ip);
    enableVoteButton(true);
    m_working = false;
    status_dialog.dismiss();
}

// If we were unable to determine an IP address, for whatever reason,
// show a retry alert box, when they hit retry, then start the process
// over again, maybe the user needs to solve a connectivity issue before
// retrying. Called from DetermineIP.onPostExecute.
public void setNoIP()
{
    Resources res = getResources();

    TextView textStatus = (TextView) findViewById(R.id.statusMessage);
    textStatus.setText(res.getString(R.string.status_unable_to_determine_ip_address));
    enableVoteButton(false);
    m_working = false;

    status_dialog.dismiss();
    RetryDialog();
}

// this is the dialog that informs the user that no IP was determined.
// clicking Retry will start the process of finding the IP again.
private void RetryDialog()
{
    Resources res = getResources();

    AlertDialog.Builder builder1 = new AlertDialog.Builder(MainActivity.this);
    builder1.setMessage(res.getString(R.string.status_unable_to_determine_ip_address));
    builder1.setCancelable(false);

    builder1.setPositiveButton(
            "Retry",
            new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                    dialog.cancel();
                    fetchIP();
                }
            });

    AlertDialog alert11 = builder1.create();
    alert11.show();

}

在DetermineIP.onPostExecute

protected void onPostExecute(String result) {
    if(result.isEmpty()) ((MainActivity) m_parent).setNoIP();
    else ((MainActivity) m_parent).setIP(result);
}

您收到的错误强烈建议您对 UI 主线程进行 UI 更新。如果你想更新视图,你应该在 UI 线程上进行。 AsyncTask 有一个 如果需要,可以在其中更新 UI 的回调:

 @Override 
        protected void onPostExecute(Object result) {
        } 

还有一个用于 onPreExecute

Android 的黄金法则 --> 在另一个线程上做繁重的工作(比如 AsyncTask 的 doInBackground)并在主线程上更新 UI .

所以任何 UI 相关的东西都只是从主线程调用它而不是从 asyncTask doInBackground

AsyncTask 对 UI 的任何更新都可以通过以下方式完成 -

protected void onPostExecute(Object result) {

            activity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    //UI related code
                }
            });
        }