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:
- GetWidth y getHeight devuelven un cero
- Android: ¿conseguir niños dentro de una vista?
- Android: ¿cuál es la diferencia entre los estados enfocado, habilitado, presionado y seleccionado?
- Android: ViewPager y HorizontalScrollVIew
- Android - cómo quitar la vista en disposición (la visión agregó dinámicamente)
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.
- Cómo obtener una vista desde un evento de coordenadas en android?
- Mejores prácticas de Android: vistas / actividades
- Android: cómo deshabilitar todos los clics en una vista
- Cómo detectar si la actividad principal de la vista se está destruyendo
- Cómo obtener la vista anterior o siguiente
- Android ver el relleno o los márgenes por defecto
- Android - Descripción de View.getLocalVisibleRect (Rect)
- Cómo crear una vista parcialmente invisible
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.
- La creación personalizada de diseño de teclado Android
- Pinch zoom in, zoom out – javascript / jquery / jquery eventos móviles para la web en la plataforma android?