个人建购物网站怎么备案,用redis加速wordpress,网站论坛推广文案怎么做,wordpress汉化插件软件HandlerThread **一、HandlerThread的基本概念和用途**1. **目的**2. **与普通线程的区别** **二、HandlerThread的使用步骤**1. **创建HandlerThread对象并启动线程**2. **创建Handler并关联到HandlerThread的消息队列**3. **发送消息到HandlerThread的消息队列** **三、Handl… HandlerThread **一、HandlerThread的基本概念和用途**1. **目的**2. **与普通线程的区别** **二、HandlerThread的使用步骤**1. **创建HandlerThread对象并启动线程**2. **创建Handler并关联到HandlerThread的消息队列**3. **发送消息到HandlerThread的消息队列** **三、HandlerThread的生命周期和注意事项**1. **生命周期**2. **注意事项** 四、使用 HandlerThread 和 线程池 举同一个例子1. **使用HandlerThread的示例下载文件并更新UI**2. **使用线程池的示例下载文件并更新UI同样的功能**3.例子1中的 handler 不在主线程了么 参考地址 HandlerThread是Android中的一个类它继承自Thread主要用于在一个单独的线程中处理消息队列MessageQueue。以下是关于它的详细内容
一、HandlerThread的基本概念和用途
1. 目的
在Android开发中为了避免在主线程UI线程执行耗时操作而导致应用程序出现“ANRApplication Not Responding”的情况需要将一些耗时任务如网络请求、文件读写等放到后台线程中执行。HandlerThread提供了一种方便的方式来创建一个带有消息队列的后台线程。(和handler一起配合使用达到)它允许通过Handler发送消息到该线程的消息队列中然后在该线程中按照消息发送的顺序依次处理这些消息。这样就可以在一个单独的线程中有序地执行一系列任务。
2. 与普通线程的区别 普通线程没有自带的消息队列机制。如果要在普通线程中处理多个任务需要自己实现任务调度和排队等复杂的逻辑。而HandlerThread内部已经实现了消息队列并且可以通过Handler方便地与其他线程进行通信。 例如在一个普通线程中如果要处理多个不同类型的任务可能需要使用复杂的状态机或者阻塞队列等方式来管理任务。但是HandlerThread通过消息机制Message和MessageQueue可以很方便地通过sendMessage等方法发送任务请求并且在Handler的handleMessage方法中处理这些任务。
二、HandlerThread的使用步骤
1. 创建HandlerThread对象并启动线程
首先需要创建一个HandlerThread对象。例如
HandlerThread handlerThread new HandlerThread(MyHandlerThread);
handlerThread.start();这里创建了一个名为MyHandlerThread的HandlerThread然后调用start方法来启动这个线程。启动后该线程就会开始运行并且创建一个与之关联的消息队列。
2. 创建Handler并关联到HandlerThread的消息队列
接着需要创建一个Handler对象并将其与HandlerThread的消息队列关联起来。可以通过以下方式实现
Handler handler new Handler(handlerThread.getLooper()) {Overridepublic void handleMessage(Message msg) {// 在这里处理消息switch (msg.what) {case 1:// 执行任务1break;case 2:// 执行任务2break;}}
};这里通过handlerThread.getLooper()获取HandlerThread的Looper对象。Looper是一个用于循环获取消息队列中的消息并分发给Handler的类。通过这种方式创建的Handler就可以将消息发送到HandlerThread的消息队列中并且在handleMessage方法中处理这些消息。
3. 发送消息到HandlerThread的消息队列
最后可以通过Handler发送消息到HandlerThread的消息队列中。例如
Message message new Message();
message.what 1;
handler.sendMessage(message);这里创建了一个Message对象设置了消息的what属性用于区分不同类型的消息然后通过handler.sendMessage方法将消息发送到HandlerThread的消息队列中。HandlerThread中的Looper会不断地从消息队列中获取消息并将消息分发给关联的Handler的handleMessage方法进行处理。
三、HandlerThread的生命周期和注意事项
1. 生命周期
当HandlerThread对象被创建并调用start方法后线程开始运行消息队列被创建Looper开始循环获取消息。只要还有未处理的消息在消息队列中或者Looper没有被显式地退出HandlerThread就会一直运行。可以通过调用HandlerThread的quit或者quitSafely方法来退出Looper从而结束HandlerThread的运行。例如
handlerThread.quitSafely();quitSafely方法会在处理完当前消息队列中的已有消息后退出Looper而quit方法会立即退出Looper可能会导致消息丢失。
2. 注意事项
内存泄漏如果Handler对象是一个内部类并且它间接引用了外部类例如Activity的实例而HandlerThread的生命周期又比外部类长那么可能会导致外部类无法被垃圾回收从而引起内存泄漏。为了避免这种情况可以将Handler定义为静态内部类并使用弱引用WeakReference来引用外部类实例。消息处理顺序HandlerThread中的消息是按照发送的顺序依次处理的。如果有高优先级的任务需要在消息机制的基础上进行适当的调整例如可以通过设置消息的优先级或者在handleMessage方法中根据任务的紧急程度优先处理某些消息。
四、使用 HandlerThread 和 线程池 举同一个例子
1. 使用HandlerThread的示例下载文件并更新UI
布局文件activity_main.xml 简单的布局包含一个按钮用于触发下载和一个文本视图用于显示下载状态。 ?xml version1.0 encodingutf-8?
LinearLayout xmlns:androidhttp://schemas.android.com/apk/res/androidandroid:orientationverticalandroid:layout_widthmatch_parentandroid:layout_heightmatch_parentButtonandroid:idid/download_buttonandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:text下载文件/TextViewandroid:idid/status_textandroid:layout_widthwrap_contentandroid:layout_heightwrap_content/
/LinearLayoutJava代码MainActivity.java 在MainActivity中实现下载文件的功能。 import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {private HandlerThread handlerThread;private Handler handler;private TextView statusText;Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button downloadButton findViewById(R.id.download_button);statusText findViewById(R.id.status_text);// 创建HandlerThread并启动handlerThread new HandlerThread(DownloadThread);handlerThread.start();// 创建Handler并关联到HandlerThread的消息队列handler new Handler(handlerThread.getLooper()) {Overridepublic void handleMessage(Message msg) {if (msg.what 1) {// 模拟下载文件的过程try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}// 下载完成后发送消息到主线程更新UIMessage uiMessage new Message();uiMessage.what 2;uiHandler.sendMessage(uiMessage);}}};downloadButton.setOnClickListener(new View.OnClickListener() {Overridepublic void onClick(View v) {// 发送下载文件的消息到HandlerThreadMessage downloadMessage new Message();downloadMessage.what 1;handler.sendMessage(downloadMessage);statusText.setText(正在下载...);}});// 创建用于更新UI的主线程HandlerHandler uiHandler new Handler(getMainLooper()) {Overridepublic void handleMessage(Message msg) {if (msg.what 2) {statusText.setText(下载完成);}}};}Overrideprotected void onDestroy() {super.onDestroy();// 退出HandlerThreadhandlerThread.quitSafely();}
}首先在onCreate方法中创建HandlerThread并启动它然后创建与HandlerThread消息队列关联的Handler。当用户点击下载按钮时发送一个消息到HandlerThread的消息队列在handleMessage方法中模拟文件下载过程这里通过Thread.sleep来模拟耗时操作。下载完成后发送一个消息到主线程的Handler来更新UI显示下载完成的状态。最后在onDestroy方法中退出HandlerThread。
2. 使用线程池的示例下载文件并更新UI同样的功能
布局文件与上面相同activity_main.xmlJava代码MainActivity.javaimport android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class MainActivity extends AppCompatActivity {private ExecutorService executorService;private TextView statusText;Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button downloadButton findViewById(R.id.download_button);statusText findViewById(R.id.status_text);// 创建一个单线程的线程池这里可以根据需要调整线程池大小executorService Executors.newSingleThreadExecutor();downloadButton.setOnClickListener(new View.OnClickListener() {Overridepublic void onClick(View v) {statusText.setText(正在下载...);// 提交下载任务到线程池executorService.submit(new Runnable() {Overridepublic void run() {try {// 模拟下载文件的过程Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}// 下载完成后发送消息到主线程更新UIHandler uiHandler new Handler(getMainLooper()) {Overridepublic void handleMessage(Message msg) {if (msg.what 1) {statusText.setText(下载完成);}}};Message uiMessage new Message();uiMessage.what 1;uiHandler.sendMessage(uiMessage);}});}});}Overrideprotected void onDestroy() {super.onDestroy();// 关闭线程池executorService.shutdown();}
}这里在onCreate方法中创建一个单线程的线程池ExecutorService。当用户点击下载按钮时将下载任务以Runnable的形式提交到线程池。在Runnable的run方法中模拟文件下载过程下载完成后创建一个主线程的Handler并发送消息到主线程来更新UI显示下载完成的状态。最后在onDestroy方法中关闭线程池。这两种方式都实现了在后台执行下载任务避免阻塞主线程并且在任务完成后更新UI的功能。
3.例子1中的 handler 不在主线程了么
handler不在主线程中 在第一个例子中handler关联的是HandlerThread的Looper而HandlerThread是一个单独的后台线程。当创建handler时通过handlerThread.getLooper()获取的是HandlerThread线程中的Looper对象。例如代码中的这部分 handler new Handler(handlerThread.getLooper()) {Overridepublic void handleMessage(Message msg) {if (msg.what 1) {// 模拟下载文件的过程try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}// 下载完成后发送消息到主线程更新UIMessage uiMessage new Message();uiMessage.what 2;uiHandler.sendMessage(uiMessage);}}
};这个handler的handleMessage方法是在HandlerThread线程中执行的。HandlerThread提供了一个后台线程环境这样就可以在这个线程中执行一些耗时的操作比如模拟文件下载通过Thread.sleep来模拟耗时而不会阻塞主线程。 与主线程通信的uiHandler 为了更新UI又创建了一个uiHandler它是关联到主线程UI线程的Looper的。代码如下 Handler uiHandler new Handler(getMainLooper()) {Overridepublic void handleMessage(Message msg) {if (msg.what 2) {statusText.setText(下载完成);}}
};当后台HandlerThread中的任务完成后通过uiHandler发送消息到主线程的消息队列然后在主线程中执行uiHandler的handleMessage方法来更新UI。这是因为在Android中只有主线程才能更新UI所以需要这种跨线程通信的方式来在后台任务完成后更新界面显示。
参考地址
豆包 AI