Handler
1.Handler介绍
在Android开发中,我们常常会使用单独的线程来完成某些操作,比如用一个线程来完成从网络上下载图片,然后显示在ImageView上,在多线程操作时,Android中必须保证以下两点:
- 不要阻塞UI线程
- 不要在UI线程之外访问Android UI工具包
有了以上两点限制,我们在线程之间的消息如何进行传递?Handler(消息的处理者)
package com.example.handler;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView=findViewById(R.id.textView);
}
//重写handler方法
private Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
case 100://下载完成后,更行UI状态
textView.setText("下载完成");
break;
}
}
};
public void downloadClick(View v){
//使用线程模拟下载操作
new Thread(new Runnable() {
@Override
public void run() {
while (true){
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
break;
}
//简写
handler.sendEmptyMessage(100);//发送一个空消息,标记为100
//全写
// Message msg=handler.obtainMessage();//获取一个消息对象
// msg.what=100;
// msg.obj="要存储的信息";//任意类型
// handler.sendMessage(msg);//发送消息
}
}).start();
}
}
发送消息的方法:
//在指定时间后发送消息
handler.sendEmptyMessageAtTime(200,System.currentTimeMillis()+3000);
//延迟多少时间后发送消息
handler.sendEmptyMessageDelayed(300,2000);
2.Handler常用API
使用Handler可以完成以下两点工作:
- 消息调度和将来的某个时间点执行一个Runnable
- 多个任务加入到一个队列中执行
Handler相关方法
void | handlerMessage(Message msg):Subclasses must implement this to recive messages. |
final Looper | getLooper() |
final Message | obtainMessage() |
final Message | obtainMessage(int what) |
final Message | obtainMessage(int what,Object obj) |
final boolean | post(Runnable r) |
final boolean | postAtTime(Runnable r,long uptimeMillis) |
final boolean | postDelayed(Runnable r,long delayMillis) |
3.Handler内部实现原理
Handler实现机制:
- Message对象,表示要传递的一个消息,内部使用链表数据结构实现一个消息池,用于重复利用,避免大量创建消息对象,造成浪费。
- Handler对象(消息处理者),负责把消息存入到消息队列中,以及接受Looper从消息队列中取出的消息,通过handlerMessage方法处理消息。
- MessageQueue对象,存放消息对象的消息队列,先进先出原则。
- Looper对象(消息队列处理者),负责管理当前线程的消息队列(MessageQueue),用于循环检查消息队列,从消息队列中一个一个的取出消息对象,传入handlerMessage方法。
Android启动程序时会在UI线程创建一个MessageQueue
4.Handler内存泄露问题分析
Handler内存泄露问题:activity虽然退出,但是Handler依然获取到activity的引用,导致activity没有完全退出,还是占用内存,导致内存泄露。
正确的Handler使用方法
package com.example.handler;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import java.lang.ref.WeakReference;
/*
* handler的内存泄露问题
* 1.定义一个内部类时,会默认拥有外部类对象的引用,所以建议使用内部类时,最好定义为一个静态内部类。
* 2.引用的强弱 强引用->软引用->弱引用
* */
public class HandlerMemoryActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_handler_memory);
//使用handler延迟执行一个Runnable(10分钟)
handler.postDelayed(new Runnable() {
@Override
public void run() {
System.out.println("runnable");
}
},1000*60*10);
finish();//关闭当前Activity
}
private MyHandler handler=new MyHandler(this);
//标准的Handler写法
private static class MyHandler extends Handler{
WeakReference<HandlerMemoryActivity> weakReference;
public MyHandler(HandlerMemoryActivity activity){
weakReference=new WeakReference<HandlerMemoryActivity>(activity);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
HandlerMemoryActivity activity=weakReference.get();
if (activity!=null){
}
}
}
}
5.使用Handler实现APP的闪屏页
闪屏页的作用
- 欢迎界面
- 初始化工作
设置闪屏页背景图片
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@mipmap/hf"
android:scaleType="centerCrop"/>
清单文件中设置全屏
android:theme="@android:style/Theme.DeviceDefault.Light.NoActionBar.Fullscreen"
实现闪屏页功能
package com.example.handler;
import android.app.Activity;
import android.content.Intent;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import java.lang.ref.WeakReference;
public class SplashActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
handler.postDelayed(new Runnable() {
@Override
public void run() {
startMainActivity();
}
},3000);
}
private void startMainActivity(){
Intent intent=new Intent(this,MainActivity.class);
startActivity(intent);
}
private Handler handler=new Handler();
// private final MyHandler handler=new MyHandler(this);
//
// private static class MyHandler extends Handler{
// private WeakReference<SplashActivity> weakReference;
// public MyHandler(SplashActivity activity){
// weakReference=new WeakReference<SplashActivity>(activity);
// }
// @Override
// public void handleMessage(Message msg) {
// super.handleMessage(msg);
// }
// }
}