无法在doInbackground()方法中执行AlertDialog

时间:2012-06-27 03:05:00

标签: java android android-asynctask httpurlconnection

我在postexecute()上执行AlertDialog时遇到问题。抛出这个例外  引起:java.lang.RuntimeException:无法在未调用Looper.prepare()的线程内创建处理程序 或者,当我放置AlertDialog.Builder时,它只是不起作用 请帮忙。 同样在输入错误密码的情况下,该过程终止。如果用户名或密码无效,我怎样才能调用Toast方法 以下是代码段

public void Login() {

    // Toast.makeText(getBaseContext(), pass.getText() + " "
    // +user.getText(),
    // Toast.LENGTH_SHORT).show();

    String url = "http://107.20.195.151/mcast_ws/" + "?user="
            + user.getText().toString() + "&password="
            + pass.getText().toString();

    result = getHttpResponse(url);  
}


String result;
private String getHttpResponse(String location) {
    result = "";
    URL url = null;
    Log.d(LOGTAG, " " + "location " + location);
    try {
        url = new URL(location);
    } catch (MalformedURLException e) {
        Log.e(LOGTAG, " " + "error" + e.getMessage());
    }
    if (url != null) {
        try {
            HttpURLConnection connection = (HttpURLConnection) url
                    .openConnection();
            BufferedReader in = new BufferedReader(new InputStreamReader(
                    connection.getInputStream()));
            String inputLine;
            int lineCount = 0;
            while ((inputLine = in.readLine()) != null) {
                result += inputLine.trim();
            }

            in.close();
            connection.disconnect();
        } catch (Exception e) {

            Log.e(LOGTAG, " " + "IOError " + e.getMessage());
            Toast.makeText(getBaseContext(), "No Internet Access",
                    Toast.LENGTH_SHORT);
        }
    } else {
        Log.e(LOGTAG, " " + "url" + url);
    }
    return result;
}

class PostToTwitter extends AsyncTask<String, Void, String> {

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

        Login();
        Log.d(LOGTAG, "Success");
        Log.d(LOGTAG, result);
        Log.d(LOGTAG, result.substring(0, 16).trim());
        // Log.d(TweetActivity.getLogtag(),"Successfully Posted: " +
        // params[0]);

        return "success";
    }

    @Override
    protected void onPostExecute(String r) {
        // TODO Auto-generated method stub
        super.onPostExecute(result);
        String msg = "Login successful";

        if (result.substring(0, 16).trim().equals(msg)) {
            // System.out.println(result.substring(0, 16).trim());
            Log.d(LOGTAG, " " + "Connection Test" + result);
            AlertDialog.Builder builder = new AlertDialog.Builder(getApplicationContext());
            builder.setMessage("Are you sure send this SMS?")
                   .setCancelable(false)
                   .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                       public void onClick(DialogInterface dialog, int id) {
                            //...Attach another thread event to send the sms
                       }
                   })
                   .setNegativeButton("No", new DialogInterface.OnClickListener() {
                       public void onClick(DialogInterface dialog, int id) {
                            dialog.cancel();
                       }
                   });
            Log.e(LOGTAG, "Error detected 2");
            AlertDialog alert = builder.create();
            alert.show();
            //return  "success";
            // Toast.makeText(getBaseContext(),
            // "Login Succesful",Toast.LENGTH_SHORT).show();

        } else {
            Toast.makeText(getBaseContext(),
                    "Login UnSuccesful. Check Username or password",
                    Toast.LENGTH_SHORT).show();
            //return null;
        }
        // Toast.makeText(getApplicationContext(), result
        // ,Toast.LENGTH_SHORT).show();
        Log.e(LOGTAG, "Error detected");

        /*
        Intent i = new Intent("com.sms.subsahara.COMPOSESMS");
        startActivity(i);
        //Log.e(LOGTAG, " " + "error2");*/

    }

}

在应用Alex的建议时,我修改了上面的原始代码,但仍然出错.Below是logcat的例外

