类似定时切换商品效果:
布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center_vertical"
tools:context=".HandlerTest">
<ImageView
android:id="@+id/show"
android:layout_gravity="center_horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#ff0000"
/>
</LinearLayout>
HandlerTest.java
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import java.util.Timer;
import java.util.TimerTask;
public class HandlerTest extends Activity {
//定义周期性显示的图片的ID
int[] imageIds = new int[]{
R.drawable.java,
R.drawable.ee,
R.drawable.ajax,
R.drawable.xml,
R.drawable.classic
};
int currentImageId = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ImageView show = (ImageView) findViewById(R.id.show); //现在已经不需要强制转换了
final Handler myHandler = new Handler() {
@Override
public void handleMessage(@NonNull Message msg) {
if (msg.what == 0x1233) {
show.setImageResource(imageIds[currentImageId++]);
if (currentImageId >= 5) { //i++之后应该是5,书上写的4,有误。4会少显示一张图片。
currentImageId = 0;
}
}
}
};
//定义一个计时器,让该计时器周期性地执行指定任务
new Timer().schedule(new TimerTask() {
@Override
public void run() {
//新启动的线程无法访问该Activity里的组件
//所以需要通过Handler发送消息
//这里我自己加的日志
Log.d("HandlerTest", "线程名称:" + Thread.currentThread().getName());
Message msg = new Message();
msg.what = 0x1233;
//发送消息
myHandler.sendMessage(msg);
}
}, 0, 800);
}
}
日志输出:
D/HandlerTest: 线程名称:Timer-0
D/HandlerTest: 线程名称:Timer-0
D/HandlerTest: 线程名称:Timer-0
D/HandlerTest: 线程名称:Timer-0
这个Timer-0线程是什么时候设置的?
new Timer().schedule(new TimerTask() {
@Override
public void run() {
...
}
}, 0, 800);
先看Timer的构造器:
public class Timer {
//作为TimerThread的构造器入参
private final TaskQueue queue = new TaskQueue();
private final TimerThread thread = new TimerThread(queue);
//serialNumber()方法在构造器中被调用
//juc包里面的AtomicInteger,在多线程环境下也能进行原子操作
private final static AtomicInteger nextSerialNumber = new AtomicInteger(0);
private static int serialNumber() {
return nextSerialNumber.getAndIncrement(); //返回值,然后把值加1
}
public Timer() { //Timer默认构造器
this("Timer-" + serialNumber());
}
public Timer(String name) {
thread.setName(name);
thread.start();
}
...
}
给TimerThread类型的成员变量thread设置了name,并启动了。接着看看这个TimerThread。
TimerThread是Timer的同级类:
TimerThread继承自Thread,重写了run()方法。所以thread.start()
就新建并启动了一个新线程。
class TimerThread extends Thread {
boolean newTasksMayBeScheduled = true;
private TaskQueue queue;
TimerThread(TaskQueue queue) {
this.queue = queue;
}
public void run() {
try {
mainLoop();
} finally {
// Someone killed this Thread, behave as if Timer cancelled
synchronized(queue) {
newTasksMayBeScheduled = false;
queue.clear(); // Eliminate obsolete references
}
}
}
private void mainLoop() {
...
}
}