Andriod UI is not thread-safe. So you should update the android UI in the android activity main thread, otherwise, it will throw an exception. But there are also methods to update android UI from the child thread. This example will show you how to do that.
1. Update Android UI From Child Thread Steps.
- Create an instance of android.os.Handler in activity main thread.
- Override it’s handleMessage method, this method will be invoked when this handler gets new messages from the activity message queue.
- Update UI in the handleMessage method.
- Create an android.os.Message object in child thread run method.
- Configure the message type by assigning the message’s what attribute.
- Send the message object to the activity main thread Handler object.
2. Update Android UI In Child Thread Examples.
If you can not watch the above video, you can see it on the youtube URL https://youtu.be/UScEkG49D3k
- If you update UI from the child thread directly, then you will meet the below exception.
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
- So we should fix the above problem using the below code.
2.1 Main Activity Java File.
- UpdateUiFromChildThreadActivity.java
package com.dev2qa.example.thread; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import com.dev2qa.example.R; public class UpdateUiFromChildThreadActivity extends AppCompatActivity { private EditText changeTextEditor; private Button changeTextButton; private TextView changeTextTextView; // This is the activity main thread Handler. private Handler updateUIHandler = null; // Message type code. private final static int MESSAGE_UPDATE_TEXT_CHILD_THREAD =1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_update_ui_from_child_thread); setTitle("dev2qa.com - Update Ui In Child Thread Example."); // Initialize Handler. createUpdateUiHandler(); // User input text editor. changeTextEditor = (EditText)findViewById(R.id.change_text_editor); // Change text button. changeTextButton = (Button)findViewById(R.id.change_text_in_child_thread_button); // Show text textview. changeTextTextView = (TextView)findViewById(R.id.change_text_textview); // Click this button to start a child thread. changeTextButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Thread workerThread = new Thread() { @Override public void run() { // Can not update ui component directly when child thread run. // updateText(); // Build message object. Message message = new Message(); // Set message type. message.what = MESSAGE_UPDATE_TEXT_CHILD_THREAD; // Send message to main thread Handler. updateUIHandler.sendMessage(message); } }; workerThread.start(); } }); } /* Update ui text.*/ private void updateText() { String userInputText = changeTextEditor.getText().toString(); changeTextTextView.setText(userInputText); } /* Create Handler object in main thread. */ private void createUpdateUiHandler() { if(updateUIHandler == null) { updateUIHandler = new Handler() { @Override public void handleMessage(Message msg) { // Means the message is sent from child thread. if(msg.what == MESSAGE_UPDATE_TEXT_CHILD_THREAD) { // Update ui in main thread. updateText(); } } }; } } }
2.2 Layout XML File.
- activity_update_ui_from_child_thread.xml
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <EditText android:id="@+id/change_text_editor" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Input text and click below button to display in bottom text view."/> <Button android:id="@+id/change_text_in_child_thread_button" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Change Text In Child Thread"/> <TextView android:id="@+id/change_text_textview" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="This is original text."/> </LinearLayout>