Проблема с Toast в вызове метода AsyncTask - PullRequest
4 голосов
/ 21 апреля 2011

Привет всем,
У меня есть AsyncTask, который отправляет некоторые данные на сервер.Это делается путем вызова статического метода, который я написал из doInBackground.Когда я запускаю AsyncTask, я отправляю контекст действия, вызвавшего execute (), который я отправляю своему статическому методу, потому что он нужен для того, чтобы сделать Toast, если что-то пойдет не так во время общения с сервером.Тем не менее, я получаю эту ошибку, когда Toast сделан в статическом методе:

04-21 12:49:16.689: ERROR/AndroidRuntime(2123): FATAL EXCEPTION: AsyncTask #1
04-21 12:49:16.689: ERROR/AndroidRuntime(2123): java.lang.RuntimeException: An error occured   while executing doInBackground()
04-21 12:49:16.689: ERROR/AndroidRuntime(2123):at android.os.AsyncTask$3.done(AsyncTask.java:200)
04-21 12:49:16.689: ERROR/AndroidRuntime(2123): at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:274)
04-21 12:49:16.689: ERROR/AndroidRuntime(2123): at java.util.concurrent.FutureTask.setException(FutureTask.java:125)
04-21 12:49:16.689: ERROR/AndroidRuntime(2123): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:308)
04-21 12:49:16.689: ERROR/AndroidRuntime(2123): at java.util.concurrent.FutureTask.run(FutureTask.java:138)
04-21 12:49:16.689: ERROR/AndroidRuntime(2123): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
04-21 12:49:16.689: ERROR/AndroidRuntime(2123): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
04-21 12:49:16.689: ERROR/AndroidRuntime(2123): at java.lang.Thread.run(Thread.java:1019)
04-21 12:49:16.689: ERROR/AndroidRuntime(2123): Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
04-21 12:49:16.689: ERROR/AndroidRuntime(2123): at android.os.Handler.<init>(Handler.java:121)
04-21 12:49:16.689: ERROR/AndroidRuntime(2123): at android.widget.Toast.<init>(Toast.java:68)
04-21 12:49:16.689: ERROR/AndroidRuntime(2123): at android.widget.Toast.makeText(Toast.java:23
04-21 12:49:16.689: ERROR/AndroidRuntime(2123): at com.microogle.dev.util.ServerConnections.PostToLoginPage(ServerConnections.java:36)
04-21 12:49:16.689: ERROR/AndroidRuntime(2123): at com.microogle.dev.Whiteboard.WhiteboardLogin$LoginTask.doInBackground(WhiteboardLogin.java:150)
04-21 12:49:16.689: ERROR/AndroidRuntime(2123): at com.microogle.dev.Whiteboard.WhiteboardLogin$LoginTask.doInBackground(WhiteboardLogin.java:1)
04-21 12:49:16.689: ERROR/AndroidRuntime(2123): at android.os.AsyncTask$2.call(AsyncTask.java:185)
04-21 12:49:16.689: ERROR/AndroidRuntime(2123): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
04-21 12:49:16.689: ERROR/AndroidRuntime(2123): ... 4 more

, что сопровождается ошибкой утечки окна.Я предполагаю, что это из-за ошибки с контекстом, переданным Toast в статическом методе.AsyncTask:

private class LoginTask extends AsyncTask<Void, Void, Void> {

    private WhiteboardLogin activity;
    private Context callingContext;
    private ProgressDialog dialog;
    private String user, pass;
    private boolean sendIntent = true, loginError = false, populateError = false;

    public LoginTask(WhiteboardLogin activity, String user, String pass, Context callingContext){
        this.activity = activity;
        this.user = user.trim();
        this.pass = pass.trim();
        this.callingContext = callingContext;
    }
@Override
    protected Void doInBackground(Void... params) {
        ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
        nameValuePairs.add(new BasicNameValuePair("user",user));
        nameValuePairs.add(new BasicNameValuePair("pass",pass));
        sessionUser = user;
        sessionPassword = pass;
        //Posts the username and password to the login page and toasts an error if the login doesn't work 
        if(ServerConnections.PostToLoginPage(callingContext, nameValuePairs, activity.getString(R.string.loginPageURI)) == 1){
            dialog.dismiss();
            sendIntent = false;
            loginError = true;
            publishProgress();
           return null;
        }
        else{
           userDataList = populateUserDataList(callingContext, user,pass);
           if(userDataList == null){
               dialog.dismiss();
               sendIntent = false;
               populateError = true;
               return null;
           }
       }
       return null;
    }

Ответы [ 4 ]

22 голосов
/ 21 апреля 2011

Код в методе doInBackground () выполняется в своем собственном потоке, поэтому вы не можете напрямую получить доступ к любому элементу пользовательского интерфейса, поскольку они выполняются в потоке пользовательского интерфейса.

Итак, у вас есть два варианта.

  1. Вы обрабатываете все элементы интерфейса в методе onPreExecute () и onPostExecute () , который выполняется в потоке интерфейса.

  2. Вы обрабатываете пользовательский интерфейс в методе onProgressUpdate () , который также выполняется в потоке пользовательского интерфейса.Вы можете вызвать этот метод из doInBackground (), вызвав publishProgress () .

2 голосов
/ 07 апреля 2013

тосты внутри doInBackground

используйте этот код

runOnUiThread(new Runnable() {
public void run() {

    Toast.makeText(<your class name>.this, "Cool Ha?", Toast.LENGTH_SHORT).show();
    }
});
1 голос
/ 21 апреля 2011

Вы пытаетесь обновить пользовательский интерфейс в doInBackground(), который работает в другом потоке, отличном от потока пользовательского интерфейса. Вы должны отобразить тост в методе onPostExecute() на AsyncTask: http://developer.android.com/reference/android/os/AsyncTask.html#onPostExecute(Result)

0 голосов
/ 20 июня 2011

Да, использовать журнал для отладки проще всего, однако, если у вас есть сообщения, которые должны отображаться во время фоновой обработки по какой-либо причине, вы можете использовать Метод onProgressUpdate (), как отмечено выше Flo. Вы можете вызвать этот метод всякий раз, когда вам нужно написать сообщение, вызвав publishProgress () из DoInBackground (). Содержимое сообщения или статусы обработки могут быть легко переданы через закрытые переменные в ASyncTask, которые доступны как для метода Background, так и для методов пользовательского интерфейса.

...