なぜのsetTextによって子スレッドでUIを更新することができます

なぜのsetTextによって子スレッドでUIを更新することができます

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

UIを更新します子スレッドでの通常の状況下ではそれがViewRootImplがチェックされていない作成しないときにViewRootImplにcheckThreadによってチェックされますので、与えられたが、ここでは主にViewRootImplは、分析のためのUIを更新することができます作成​​されていることですされています。

私たちは、コードを見て、与えられていないサブスレッドのsetTextの結果から直接実行します。

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>

変更前ここに画像を挿入説明
私たちは、スムーズな更新UIをクリックした後に見ることができます。キーポイントは、アンドロイドである:layout_width =「100dp」のandroid :layout_height =「100dp」
ビューのサイズが固定されたと私はここにいます。エラーは確かにcheckThreadを引き起こしたが、彼らはないトリガーが正常にUIを更新することができません、とのsetTextはない、どのような場合にのcheckThreadをトリガーします。

SetTextメソッドでcheckForRelayoutを呼び出し、このメソッドはcheckThreadをトリガしない理由が表示されます。checkThreadのみrequestLayoutで行われ、すべてここに、私たちはrequestLayoutはcheckThreadではありません呼び出すことはありません。

ソースコードに従うことにより、あなたは、すべてのケースがrequestLayout呼び出されることがわかります。私達はちょうどビューwrap_contentの大きさが、match_parentまたは固定DPを知ることができないので、その見返りに2つの無用の呼び出しは、requestLayoutありますが、それはrequestLayoutをトリガしませんが、当然、子スレッドで更新することができます。

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();
        }
    }

概要:
1.コールrequestLayoutなくてもコールしないときコンテンツは、新しいビューのレイアウトを必要とするためです。
サブスレッドのUI 2.子スレッドを防ぐためにcheckThread Updateを通じて更新されます。
3.コールrequestLayoutた場合にのみ表示更新トリガーCheckThred、あなたは子スレッドで更新することができrequestLayout手段を呼び出すことはありません。

出版元の記事 ウォンの賞賛0 ビュー65

おすすめ

転載: blog.csdn.net/m0_46496806/article/details/105356056