E/AndroidRuntime(  326): Uncaught handler: thread main exiting due to uncaught exception
E/AndroidRuntime(  326): android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application
E/AndroidRuntime(  326):        at android.view.ViewRoot.setView(ViewRoot.java:472)
E/AndroidRuntime(  326):        at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:177)
E/AndroidRuntime(  326):        at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
E/AndroidRuntime(  326):        at android.app.Dialog.show(Dialog.java:239)
E/AndroidRuntime(  326):        at com.sms.subsahara.WebMessengerActivity$PostToTwitter.onPostExecute(WebMessengerActivity.java:216)
E/AndroidRuntime(  326):        at com.sms.subsahara.WebMessengerActivity$PostToTwitter.onPostExecute(WebMessengerActivity.java:1)
E/AndroidRuntime(  326):        at android.os.AsyncTask.finish(AsyncTask.java:417)
E/AndroidRuntime(  326):        at android.os.AsyncTask.access$300(AsyncTask.java:127)
E/AndroidRuntime(  326):        at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:429)
E/AndroidRuntime(  326):        at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime(  326):        at android.os.Looper.loop(Looper.java:123)
E/AndroidRuntime(  326):        at android.app.ActivityThread.main(ActivityThread.java:4363)
E/AndroidRuntime(  326):        at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime(  326):        at java.lang.reflect.Method.invoke(Method.java:521)
E/AndroidRuntime(  326):        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
E/AndroidRuntime(  326):        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
E/AndroidRuntime(  326):        at dalvik.system.NativeStart.main(Native Method)

4 个答案:

答案 0 :(得分:8)

doInBackground与UI线程不同步,这意味着您无法从方法中直接操作UI元素,启动对话框等。修复很容易。只需将AlertDialog代码移至onPostExecute方法( 与UI线程同步)。

使用AsyncTask时,请记住:

  1. doInBackground用于执行潜在的昂贵操作(网络访问,套接字连接,数据库查询等)。
  2. 如果您愿意,
  3. onPostExecute意味着对结果做一些事情(此方法与UI线程同步,因此您可以直接操作UI元素)

答案 1 :(得分:3)

DoInBackground()仅在与主UI线程不同的线程上执行。这就是AsyncTask的重点。

有三种方法可以将结果发布到UI(几乎......到UI线程)

  1. 使用onPostExecute方法。你得到传入的doInBackground方法的返回值,你可以用它做任何事情。 (我认为这符合您的使用案例。)

  2. 如果您的任务正在进行中,并且您希望在UI上获得少量信息,例如进度条更新,请使用doInBackground方法中的publishProgress(...),然后将其传递到onProgressUpdate (...)AsyncTask中的方法,它将在UI Thread上运行。

  3. 与2类似,但您可以使用RunOnUiThread(...)方便方法抛出runnable以在UI Thread中运行。当你有多个匿名方法浮动时,可能不是最漂亮的代码,但这是快速而肮脏的方式。请注意,此方法在活动类上可用,而不是Context类,这可能是某些情况下的交易破坏者。

答案 2 :(得分:1)

我猜是因为你的Login()在AsyncTask里面执行,而不是在mainUI里面执行。可以将onPostExecute处理程序输出到内部,返回主线程执行;也可以在onPostExecute UIThread中使用:

runOnUiThread(new Runnable() {
                 @Override
                    public void run() {
                    Login();    
                   }
                });

我希望它可以帮到你。

答案 3 :(得分:0)

@Alex Lockwood

对于非常长且重复的操作,

AsyncTask.doInBackground(Void..params) 不适合,更好的替换是HandlerThread

原因:

在android 3.2中,AsyncTask以显着的方式改变了它的实现。从Android 3.2开始,AsyncTask 不会为AsyncTask中的每个实例创建一个线程,而是使用执行程序为单个后台线程上的所有AsyncTasks运行后台工作!这意味着每个AsyncTask线程都必须一个接一个地跑。因此,例如,如果你有一个很长的AsyncTask线程(来自REST的图像获取器),我建议使用HandlerThread,而不是,因为长任务运行线程可能会延迟整个链。

但是

使用线程池执行器可以安全地并行运行AsyncTask ,但我不知道具体原因,程序员不建议这样做所以,背后有几个原因与这篇文章无关。但是如果你这样做,我建议你做自己的线程,使用处理程序在必要时与主线程进行通信。