My code contains two buttons and a TextView. When the program is running, by clicking on the start Thread button, a background Thread will be executed and at the same time a counter will be displayed in the TextView, and when you click on the stop Thread button, the background Thread will stop. My question is that I have not used the looper here and the counter value is displayed from the background thread in the TextView on the UI thread. How is this possible?
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
tools:context=".MainActivity">
<TextView
android:id="@ id/txtViewThreadCount"
android:hint="Thread Count"
android:textSize="30sp"
android:textColor="@color/black"
android:gravity="center"
android:padding="8dp"
android:layout_margin="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<Button
android:id="@ id/btnStartThread"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:textSize="30sp"
android:layout_marginTop="30dp"
android:text="Start Thread" />
<Button
android:id="@ id/btnStopThread"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:textSize="30sp"
android:layout_marginTop="30dp"
android:text="Stop Thread" />
</LinearLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
//Fields
private static final String TAG = MainActivity.class.getSimpleName();
private TextView txtViewThreadCount;
private Button btnStartThread, btnStopThread;
private boolean stopLoop;
private int count = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.e(TAG, "Thread id : " Thread.currentThread().getId());
btnStartThread = findViewById(R.id.btnStartThread);
btnStopThread = findViewById(R.id.btnStopThread);
txtViewThreadCount = findViewById(R.id.txtViewThreadCount);
btnStartThread.setOnClickListener(this);
btnStopThread.setOnClickListener(this);
}
public void onClick(View view){
switch(view.getId()){
case R.id.btnStartThread:
stopLoop = true;
new Thread(new Runnable() {
@Override
public void run() {
while(stopLoop){
try {
Thread.sleep(1000);
count ;
} catch (InterruptedException e) {
Log.e(TAG,e.getMessage());
}
Log.e(TAG,"Thread id in while loop: " Thread.currentThread().getId() ", Count: " count);
txtViewThreadCount.setText(count "");
}
}
}).start();
break;
case R.id.btnStopThread:
stopLoop = false;
break;
}
}
}
CodePudding user response:
See Processes and threads overview in the Android docs:
- Do not access the Android UI toolkit from outside the UI thread
It doesn't state what will happen if you ignore this rule; one of the possible outcomes is "it may sometimes work and then crash on your users' devices".
You can use runOnUiThread
or View.post
in this situation to do move the setText
call back onto the UI thread.
See also What is the Android UiThread?.
CodePudding user response:
When an application is launched, the system creates a thread of execution for the application, called "main." This thread is very important because it is in charge of dispatching events to the appropriate user interface widgets, including drawing events. It is also almost always the thread in which your application interacts with components from the Android UI toolkit (components from the android.widget and android.view packages).
Normally you could not update the UI in the work thread. You could use
1.Activity.runOnUiThread(Runnable) 2.View.post(Runnable) to fix this issue.
Please see for detail https://developer.android.com/guide/components/processes-and-threads#WorkerThreads