HandlerThread案例学习

(1) 2024-07-09 12:12

Hi,大家好,我是编程小6,很荣幸遇见你,我把这些年在开发过程中遇到的问题或想法写出来,今天说一说
HandlerThread案例学习,希望能够帮助你!!!。

Android的消息机制中,如果需要在子线程中创建Hanlder来处理消息,那么很经典的代码如下:

new Thread(new Runnable() { 
    @Override public void run() { 
    Looper.prepare(); handler = new Handler(Looper.myLooper()){ 
    @Override public void handleMessage(@NonNull Message msg) { 
    } }; Looper.loop(); } }).start 

这样处理比较繁琐,有点类似于Service中的意图服务的意思。因为自己创建比较繁琐,故而官方就提供了一套封装。

回顾一下:使用意图服务的时候,只需要自定义一个继承自IntentService的类,复写onHandleIntent方法即可,然后可在该方法中进行耗时操作,且操作完成后自动销毁Service

那么在使用HandlerThread的时候,应该如何?

HandlerThread 是一个包含 LooperThread,我们可以直接使用这个 Looper 创建 Handler

HandlerThread 所做的就是在新开的子线程中创建了 Looper,那它的使用场景就是 前面提到的需要在子线程中创建Handler,来处理消息的场景。

这里不妨看下这个类的构成:

public class HandlerThread extends Thread { 
    int mPriority; int mTid = -1; Looper mLooper; private @Nullable Handler mHandler; ... public void run() { 
    mTid = Process.myTid(); Looper.prepare(); synchronized (this) { 
    mLooper = Looper.myLooper(); notifyAll(); } Process.setThreadPriority(mPriority); onLooperPrepared(); Looper.loop(); mTid = -1; } public Handler getThreadHandler() { 
    if (mHandler == null) { 
    mHandler = new Handler(getLooper()); } return mHandler; } } 

在上面可以看见HandlerThread是一个线程类,且在run方法中初始化了对应的Looper对象,在getThreadHandler方法中创建一个和Looper关联的Handler对象。

那么,我们在使用的时候应该如何使用?不妨看看下面的简单案例:

public class MainActivity extends AppCompatActivity { 
    private Handler workHandler; @Override protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button button = findViewById(R.id.id_mybutton); // 【开启子线程】开启一个子线程来处理消息 Looper+Thread+Handler HandlerThread handlerThread = new HandlerThread("MyHandlerThread"); handlerThread.start(); workHandler = new Handler(handlerThread.getLooper()){ 
    @Override public void handleMessage(@NonNull Message msg) { 
    // 【子线程处理消息】 String channelId = "weizu"; // 1. 创建通知管理器 NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); // 2. 创建通道 NotificationChannel channel = new NotificationChannel(channelId, "Simple Test", NotificationManager.IMPORTANCE_DEFAULT); manager.createNotificationChannel(channel); // 3. 创建通知对象 Notification.Builder builder = new Notification.Builder(MainActivity.this, channelId); Intent intent = new Intent(getApplicationContext(), MainActivity.class); PendingIntent pi = PendingIntent.getActivity(getApplicationContext(), 0, intent, 0); Notification notification = builder.setContentTitle("Info") .setContentText((String) msg.obj) .setContentIntent(pi) .setSmallIcon(R.drawable.ic_baseline_bluetooth_24) .setAutoCancel(true) .build(); // 4. 发送通知 manager.notify(1, notification); } }; button.setOnClickListener(new View.OnClickListener() { 
    @Override public void onClick(View v) { 
    // 【主线程】点击事件来发送消息 Message msg = Message.obtain(); msg.what = 1; msg.obj = "Hello"; workHandler.sendMessage(msg); } }); } } 

在上面的结果中,我们在子线程HandlerThread中也可以在状态栏显示通知,进行了消息的处理。

需要注意的是,子线程中不可进行更新UI操作,显然,这里的Notification不属于更新UI操作。

注意到在run中调用了Looper.loop方法,故而是一个无限循环。

也就是说这个HandlerThread方法不会自动停止,我们需要显示的调用quit方法,当不需要的时候,可以结束线程,即workHandler.quit();


另在IntentService类中也有HandlerThread的影子:

public abstract class IntentService extends Service { 
    private volatile Looper mServiceLooper; private volatile ServiceHandler mServiceHandler; private final class ServiceHandler extends Handler { 
    public ServiceHandler(Looper looper) { 
    super(looper); } @Override public void handleMessage(Message msg) { 
    onHandleIntent((Intent)msg.obj); stopSelf(msg.arg1); } } ... public void onCreate() { 
    super.onCreate(); HandlerThread thread = new HandlerThread("IntentService[" + mName + "]"); thread.start(); mServiceLooper = thread.getLooper(); mServiceHandler = new ServiceHandler(mServiceLooper); } 

在个方法中类似的关联了Looper对象、Handler对象,以及前面提到的HandlerThread线程对象。且在onCreate周期函数中的使用方式和我们的案例中类似。

今天的分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。

上一篇

已是最后文章

下一篇

已是最新文章

发表回复