runOnUiThread是如何解决子线程不能更新主线程View的问题的?

上篇文章:子线程不显示Toast? 分析了子线程不显示Toast的原因,并通过Looper.prepare(); Looper.loop();解决。这篇文章我们通过runOnUiThread()解决,并分析原因。

本文:Android 12 api=32

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        new Thread(new Runnable() {
            @Override
            public void run() {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(MainActivity.this,"子线程",Toast.LENGTH_SHORT).show();
                    }
                });

            }
        }).start();

    }
}

	//Activity.java
    final Handler mHandler = new Handler();
    ...	
    public final void runOnUiThread(Runnable action) {
        if (Thread.currentThread() != mUiThread) {
            mHandler.post(action);
        } else {
            action.run();
        }
    }
	//Handler.java
    public final boolean post(@NonNull Runnable r) {
    	//这里通过getPostMessage() 把Runnable转为了一个Message对象
       return  sendMessageDelayed(getPostMessage(r), 0);
    }

    private static Message getPostMessage(Runnable r) {
        Message m = Message.obtain();
        //Runnable 保存在Message的成员变量callback里面。
        m.callback = r;
        return m;
    }
	//Message.java
	public final class Message implements Parcelable {
		...
	    @UnsupportedAppUsage
	    /*package*/ Runnable callback;
	    ...
	}

总接一下:runOnUiThread()方法,是Activity的方法。它的入参Runnable最终被转化成了一个Message对象,然后就和sendMessage()方法的流程一样了。

你可能感兴趣的:(Handler,android,java,开发语言)