1.Handler初识
(1)Handler是什么?有什么作用?
Handler是android提供用于更新UI的一套机制,也是消息处理机制。
Handler的主要作用有两个:
在新启动的线程中发送消息。
在主线程中获取,处理消息。
由于android中无法在主线程(即UI线程)中访问网络、无法在子线程中访问UI线程元素。故一般是在子线程中访问网络,然后使用Handler发送message通知主线程处理UI更新操作。
(2)Handler/Looper/MessageQueue/Message分别是干嘛的?
Message是消息原型,包含消息描述和数据;MessageQueue是消息队列;Looper完成消息循环 ;Handler就是驾驭整个消息系统模型,统领Message,MessgeQueue和Looper。
Handler发送消息和接收消息都是通过Message,而Message是由MessageQueue管理的,Looper用于阻塞和唤醒线程以便处理Message。
(3)同步异步是什么?
异步就是发送信息后,发送者发送信息后,就不再管,它还可以再去做别的事情。 同步就是发送者与接收者同步交流,发送完之后,必须傻等着,什么也不能做,就在那等收的消息。
2.Handler的实现和优化
(1)首先创建好handler.
new Handler()
(2)从子线程中发出消息,通过message对象,然后sendMessage()
what属性: 主线程用来识别子线程发来的是什么消息。
arg1属性/obj属性: 如果传递的消息类型为int型/其他类型,将数字赋给arg1,arg2/obj。
(3)在handler中捕获所需消息,实现响应
public void handleMessage(Message msg) {
}
3.1后台下载并更新进度:主线程点击按键、发起下载、开启子线程做下载、下载过程中通知主线程、同时主线程更新进度条
下载方法解:
(1)实例化URL对象,连接,然后获取要下载文件的输入流
(2)获取文件总长度
(3)获取存储设配的地址,指定文件下载的位置
(4)读取inputStream,并把读取的内容通过outputStream写进目标文件中
(5)获取消息对象,并把需要发送的消息放入MessageQueue中
(6)创建Handler对象,发送消息sendMessage(message)
private void download(String appUrl){
URL url = new URL(appUrl);
URLConnection urlConnection = url.openConnection();
InputStream inputStream = urlConnection.getInputStream();
int contentLength = urlConnection.getContentLength();
String downloadFolderName = Environment.getExternalStorageDirectory()
+ File.separator+"imooc"+File.separator;
File file = new File(downloadFolderName);
if (!file.exists()){
file.mkdir();
}
String fileName = downloadFolderName + "imooc.apk";
File apkFile = new File(fileName);
if (apkFile.exists()){
apkFile.delete();
}
int downloadSize = 0;
byte[] bytes = new byte[1024];
int length = 0;
OutputStream outputStream = new FileOutputStream(fileName);
while ((length = inputStream.read(bytes)) != -1){
outputStream.write(bytes,0,length);
downloadSize += length;
Message message = Message.obtain();
message.obj = downloadSize * 100 / contentLength;
message.what = DOWNLOAD_MESSAGE_CODE;
mHandler .sendMessage(message);
}
inputStream.close();
outputStream.close();
3.2Handler实现倒计时功能
(1)获取TextView控件
(2)创建Handler和Message对象,并延迟发送消息Message
(3)将Handler声明为静态类,并在类中增加一个对Activity的弱引用,重写handleMessage()方法
(4)在每次发消息之做判断,(因为消息本来就是循环发送的,故不用添加循环,只需重新创建message对象就可)
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mCountdownTimeTextView= (TextView)findViewById(R.id.countdownTimeTextView)
CountdownTimeHandler handler = new Countdown TimeHandler(this);
Message message = Message.obtain();
message.what = COUNTDOWN_TIME_CODE;
message.arg1 = MAX_COUNT;
handler.sendMessageDelayed(message,DELAY_MILLIS);
}
public static class CountdownTimeHandler extends Handler{
static final int MIN_COUNT = 0;
final WeakReference<MainActivity> mWeakReference;
CountdownTimeHandler(MainActivity activity){
mWeakReference = new WeakReference<> (activity );
}
public void handleMessage(Message msg) {
super.handleMessage(msg);
MainActivity activity =mWeakReference.get();
switch (msg.what){
case COUNTDOWN_TIME_CODE:
int value = msg.arg1;
activity.mCountdownTimeTextView.setText(String.valueOf(value --));
if (value >= MIN_COUNT) {
Message message = Message.obtain();
message.what = COUNTDOWN_TIME_CODE;
message.arg1 = value;
sendMessageDelayed(message, DELAY_MILLIS);
}
break;
}
3.3打地鼠
(1)初始化各控件,TextView(显示记录打了几只地鼠),Button(开始游戏),ImageView(要打的地鼠,也就是要点击的图片)
(2)点击开始游戏,发送消息
(3)声明一个Handler静态类,并在类中增加一个对Activity的弱引用,重写handleMessage()方法,设置地鼠出现位置
(4)activity.next()继续发送消息
private void next(int delayTime){
int position = new Random().nextInt(mPosition.length);
Message message = Message.obtain();
message.what =CODE;
message.arg1 = position;
mHandler.sendMessageDelayed(message,delayTime);
mTotalCount ++;
}
public static class DiglettHandler extends Handler{
public static final int RANDOM_NUBER = 500;
public final WeakReference<DiglettActivity> mWeakReference;
public DiglettHandler(DiglettActivity activity){
mWeakReference = new WeakReference<>(activity);
}
public void handleMessage(Message msg) {
super.handleMessage(msg);
DiglettActivity activity = mWeakReference.get();
switch (msg.what){
case CODE:
int position = msg.arg1;
activity.mDiglettImageView.setX(activity.mPosition[position][0]);
activity.mDiglettImageView.setY(activity.mPosition[position][1]);
activity.mDiglettImageView.setVisibility(View.VISIBLE);
int randomTime = new Random().nextInt(RANDOM_NUBER) + RANDOM_NUBER;
activity.next(randomTime);
break;
}