Asynctask:为什么在doInbackground中更新UI线程会遇到错误?

时间:2012-03-21 08:55:29

标签: android multithreading android-asynctask

当我阅读关于asyntask的文档时,他们说:“不应该”更新doInbackground中的UI线程,因为doInbackground在不同的线程上工作。

这意味着:此操作会很危险,因为UI线程不是线程安全的。我明白了。但是当我尝试测试当我在此函数中更新UI线程时会发生什么。我收到错误:(但错误看起来并不像aysnchonize,但因为我们不能这样做)

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

请为我解释。我们是shouldn't还是mustn't

谢谢:)

8 个答案:

答案 0 :(得分:8)

到目前为止我对android的了解是......,

我们无法从后台线程更新UI线程。 可能是他们阻止我们从后台线程更新UI的情况。

原因很明显...... @操作系统级别会有这么多线程将会运行。

还有 来自不同应用程序的不同线程,在这种情况下,如果我们可以从bg-thread更新UI,它将在屏幕上出现混乱

答案 1 :(得分:2)

在doInBackground内部,您将无法获得UI访问权限。如果您想从doInBackground获取UI访问权限,那么您将从那里进入onProgressUpdate,在UI上显示您想要显示的内容。

以下是您将检查的代码供您参考:

类DownloadAsyncTask扩展了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();
        }*/
    }

}

答案 2 :(得分:1)

所以你必须只在OnPostExecute&上更新ui。 OnPreExecute。 这是asynctask的一个很好的例子。试一试

你通过

来称呼它
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();
         }
     }
}

答案 3 :(得分:1)

创建Aysnc任务时,doInBackground方法在UI线程的单独线程中运行。因此,您无法从此方法更新UI。

OnPostExecuteonPreExecute方法在与UI线程相同的线程中执行。如需进一步阅读,请转到here

答案 4 :(得分:0)

如果只允许一个线程触及用户界面,Android可以保证在测量视图并将其渲染到屏幕时不会发生任何重要变化 这是因为..用户界面只能在mainthread上更新。所有屏幕中的用户界面对象都由此主线程维护....现在,如果您尝试从其他线程更改用户界面(在后台执行)在这种情况下..它会导致错误,因为..例如..如果你试图从主线程以外更改搜索栏(某个小部件)值...并且用户试图放置不同的值...那么它是对于android来说是暧昧的...至于它应该听哪个线程...希望它澄清你的怀疑......

所以,就像我们不应该尝试......并且因为它的安全性......我们也不能尝试..因为它给出了错误.. =]

答案 5 :(得分:0)

doInBackground用于执行繁重的计算或您要在活动中执行的任何后台工作。 当你的doinbackground方法中的操作完成后,on postexecute方法会更新你的ui .. 简而言之,doinbackground不用于更新ui。

答案 6 :(得分:0)

我认为答案是我们不能

这对我来说似乎不合逻辑.. 它就像试图改变另一辆在你旁边的汽车的广播电台.. 这种架构不会那样工作..你可以在出发前往公路旅行或停止驾驶时决定一个广播电台,理论上你可以向他大喊并要求他改变电台,但你不能这样做自己。

答案 7 :(得分:0)

由于doInBackground()在单独的线程上运行,并且onPostExecute在UIMain线程上运行,并且根据Android提供的约束,您无法从其他线程更新UIMain线程。

由于上述原因,您在运行应用程序时会收到提及的消息。