Handler译为处理者,不难理解,它的作用就算发送和处理消息。
在Android开发中,我们常常会使用单独的线程来完成某些操作。
如用一个线程来完成从网络上下载图片,然后显示在ImageView上。
在多线程操作时,Android中必须保证以下两点:
有了以上两点限制,我们在线程之间的消息如何进行传递?回顾一下Handler的作用,确实,线程之间的消息传递就是依靠它。
出处见图上水印
准备Button和TextView
要实现Handler线程之间的消息传递,需要重写Handler方法。
package com.example.a4_9handler;
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.text1);
}
//匿名内部类
private Handler handler=new Handler(){
//重写Handler方法
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
case 100:
textView.setText("下载完成");
break;
}
}
};
//使用线程模拟下载操作
public void download(View v){
new Thread(new Runnable() {
@Override
public void run() {
while (true){
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
break;
}
//下载完成后更新UI状态
//错误的示范:textView.setText("下载完成");
//发送了一个标记——100
handler.sendEmptyMessage(100);
}
}).start();
}
}
效果如下:
使用Handler通常完成以下两点工作:
Handler的相关方法:
- void handleMessage(Message msg):处理消息的方法,通常是用于被重写!
- sendEmptyMessage(int what):发送空消息
- sendEmptyMessageDelayed(int what,long delayMillis):指定延时多少毫秒后发送空信息
- sendMessage(Message msg):立即发送信息
- sendMessageDelayed(Message msg):指定延时多少毫秒后发送信息
- final boolean hasMessage(int what):检查消息队列中是否包含what属性为指定值的消息 如果是参数为(int what,Object object):除了判断what属性,还需要判断Object属性是否为指定对象的消息
在相关方法的帮助下,再看之前的案例
handler.sendEmptyMessage(100);
实际上是发送了一个空消息,并标记为100
其等价于下面一段话
//获取一个消息对象
Message msg=handler.obtainMessage();
//标记为100
msg.what=100;
//任意类型
msg.obj="要存储的信息";
//发送消息
handler.sendMessage(msg);
另外还可以延迟发送(之前是立即发送)
//在指定时间后发送消息(当前时间3秒后)
handler.sendEmptyMessageAtTime(200,System.currentTimeMillis()+3000);
//延迟多少时间后发送消息(延迟2秒)
handler.sendEmptyMessageDelayed(300,2000);
//对于非空有...
handler.sendMessageDelayed();
handler.sendMessageAtTime();
程序运行过程中会使用内存,正常情况下,退出时会释放内存。但是,如果在退出时占用的部分没有被正常释放,就会造成内存泄漏。
回顾之前的案例中,IDE已经给出了相应的警告——
This Handler class should be static or leaks might occur
这个处理程序类应该是静态的,否则可能会发生泄漏。
显然这么写是不合理的。
在外部类内定义Handler,Handler会持有外部类的引用(内部类的对象会依赖于外部类的对象),在使用的时候,退出Activity,Activity对象会被销毁,此时如何Handler还在工作,且获取外部类的引用(Handler隐式的获取Activity对象),结果就是Activity无法正常退出(Activity依然占有内存)
即存在内存泄漏风险
新建一个Activity(HandlerMemoryActivity)
package com.example.a4_9handler;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class HandlerMemoryActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_handler_memory);
//使用handler延迟执行一个Runnable
handler.postDelayed(new Runnable() {
@Override
public void run() {
System.out.println("Runnable");
}
//延迟10分钟
},1000*60*10);
//10分钟后关闭当前Activity
finish();
}
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
};
}
启动程序,程序一闪而过,看似退出,实际上还是在后台继续运行。
package com.example.a4_9handler;
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 HandlerMemoryActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_handler_memory);
//使用handler延迟执行一个Runnable
handler.postDelayed(new Runnable() {
@Override
public void run() {
System.out.println("Runnable");
}
//延迟10分钟
},1000*60*10);
//10分钟后关闭当前Activity
finish();
}
/* private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
};*/
private MyHandler handler=new MyHandler(this);
private static class MyHandler extends Handler{
//弱引用,引用当前Activity
WeakReference weakReference;
public MyHandler(HandlerMemoryActivity activity){
weakReference=new WeakReference(activity);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
HandlerMemoryActivity activity=weakReference.get();
if (activity!=null){
}
}
}
}
新建一个Activity(,并准备一张图片(用作闪屏页)
布局方面,Imageview也好,background也好,反正就是把准备好的图片设置为Activity的背景
android:background="@mipmap/s123"
闪屏页显然不需要标题栏,于是可以在配置清单文件里设置一下全屏的主题。
android:theme="@android:style/Theme.DeviceDefault.Light.NoActionBar.Fullscreen"
完整代码如下:
package com.example.a4_9handler;
import android.app.Activity;
import android.content.Intent;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
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();
}
效果如下:三秒后从图1跳到图2
Android提供的一个抽象类,可以更好的协助我们完成多线程编程,这部分在
https://blog.csdn.net/nishigesb123/article/details/89145264
这篇文章中描述