Asyntask: почему обновление потока пользовательского интерфейса в doInbackground встретит ошибку? - PullRequest
3 голосов
/ 21 марта 2012

когда я читаю документ о asyntask, они говорят: «не следует» обновлять поток пользовательского интерфейса в doInbackground, потому что doInbackground работает в другом потоке.

, что означает: это действие будет опасным, потому что поток пользовательского интерфейса непотокобезопасный.Я понимаю, это.но когда я пытаюсь проверить, что происходит, когда я обновляю поток пользовательского интерфейса в этой функции.Я получаю сообщение об ошибке: (но ошибка выглядит не так, как aysnchonize, а потому, что мы НЕ МОЖЕМ это сделать)

   (TextView)((Activity)context).findViewById(R.id.text)).setText("StackOverFlow");
//context: reference of context object of UI Thread

Пожалуйста, объясните мне.Мы shouldn't или mustn't.

спасибо:)

Ответы [ 8 ]

8 голосов
/ 21 марта 2012

что я понимаю до сих пор с Android это ...,

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

Причина этого очень ясна ... @ Уровень ОС будет , поэтому будет запущено столько потоков .

А также отличается от другого приложения , и в этом случае на экране будет хаос, если мы сможем обновить пользовательский интерфейс из bg-thread

2 голосов
/ 21 марта 2012

Внутри doInBackground вы не получите доступ к пользовательскому интерфейсу.Если вы хотите получить доступ к пользовательскому интерфейсу publishProgress из doInBackground, вы перейдете к onProgressUpdate и выполните то, что хотите показать в пользовательском интерфейсе.

Ниже приведен код, который вы проверите для справки:

Скачать AsyncTask расширяет AsyncTask {

    ProgressDialog progressDialog;


    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        progressDialog = ProgressDialog.show(Login.this, "", "Please Wait ...");
    }



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

        int status1 = validationuser(username);
        Log.i("MyLog", "Inside the doInBackground is came"+status1);

        if(status1 == 1)
        {
            publishProgress(status1+ "Valid User Code","1",""+status1);
        }
        else
        {
            publishProgress(status1+ " Invalid Valid User Code","0",""+status1);
        }

        return null;
    }

    @Override
    protected void onProgressUpdate(String...values){
        super.onProgressUpdate(values);

        int index = Integer.parseInt(values[2]);

        if(index == 1)
        {
            USERIDLOGIN = edittextuserName.getText().toString();
            Intent intent=new Intent(Login.this, CollectionModuleandDownload.class);
            /*Toast.makeText(Login.this, "Valid User Password", Toast.LENGTH_SHORT).show();*/
            startActivity(intent);
            progressDialog.dismiss();
        }
        else
        {
            Toast.makeText(Login.this, "Invalid Username & Password", Toast.LENGTH_SHORT).show();
            progressDialog.dismiss();
        }
    }

    @Override
    protected void onPostExecute(Void result){
        super.onPostExecute(result);
        /*if(progressDialog != null)
        {
            progressDialog.dismiss();
        }*/
    }

}
1 голос
/ 21 марта 2012

При создании задачи Aysnc метод doInBackground выполняется в отдельном потоке из потока пользовательского интерфейса. Таким образом, вы не можете обновить пользовательский интерфейс из этого метода.

Методы OnPostExecute и onPreExecute выполняются в том же потоке, что и поток пользовательского интерфейса. Для дальнейшего чтения зайдите здесь

1 голос
/ 21 марта 2012

, поэтому вы должны обновлять пользовательский интерфейс только на OnPostExecute & OnPreExecute.Вот хороший пример асинктаск.попробуйте

вы называете это

new SaveProfile().execute();

тогда это ...

private class SaveProfile extends AsyncTask<String, Void, Boolean>{

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


        //---------- so your stuff here.... non ui related

        Log.v("response from saving",response);

        if(response.equals("1")){

            return true;                
        }else{

            return false;
        }
    }

    protected void onPostExecute(Boolean result) {

         if(result) {

                      //------ UPDATE UI HERE
             Toast.makeText(ProfileCompanyActivity.this, "profile saved", 2500).show();
         }else{
             Toast.makeText(ProfileCompanyActivity.this, "an error occured", 2500).show();
         }
     }
}
0 голосов
/ 19 февраля 2013

Поскольку doInBackground () запускается в отдельном потоке, а onPostExecute запускается в потоке UIMain, и согласно ограничениям, предоставляемым Android, вы не можете обновлять UIMain Thread из другого потока.

По вышеуказанной причине вы получаете упомянутое сообщение во время работы приложения.

0 голосов
/ 21 марта 2012

Я думаю, что ответ заключается в том, что мы не должны

Это просто не кажется мне логичным ... это все равно что пытаться сменить радиостанцию ​​на другой машине, которая едет рядом с тобой ... архитектура просто нене получается так ... вы можете выбрать радиостанцию ​​перед тем, как отправиться в поездку, или когда вы перестанете ехать, и теоретически вы можете крикнуть ему и попросить его сменить станцию, но вы не можете сделать это самостоятельно.

0 голосов
/ 21 марта 2012

doInBackground используется для выполнения тяжелых вычислений или любой фоновой работы, которую вы хотите выполнить в своей деятельности.когда операция в вашем методе doinbackground завершена, методы on postexecute обновляют ваш пользовательский интерфейс .. короче говоря, doinbackground не используется для обновления пользовательского интерфейса.

0 голосов
/ 21 марта 2012

Если только одному потоку разрешено касаться пользовательского интерфейса, Android может гарантировать, что при измерении представлений и отображении их на экране ничего существенного не изменится. Это происходит потому, что ... Пользовательский интерфейс может быть обновлен только в mainthread.объекты пользовательского интерфейса на вашем экране поддерживаются этой основной темой .... теперь, если вы попытаетесь изменить пользовательский интерфейс из какого-либо другого потока (в этом случае - в фоновом режиме), то это вызовет ошибку, потому что, например, если выпопробуйте изменить значение seekbar (некоторый виджет), отличное от основного потока ... и пользователь пытается ввести другое значение ... тогда это неоднозначно для android .. какой поток он должен слушать ... надеюсь, что этопроясняет ваши сомнения ..

Итак, похоже, что мы не должны пытаться .. и из-за его безопасности .. мы не можем пытаться также .., поскольку это дает ошибку .. =]

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...