- 1. Java Thread多线程
- 2. Handler
- 3. Message
- 4. MessageQueue
- 5. Looper
- 6. AtomicBoolean
- 7. Handler使用总结
- 8. 案例
- 8.1 倒计时
- 8.2 计时器
- 8.3 获取网页内容
- 参考博文(侵删)
Adnroid官方文档
两种方式创建并启动线程
- 方式一: 继承 java.lang.Thread 并重写run()
class myThread extends Thread{ // 成员变量 private int num; myThread(int num){ this.num = num; } @Override public void run(){ //... } } // 启动线程 new myThread(10).start();
- 方式二:实现 Runnable 接口
class myThread implements Runnable{ private int num; myThread(int num){ this.num = num; } @Override public void run(){ //... } } // 启动线程 new Thread(new myThread(10)).start();2. Handler
Handler : 线程之间传递消息的即时接口,生产线程和消费线程调用以下 *** 作使用Handler:
- 在消息队列创建、插入或移除消息
- 在消费线程中处理消息
每个Handler有一个与之相关的 Looper 和消息队列MessageQueue。
同一线程的多个Handler分享一个同样的消息队列,因为他们分享的Looper对象是同一个。
关于Handler的构造函数官方文档
在构造函数中,looper对象可以通过Looper.myLooper() 创建并获取
3. Message官方文档
Message 是容纳任意数据的容器,是Handler接收与处理的消息对象。
生产消息发送消息给Handler,Hadnler将消息加入到消息队列中。
该对象提供三种信息,以便Handler和消息队列处理时使用:
- what 一种标识符,Hander能使用它区分不同消息,从而采取不同的处理方法
- time 告知消息队列何时处理消息
- target 表示哪一个Handler 应当处理消息
该对象的创建方式有:
Handler.obtainMessage(); Handler.obtainMessage(int what); Handler.obtainMessage(int what, Object obj); Handler.obtainMessage(int what, int arg1, int arg2); Handler.obtainMessage(int what, int arg1, int arg2, Object obj);
通过Bundle对象设置消息的数据
public void setData (Bundle data);4. MessageQueue
官方文档
消息队列(为方便阅读,简写为MQ),以FIFO方式管理所有的Message对象。
是一个linkedList集合
- 在初始化Looper对象时会创建一个与之关联的MQ
- 每个线程最多只有一个MQ
- MQ通常是由 Looper 管理
- 主线程创建时,会创建一个默认的Looper对象,从而自动创建一个MQ
官方文档
负责从消息队列MessageQueue中读取消息,然后分发给对应的Handler处理。
每个线程只能管理一个Looper。
使用范例:
class LooperThread extends Thread { public Handler mHandler; public void run() { Looper.prepare(); mHandler = new Handler(Looper.myLooper()) { public void handleMessage(Message msg) { // process incoming messages here } }; Looper.loop(); } }6. AtomicBoolean
作为 java.util.concurrent.atomic 包下的一个类,指原子性的Boolean类型
该类实现的是在多线程环境下,具有排他性,不会被打断,常用方法:
构造方法:initialValue(Boolean b)
7. Handler使用总结首先在AppCompatActivity.java类中创建 h a n d l e r handler handler 对象,传入两个参数,第一个是 l o o p e r looper looper,第二个是 C a l l b a c k ( ) Callback() Callback()接口的实现类,
该接口方法实现的是当线程接收到消息 m e s s a g e message message 时做出的响应,在倒计时的案例里就是更新 T e x t V i e w TextView TextView,即显示当前的数字。
综上,Handler作为线程之间传递消息的接口,实现步骤为:
- App主类负责编写handler对象接收到消息后的处理逻辑
- 线程类负责存储handler对象,以及在run方法里编写向Handler传递消息的具体实现
Handler传输的消息对象Message里的数据是通过对Java的数据类型或对象进行封装后的Bundle对象来传输的。
8. 案例8.1 倒计时
import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.view.View; import android.widget.TextView; class TimeCountThread extends Thread{ private Handler handler; private int timecount; public TimeCountThread(Handler handler, int timecount){ this.handler = handler; this.timecount = timecount; } @Override public void run() { for(int i = timecount; i >= 0; i--) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } Message message = handler.obtainMessage(); Bundle bundle = new Bundle(); bundle.putInt("Now", i); message.setData(bundle); handler.sendMessage(message); } } } public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView tv = findViewById(R.id.TextView); Handler handler = new Handler(Looper.myLooper(), new Handler.Callback() { @Override public boolean handleMessage(@NonNull Message message) { tv.setText(message.getData().getInt("Now") + ""); return false; } }); new TimeCountThread(handler, 100).start(); } }8.2 计时器
layout_main.xml
TimerCounterThread.java
package com.example.ycc_task4_1; import android.os.Bundle; import android.os.Handler; import android.os.Message; import java.util.concurrent.atomic.AtomicBoolean; public class TimerCounterThread extends Thread{ public static final String KEY_TIME_COUNTER = "key_time_counter"; private Handler handler; private AtomicBoolean isRunning; private float timeCount=0.0f; public TimerCounterThread(Handler handler) { this.handler = handler; isRunning = new AtomicBoolean(false); } @Override public void run() { super.run(); isRunning.set(true); while(isRunning.get()){ try{ Thread.sleep(100); timeCount += 0.10f; sendCounter(); } catch (InterruptedException e){ e.printStackTrace(); } } } private void sendCounter(){ Message mes = handler.obtainMessage(); Bundle bundle = new Bundle(); bundle.putFloat(KEY_TIME_COUNTER, timeCount); mes.setData(bundle); handler.sendMessage(mes); } public void stopTimer(){ isRunning.set(false); } }
MainActivity.java
import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.view.View; import android.widget.Button; import android.widget.TextView; import java.util.concurrent.atomic.AtomicBoolean; public class MainActivity extends AppCompatActivity { Button b_start, b_stop; TextView tv; TimerCounterThread thread; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.layout_main); b_start = findViewById(R.id.b_start); b_stop = findViewById(R.id.b_stop); tv = findViewById(R.id.tv_result); // 创建 Handler final Handler handler = new Handler(Looper.myLooper(), new Handler.Callback(){ @Override public boolean handleMessage(@NonNull Message message) { Bundle data = message.getData(); float timeCounter = data.getFloat(TimerCounterThread.KEY_TIME_COUNTER); tv.setText(String.format("%.2f", timeCounter)); return false; } }); b_start.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { thread = new TimerCounterThread(handler); thread.start(); b_start.setEnabled(false); b_stop.setEnabled(true); } }); b_stop.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { thread.stopTimer(); b_start.setEnabled(true); b_stop.setEnabled(false); } }); } }8.3 获取网页内容
首先需要在项目的 mainifests/AndroidMainifest.xml 里的 标签添加
允许项目进行网络访问
layout_main.xml
JsoupGetThread.java
package com.example.ycc_task4_2; import android.os.Bundle; import android.os.Handler; import android.os.Message; import org.jsoup.Jsoup; import org.jsoup.nodes.document; import java.io.IOException; public class JsoupGetThread extends Thread{ private static final String HTML_ACK = "html_ack"; private String url; private Handler handler; public JsoupGetThread(String url, Handler handler) { this.url = url; this.handler = handler; } public static String getMessage(Message mes){ Bundle data = mes.getData(); return data.getString(HTML_ACK); } @Override public void run() { String ack; try{ document doc = Jsoup.connect(url).timeout(10000).get(); ack = doc.toString(); } catch (IOException e){ e.printStackTrace(); ack = e.toString(); } Message mes = handler.obtainMessage(); Bundle bundle = new Bundle(); bundle.putString(HTML_ACK, ack); mes.setData(bundle); handler.sendMessage(mes); } }
MainActivity.java
import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.layout_main); TextView tv = findViewById(R.id.tv_ack); Handler handler = new Handler(new Handler.Callback(){ @Override public boolean handleMessage(@NonNull Message message) { String s = JsoupGetThread.getMessage(message); tv.setText(s); return false; } }); EditText et = findViewById(R.id.editText); Button bt = findViewById(R.id.button); bt.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { String url = et.getText().toString(); new JsoupGetThread(url, handler).start(); } }); } }参考博文(侵删)
-
Android 为什么要有handler机制?handler机制的原理
-
Android-Thread官方帮助文档
-
[译] 探索 Android 大杀器——Handler
-
Android-handler
-
理解AtomicBoolean
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)