The foreword 0.

In Android, an application runs as an independent process, but each process can contain multiple threads to improve running efficiency. In multithreaded development, it is an important rule not to update the UI in child threads.

Only the original thread that created a view hierarchy can touch its views.

To solve this problem, there are multiple solutions for communicating between child threads and the main thread (the UI thread).

1. Determine the thread of code execution

In some simple code logic, it might be easy to tell which route is in the child thread or the main thread. Often in complex class dependencies, nested function calls, it can take a lot of effort to read the code to determine. However, there are clever ways, a line of code to solve.

Log.d("TAG"."test");
Copy the code

In the log content, 2368-2393 indicates that logs are generated in the child thread.

11-16 01:08:31.584 2368-2393/com.flueky.demo D/TAG: test

2368 indicates PID indicates the process ID, and 2393 indicates TID indicates the thread ID. If TID is also 2368, the log output is in the main thread.

Some of you may have heard of itUIDWhen an application is installed on the device for the first time, the system assigns a serial number to the application as its unique identifier.UIDIt does not change when overwriting an installation, and will be reassigned when uninstalling it.

Here’s how you get the three ids in your code.

/ / get dar
Process.myTid()
/ / get the pid
Process.myPid()
/ / get the uid
Process.myUid()
Copy the code

When you need to update UI operations in child threads, you can do so in the following ways.

2. Use the View. The post

When child thread code is running in an Activity or Fragment and can get a reference to any view, you can use this method to run the code to be implemented in the main thread.

// The post method is called in the child thread
textView.post(new Runnable() {
    @Override
    public void run(a) {
        // Here the code is executed in the UI thread}});Copy the code

3. Use the Activity. RunOnUiThread

If you can get the Activity instance directly, use the runOnUiThread method.

The runOnUiThread method is called in the child thread
activity.runOnUiThread(new Runnable() {
    @Override
    public void run(a) {
        // Here the code is executed in the UI thread}});Copy the code

4. Use Handler. Post

Using Handler is tricky because you need to take into account where the Handler instance is initialized.

// The post method is called in the child thread
handler.post(new Runnable() {
    @Override
    public void run(a) {
        // When the handler is initialized in the main thread, this code is executed in the main thread
        // Handler initializes the event in the child thread, where the code is executed}});Copy the code

Looper.getmainlooper () is passed to initialize the handler instance, and handler.post is also executed on the main thread.

// The following code is executed in the child thread
Looper.prepare();
handler = new Handler(Looper.getMainLooper());
Looper.loop();
Copy the code

5. Use the EventBus

EventBus comes from GreenRobot and, by subscribing, tells the function which thread it runs on. To make the subscription function execute in the MAIN thread, use the annotation MAIN or MAIN_ORDERED.

/** * a simple example of eventBus */
public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    /** * the subscription function, * threadmode. MAIN, runs in the MAIN thread and may block child threads. * threadmode. MAIN_ORDERED: runs in the main thread and does not block child threads. * /
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onMessageEvent(Object event) {
        if(event instanceof Runnable)
            ((Runnable)event).run();
    }

    @Override
    protected void onStart(a) {
        super.onStart();
        // Register eventBus listener
        EventBus.getDefault().register(this);
    }

    @Override
    protected void onStop(a) {
        super.onStop();
        // Unlog the EventBus listener
        EventBus.getDefault().unregister(this); }}// Send messages in child threads
EventBus.getDefault().post(new Runnable() {
    @Override
    public void run(a) {
        // Here the code is executed in the UI thread}});Copy the code

6. Transfer data

The previous four methods demonstrate how to do UI updates in child threads. AsyncTask can be used in the same way, but it’s a bit of a stretch because onPostExecute is only called in the main thread if the execute method is executed in the main thread. Since onPostExecute can receive any type of object data passed by a child thread, AsyncTask can be used as a vehicle for data interaction between threads. Handler and EventBus disagree.

EventBus, as shown earlier, can replace Runnable objects with arbitrary instances.

The Handler can also sendMessage objects using the sendMessage method. Message.obj is used as the carrier for passing object data.

It is recommended to reuse Message instances using the message.obtain () method.

BroadcastReceiver, by the way, can also be used for this purpose, but not as conveniently as EventBus and Handler.

Think it works? I’ll give you a bonus.To play to admire

Flueky.github. IO /