在主线程中直接写耗时操作的话很容易引起ANR异常,所以我们都把耗时操作写在子线程中去完成,但执行完之后,想要更新页面,又不允许在子线程中去更改页面 -- 异步任务 或加载器解决了此问题。除了以上两种解决方式外,使用Thread +Handler也可实现上述效果。
“Handler的作用:注意是在android.os包下的类
(1)、发送并处理消息
(2)、可以排队执行一系列的动作
此类介绍Handler的最最最基本使用
一. 发送空消息
static final int LOADING_START= 1;
static final int LOADING_FINISH=0;
Button textView;
/*
* 创建Handler对象,
* */
Handler handler = new Handler(){
//此处接收所有有当前handler对象通过send方法发出的消息
//参数代表接收到的消息对象
@Override
public void handleMessage(Message msg) {
//通过msg对象的what属性取出当前接收到的消息的标识
if (msg.what == LOADING_FINISH) {
textView.setText("我要当大牛");
}
super.handleMessage(msg);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (Button) findViewById(R.id.textview);
}
//模拟按钮 进行耗时操作
public void click(View v) {
new Thread(){
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//更新页面操作
/*
* 如果直接在子线程执行更改UI的操作的话
* 会抛出CalledFromWrongThreadException
* 引起程序的崩溃
* 原因:规定子线程不允许操作UI页面
*
* 注意:Toast,对话框这种弹出窗口的show方法也算是UI操作
* */
// textView.setText("zss");
// Toast.makeText(MainActivity.this,"哈哈先生",Toast.LENGTH_SHORT);
/*
* 不让在子线程中写,那么我就想办法把我要干的事情传出去,在某一个位置
* 接收到我在子线程中传出的事情,并执行 通过Handler发送消息
* */
//发送一个空消息
handler.sendEmptyMessage(LOADING_FINISH);
}
}.start();
}
完整代码已贴出,附有详细注释,上述代码只是发送了一个简单的空消息。
补充知识点:对于上述发送的消息,结构为 耗时+发送的结构。现在我们改为 发送 + 耗时 +发送 代码如下:
只需在如下方法中添加这几行代码即可
public void handleMessage(Message msg) {
//通过msg对象的what属性取出当前接收到的消息的标识
if (msg.what == LOADING_FINISH) {
textView.setText("我要当大牛");
}else if(msg.what == LOADING_START){
textView.setText("等待时间");
}
super.handleMessage(msg);
}
new Thread(){
@Override
public void run() {
handler.sendEmptyMessage(LOADING_START);
try {
Thread.sl
剩余代码都是一样的,就不完整贴出了。
二. 发送非空消息
** //通过Handler发送非空消息
/*
* 当想要发送非空消息的时候,
* 1.封装要发送的消息对象
* 在初始化Message对象的时候,推荐使用以下的初始化方式
* 原因:下面的方式比new 的方式效率高,节省内存“
* /*
//模拟按钮 进行耗时操作
public void click(View v) {
new Thread(){
@Override
public void run() {
//handler.sendEmptyMessage(LOADING_START);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// Message msg = Message.obtain(); //第一种方式
Message msg = handler.obtainMessage(); //第二种方式
//向msg中存取数据
msg.what = LOADING_FINISH;
msg.arg1 = 2;
msg.arg2 = 3;
msg.obj = System.currentTimeMillis();
//调用sendMessage()方法 把Message的对象传进去
handler.sendMessage(msg);
}
}.start();
}
Handler handler = new Handler(){
//此处接收所有有当前handler对象通过send方法发出的消息
//参数代表接收到的消息对象
@Override
public void handleMessage(Message msg) {
//通过msg对象的what属性取出当前接收到的消息的标识
int a =msg.arg1; //取值
int b =msg.arg2; //取值
Long s = (Long) msg.obj;
textView.setText(a+" " + b+" " +s);
super.handleMessage(msg);
}
};
如果想要存储多个数据的话:采用Bundle 如下:
//模拟按钮 进行耗时操作
public void click(View v) {
new Thread(){
@Override
public void run() {
//handler.sendEmptyMessage(LOADING_START);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// Message msg = Message.obtain(); //第一种方式
Message msg = handler.obtainMessage(); //第二种方式
//向msg中存取数据
msg.what = LOADING_FINISH;
Bundle bundle = new Bundle();
bundle.putString("data", "dfasdfa");
bundle.putBoolean("boo", true);
msg.setData(bundle);
//调用sendMessage()方法 把Message的对象传进去
handler.sendMessage(msg);
}
}.start();
}
Handler handler = new Handler(){
//此处接收所有有当前handler对象通过send方法发出的消息
//参数代表接收到的消息对象
@Override
public void handleMessage(Message msg) {
//通过msg对象的what属性取出当前接收到的消息的标识
if(msg.what == LOADING_FINISH) {
Bundle data = msg.getData();
textView.setText(data.getString("data")+" "+data.getBoolean("boo"));
super.handleMessage(msg);
}
}
};
好了,第一节的简单的handler的用法,先写到这哈。以上代码如有不妥指出,还望指出谢谢。。