I'm afraid, so in a nutshell, a memo of multi-thread processing
■ ** Thread ** class extension | ** Runnable ** interface inheritance ** Communication with UI thread ** view#post(Runnable) View#postDelayed(Runnable.long) runOnUiThread(Runnable) ■ ** AsyncTask ** class ** Processing and UI thread communication ** With execute (), doInBackground (), postExecute (), etc. ■ ** Handler ** class ** Realizes communication between multiple threads (OK even if it is not a UI thread) ** Message Runnable
■Thread(Thread/Runnable) Android now runs on one Linux process, using one thread. This thread is called a single thread, and MainActivity.java runs in a single thread. Here, the thread in which MainActivity runs is called the main thread and is described. Only the main thread can handle UI parts directly, and to operate UI parts from other threads, a dedicated method is used.
MainActivity plays the role of an interface operated by the user, so if the main thread performs time-consuming processing, the operation screen will become unresponsive or the overall processing will slow down, making it difficult to use. It ends up.
Therefore, in order to maintain the ease of use of the application, design the processing that is not related to user operation to be processed separately using another thread (multithread). It seems that separate thread processing is performed using either the Thread class or the Runnable interface.
**
Since another thread is also processed on the same Linux process as the main thread, if there is a problem with a single process, consider launching another Linux process (multi-process) and creating another thread as needed. You may (Manifest.java).
□Thread
In a subclass of Thread
public void onCreate(){
SubThread subThread = new SubThread();
subThread.start();
}
class SubThread extends Thread{
public void run(){
// todo
}
}
□Runnable Although it is a description of Runnable, there are three familiar description methods.
Anonymous functional
new Thread(new Runnable(){
@Override
public void run(){
// todo
}
}).start();
Using an instance of Thread
public void onCreate(){
MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);
Thread.start();
}
class MyRunnable implement Runnable{
@Override
public void run(){
// todo
}
}
Call Thread class directly
public void onCreate(){
Thread thread = new Thread(MyRunnable());
}
class MyRunnable implement Runnable{
@Override
public void run(){
// todo
}
}
--Thread running on Service --If there is Service, Service will not be started twice. --Stop with cancel ()
MainActivity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Get the start and stop button objects!
Button btn_start = findViewById(R.id.btn_start);
Button btn_stop = findViewById(R.id.btn_stop);
final Intent intent = new Intent(this,MyService.class);
btn_start.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
//If MyService is not started, start it!
if(!MyService.serviceState) {
startForegroundService(intent);
}
}
});
btn_stop.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
// stopService()So, I'll call onDestroy of MyService ~
stopService(intent);
}
});
}
MyService.java
public class MyService extends Service {
// serviceState =If true, MyService has already started
// threadState =If true, Thread will continue to run
static boolean serviceState;
boolean threadState;
public MyService() {
serviceState = true;
threadState = true;
}
@Override
public int onStartCommand(Intent intent,int flags,int startId){
//Set up Notification content!
Notification notification;
NotificationCompat.Builder builder = new NotificationCompat.Builder(this,"id");
notification = builder.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("sanple")
.setContentText("text")
.build();
//Set the Notification channel and importance!
int importance = NotificationManager.IMPORTANCE_LOW;
NotificationChannel channel = new NotificationChannel("id","name",importance);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(channel);
startForeground(1,notification);
//Start the thread!
new Thread(new Runnable() {
@Override
public void run() {
int count = 0;
//Run the count log every 2 seconds while threadState is true.
while(threadState){
Log.d("msg",String.valueOf(count));
try {
sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
count++;
}
}
}).start();
return START_NOT_STICKY;
}
@Override
public void onDestroy(){
Log.d("msg","onDestroy");
//StopService in MainActivity()When you call onDestroy()Is called
//MyService is stopped, Thread is also set to stopped
serviceState = false;
threadState = false;
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
Thread destruction (stop ()) is deprecated from API15. That said, even before that, there was a code need such as wanting to destroy Thread or forcibly terminating it, and I also recommended code that can be destroyed. However, it has been deprecated since API15. This is because thread discard leaves a lot of bad trash.
When Thread is running normally, protected objects can become unstable due to Thread discard, which can lead to unexpected behavior. Since it is difficult to find and identify objects that have been released from Thread, let's consider whether to design a program with interrupt () without discarding Thread, and from API 15 the thread is forcibly terminated. It has been deprecated. For cute and cute apps (and for users who love your app), please do not use Thread.stop () and use interrupt () to design your code!
If you still like stop ()! So, isn't it good to use it so that there are no missing people (objects, etc.)?
□ UI thread <-worker thread □ Worker thread <-Worker thread
Handle is a class that communicates between threads, and the thread that created the Handle instance has the functions of Queue and Looper required for communication. Information sent from other threads is stored in a queue, and Looper retrieves the stored information and processes it in the main thread (since it is processed in the main thread, UI parts can also be operated).
It seems that UI parts cannot be operated directly from the worker thread, so use the methods and classes for operating the UI parts to act as if the operation processing of the UI parts is passed to the UI thread.
The method of manipulating View using View.post becomes difficult to maintain when the operation becomes complicated </ font>. There is also a way to use Handle in the worker thread, but AsyncTask is recommended for reference.
View.post () and View.postDelayed (), both methods on the View object. Post () from different View (TextView.post () or Button.Post ()) will be received as the same View.post () on the receiving queue side (identify the sender as TextView or EditText) Not).
public boolean post(Runnable action)
View class methods: Like TextView.post, TextEdit.post (), Button.post (), view parts can use post () and postDelayed () methods. post adds Runnable to the message queue and processes Runnable in the UI thread. If the Runnable process is successful, it will return true. If false, it seems that there are many cases where the message queue has ended.
activity_main.xml
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
android:id="@+id/textView"
/>
Using the Thread class
public class MainActivity extends AppCompatActivity {
public static TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.textView);
//Instantiate and start Thread class
ThreadSample threadSample = new ThreadSample();
threadSample.start();
}
}
class ThreadSample extends Thread{
public void run(){
//Operate UI parts of the main activity
// post()Since the method takes Runnable as an argument, it is as follows
MainActivity.textView.post(new Runnable(){
@Override
public void run() {
MainActivity.textView.setText("From ThreadSample");
}
});
}
}
As a reminder, I will write it in the anonymous class as well.
python
public class MainActivity extends AppCompatActivity {
public static TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.textView);
new Thread(new Runnable() {
@Override
public void run() {
textView.post(new Runnable() {
@Override
public void run() {
textView.setText("From Another Thread");
}
});
}
}).start();
}
}
public boolean postDelayed(Runnable action,long delayMillis) delay ... delay; Millis ... milliseconds </ font> postDelayed adds Runnable to the message queue and, after a specified amount of time, processes the Runnable in the UI thread.
When you execute the code below, the textview will be greeted with the initial value "Hello World!", But after 5 seconds, the display will change to "From ThreadSample".
activity_main.xml
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
android:id="@+id/textView"
/>
In Thread class
public class MainActivity extends AppCompatActivity {
public static TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.textView);
ThreadSample threadSample = new ThreadSample();
threadSample.start();
}
}
class ThreadSample extends Thread{
public void run(){
MainActivity.textView.postDelayed(new Runnable(){
@Override
public void run() {
MainActivity.textView.setText("From ThreadSample");
}
},5000);
}
}
public final void runOnUiThread(Runnable action)
Activity class method: ** Activity can use runOnUiThread () **. Activity provides the UI screen.
runOnUiThread executes the specified action on the UI thread. If the current thread is a UI thread, the action will be executed immediately! Otherwise, the action will be added to the UI thread's event queue. It seems that the behavior works much like the post () method! ..
public class MainActivity extends AppCompatActivity {
public static TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.textView);
new Thread(new Runnable(){
@Override
public void run() {
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
textView.setText("runOnUiThread");
}
});
}
}).start();
}
}
■Handler For more information, click here "Hanler Summary" Handlers can be used to send Runnable objects and process messages associated with a thread's message queue. Instances of Handler are associated with single threads and message queues. Returns true when added to the message queue. It is not whether the process was successful. If the looper exits before the specified time has elapsed, Runnable will be abandoned. If false, suspect that the message queue has ended!
■android.os.AsyncTask public abstract class AsyncTask extends Object android.os.AsyncTask<Params,Progress,Result>
Summary here Reference code here
AsyncTask is an asynchronous process. Especially suitable for short-time asynchronous processing. ** Please use other APIs (Executor, ThreadPoolExecutor, etc.) ** for processing that runs for a long time!
Recommended Posts