No error "Sólo el subproceso original que creó una jerarquía de vista puede tocar sus vistas" cuando la vista se actualiza sin demora

Me enfrenté a un problema interesante. Si escribe el siguiente código en el método de actividad onCreate/onStart/onResume :

 final Button myButton = (Button)findViewById(R.id.myButton); final TextView myTextView = (TextView)findViewById(R.id.myTextView); final Thread thread = new Thread(new Runnable() { @Override public void run() { myTextView.setText("Hello text"); } }); myButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { thread.start(); } }); 

o:

 final TextView myTextView = (TextView)findViewById(R.id.myTextView); final Thread thread = new Thread(new Runnable() { @Override public void run() { try { Thread.currentThread().sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } myTextView.setText("Hello text"); } }); thread.start(); 

Cómo debe ser, un error es lanzado

 android.view.ViewRoot $ CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views." 

Está claro que en este caso debo actualizar la vista en ui-thread (Handler, AsyncTask, runOnUiThread, view.post).

Pero si actualiza la vista en otro hilo sin demora (sin llamada de descanso o sin iniciar el hilo pulsando un botón), la excepción no se lanzará .

 final TextView myTextView = (TextView)findViewById(R.id.myTextView); final Thread thread = new Thread(new Runnable() { @Override public void run() { myTextView.setText("Hello text"); } }); thread.start(); 

¿Puede alguien decirme por qué hay tal comportamiento?

ACTUALIZAR:

He aprendido el código fuente de Android y llegó a las siguientes conclusiones. Nandeesh escribió la verdad. Al inicializar la vista denominada dispatchAttachedToWindow (AttachInfo info, int visibility) método de View, que inicializa el campo mAttachInfo. El objeto mAttachInfo tiene el campo mViewRootImpl. Si es nulo, getViewRootImpl devuelve como null:

 public ViewRootImpl getViewRootImpl() { if (mAttachInfo != null) { return mAttachInfo.mViewRootImpl; } return null; } 

ViewRootImpl contiene el método checkThread. Compara los subprocesos: el subproceso que creó la vista y el subproceso de la solicitud para la actualización de la vista.

  void checkThread() { if (mThread != Thread.currentThread()) { throw new CalledFromWrongThreadException( "Only the original thread that created a view hierarchy can touch its views."); } } 

Por lo tanto, si la vista no se inicializó, no hay comprobación y el cambio no arroja excepciones.

La comprobación del hilo sólo está presente si se realiza textout relayout. Sin embargo, el diseño de la vista sólo se realiza después de OnCreate se llama. Así que hasta que el Ui no se muestra, el cambio de textView no resultará en la invalidación de la vista.

Pero una vez que se ha mostrado el textView, se requiere el relayout UI, en cuyo caso se comprueba el hilo. Así que obtendrá la excepción sólo después de algún tiempo de Oncreate pero no inmediatamente.

  • Cómo implementar un deslizamiento de una vista (como feed de noticias en la aplicación de Facebook)
  • ¿Podría ocultar la barra de progreso después de cargar la imagen en picasso?
  • Android: ¿es eficiente almacenar referencias a Views como variables miembro?
  • Cambiar retardo de clic largo
  • Android infla la vista utilizando un objeto de vista existente
  • Android view.getId () devuelve -1
  • Cómo manejar los cambios de visibilidad para una vista / widget personalizado de Android
  • Obtener la vista de raíz de la actividad actual
  • Cómo agregar una vista a la parte superior de un diseño lineal en el código?
  • Cómo establecer la unidad para Paint.setTextSize ()
  • Android ¿hay alguna llamada de vista cuando se destruye?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.