¿Por qué se puede actualizar la interfaz de usuario en el hilo hijo por setText

¿Por qué se puede actualizar la interfaz de usuario en el hilo hijo por setText

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

En circunstancias normales en el hilo hijo va a actualizar la interfaz de usuario se le está dando, porque va a ser comprobado por checkThread en ViewRootImpl en cuando ViewRootImpl no crea no está marcada, pero aquí es sobre todo para haber sido creado ViewRootImpl también puede actualizar la interfaz de usuario para el análisis .

Nos fijamos en el código y ejecutar directamente a través de los resultados de setText sub-hilo no están dadas.

public class MainActivity extends AppCompatActivity implements View.OnClickListener  {

    TextView text;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        text= findViewById(R.id.text); 
       }
    @Override
    public void onClick(View v) {
       new Thread((Runnable)()->{
           text.setText("改变后");
       }).start();
    }
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:orientation="vertical">

    <TextView
        android:id="@+id/text"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="@color/colorAccent"
        android:text="改变前"
        />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button"
        android:onClick="onClick"
        />

</LinearLayout>

cambio antesAquí Insertar imagen Descripción
Podemos ver después de hacer clic en una interfaz de usuario actualizada suavizar. El punto clave es que el androide: layout_width = "100dp" android : layout_height = "100dp"
Estoy aquí para tamaño de la vista se fijó. Error sin duda provocó checkThread, pero que no desencadenan puede actualizado correctamente la interfaz de usuario, y setText no, en cualquier caso, se disparará checkThread de.

En el método setText llamadas checkForRelayout, y este método mostrará la razón no desencadena la checkThread. checkThread solamente se lleva a cabo en requestLayout, todos aquí, no llamamos requestLayout no será checkThread.

Siguiendo el código fuente se encuentra que no todos los casos serán llamados requestLayout. A cambio hay dos llamadas inútiles requestLayout, por lo que no podemos saber el tamaño de apenas Ver wrap_content, pero match_parent o dp fijo, no se disparará requestLayout, naturalmente, puede ser actualizado en el hilo hijo.

private void checkForRelayout() {
        // If we have a fixed width, we can just swap in a new text layout
        // if the text height stays the same or if the view height is fixed.

        if ((mLayoutParams.width != LayoutParams.WRAP_CONTENT
                || (mMaxWidthMode == mMinWidthMode && mMaxWidth == mMinWidth))
                && (mHint == null || mHintLayout != null)
                && (mRight - mLeft - getCompoundPaddingLeft() - getCompoundPaddingRight() > 0)) {
            // Static width, so try making a new text layout.

            int oldht = mLayout.getHeight();
            int want = mLayout.getWidth();
            int hintWant = mHintLayout == null ? 0 : mHintLayout.getWidth();

            /*
             * No need to bring the text into view, since the size is not
             * changing (unless we do the requestLayout(), in which case it
             * will happen at measure).
             */
            makeNewLayout(want, hintWant, UNKNOWN_BORING, UNKNOWN_BORING,
                          mRight - mLeft - getCompoundPaddingLeft() - getCompoundPaddingRight(),
                          false);

            if (mEllipsize != TextUtils.TruncateAt.MARQUEE) {
                // In a fixed-height view, so use our new text layout.
                if (mLayoutParams.height != LayoutParams.WRAP_CONTENT
                        && mLayoutParams.height != LayoutParams.MATCH_PARENT) {
                    autoSizeText();
                    invalidate();
                    return;
                }

                // Dynamic height, but height has stayed the same,
                // so use our new text layout.
                if (mLayout.getHeight() == oldht
                        && (mHintLayout == null || mHintLayout.getHeight() == oldht)) {
                    autoSizeText();
                    invalidate();
                    return;
                }
            }

            // We lose: the height has changed and we have a dynamic height.
            // Request a new view layout using our new text layout.
            requestLayout();
            invalidate();
        } else {
            // Dynamic width, so we have no choice but to request a new
            // view layout with a new text layout.
            nullLayouts();
            requestLayout();
            invalidate();
        }
    }

Resumen:
1. Llamar requestLayout es debido a que el contenido requiere un nuevo diseño de vista, cuando sin la necesidad de no llamar.
2. En la interfaz de usuario sub-hilo de actualizaciones a través de la actualización checkThread para prevenir hilo hijo.
3. Llame sólo cuando requestLayout Ver activador de actualización CheckThred, no se llama a los medios requestLayout pueden ser actualizados en el hilo hijo.

Publicó un artículo original · ganado elogios 0 · Vistas 65

Supongo que te gusta

Origin blog.csdn.net/m0_46496806/article/details/105356056
Recomendado
Clasificación