Android Handler
此文是关于Handler的。 Handler主要接受子线程发送的数据, 并用此数据配合主线程更新UI。 当应用程序启动时,Android首先会开启一个主线程 (也就是UI线程) ,主线程为管理界面中的UI控件,进行事件分发, 比如说,你要是点击一个 Button ,Android会分发事件到Button上,来响应你的操作。如果此时需要一个耗时的操作,例如: 联网读取数据,或者读取本地较大的一个文件的时候,你不能把这些操作放在主线程中,如果你放在主线程中的话,界面会出现假死现象, 如果5秒钟还没有完成的话,会收到Android系统的一个错误提示 “强制关闭”。
这个时候我们需要把这些耗时的操作,放在一个子线程中,因为子线程涉及到UI更新,Android主线程不是线程安全的,也就是说,更新UI只能在主线程 中更新,子线程中操作是危险的。这个时候,Handler就出现了,来解决这个复杂的问题。Handler运行在主线程中(UI线程中),它与子线程可以 通过Message对象来传递数据,这个时候,Handler就承担着接受子线程传过来的(子线程用sedMessage()方法传递)Message对 象(里面包含数据),把这些消息放入主线程队列中,配合主线程进行更新UI。
Handler 是 android 提供的对于异步消息处理的方案。 Handler 的特点是与调用者处于同一线程,如果 Handler 里面做耗时的动作,调用者线程会阻塞。 Android UI 操作不是线程安全的,并且这些操作必须在 UI 线程中执行。
所以, Handler 经常被用来在另外的线程中更新 UI 界面。因为 UI 操作必须在 UI 线程中完成,可以通过 Handler 在别的线程中向 UI 线程发送刷新消息, UI 线程收到消息后执行相关操作。主要用到下面两个函数:
public final boolean sendMessage (Message msg) 发送消息
public void handleMessage(Message msg)
Handler 对于 Message 的处理不是并发的。一个 Looper 只有处理完一条 Message 才会读取下一条,所以消息的处理是阻塞形式的。
Handler一些特点:Handler可以分发Message对象和Runnable对象到主线程中, 每个Handler实例,都会绑定到创建他的线程中(一般是位于主线程),它有两个作用: (1): 安排消息或Runnable 在某个主线程中某个地方执行, (2)安排一个动作在不同的线程中执行。
Handler中分发消息经常使用post(Runnable)和sendMessage(Message)方法。
先是sendMessage的例子:
main.xml
Demo.java
package com.zhouzijing.android.demo;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
public class Demo extends Activity{
private final static String TAG = "DEMO";
private TextView textView;
private Button startButton;
private ProgressBar progressBar;
private MyHandler myHandler;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
textView=(TextView)findViewById(R.id.text);
startButton = (Button)findViewById(R.id.startButton);
progressBar=(ProgressBar)findViewById(R.id.bar);
progressBar.setMax(100);
myHandler=new MyHandler();
}
/**
* [开始演示]的按钮事件.
* @param v
*/
public void startIt(View v) {
Button btn = (Button)v;
//禁止演示按钮重复点击
btn.setClickable(false);
btn.setText("演示中...");
progressBar.setProgress(0);
textView.setText("演示信息:");
new Thread(new MyThread(1)).start();
}
//在对UI进行更新时,执行时所在的线程为主UI线程
//继承Handler类时,必须重写handleMessage方法
class MyHandler extends Handler{
public MyHandler(){
}
public MyHandler(Looper l){
super(l);
}
@Override
public void handleMessage(Message msg) {
//执行接收到的通知,此时执行的顺序是按照队列进行,即先进先出
Log.i(TAG,"Handler--The ThreadId is: "+Thread.currentThread().getId());
int what = msg.what;
//根据message的what属性来进行处理
switch(what){
case 100:
Bundle b=msg.getData();
String textStr1=b.getString("textStr");
textView.append(textStr1);//更改TextView中的值
int barValue=b.getInt("barValue");
progressBar.setProgress(barValue);//更改进度条当中的值
if(barValue==100){
//允许演示按钮点击
startButton.setText("演示结束,可以点击重新演示");
startButton.setClickable(true);
}
break;
default:
//其他message扔回上级处理.
super.handleMessage(msg);
}
}
}
//该线程将会在单独的线程中运行
class MyThread implements Runnable{
int index=1;
public MyThread(int index) {
this.index = index;
}
@Override
public void run() {
while(index
运行效果图,如下:
简单的说,Activity的onCreate方法里启动一个线程,在这个线程的run方法里使用一个Message对象并使用Handler的 sendMessage方法发送到队列中,最后在Activity里new一个Handler的内部类实现handMessage方法,使用这个方法把队 列中的Message对象取出来以实现异步操作。
得到Message对象的方法:(1)new Message();(2)handler对象的obtainMessage();前者需要新建一个Message对象,而后者直接从系统的Message池中获取1个(不用创建对象)。建议使用后者!
然后是post的例子,这里稍微说一下,直接使用new Handler().post(Runnable)这样的写法并没有新开线程。
xml配置文件
由于下面代码要访问网络和在sdcard上写文件,因此需要在AndroidManifest.xml配置权限:
代码文件:
package com.zhouzijing.android.demo;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import android.app.Activity;
import android.app.AlertDialog;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.TextView;
public class HandlerPostRunnable extends Activity {
private EditText edtDownloadUrl;
private ProgressBar pBarDownload;
private TextView tvProgressBarPercent;
private Button btnHandlerPostRunnable;
private int fileSize = 0;
private int progress = 0;
private final String TAG = "HandlerPostRunnable";
private Handler handler = new Handler();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.handler_post_runnable);
//定义组件
edtDownloadUrl = (EditText)findViewById(R.id.edtDownloadUrl);
pBarDownload = (ProgressBar)findViewById(R.id.pBarDownload);
tvProgressBarPercent = (TextView)findViewById(R.id.tvProgressBarPercent);
btnHandlerPostRunnable = (Button)findViewById(R.id.btnHandlerPostRunnable);
}
//开始演示-按钮事件
public void startIt(View v) {
Button btn = (Button)v;
btn.setText("下载中...");
btn.setClickable(false);
downloadFile(edtDownloadUrl.getText().toString());
}
/**
* 获取文件名.
* @param url
* @return
*/
private String getFileNameFromUrl(String url) {
String fileName = url.substring(url.lastIndexOf("/") + 1);
return fileName;
}
/**
* 下载文件.
* @param url
*/
private void downloadFile(final String url) {
new Thread() {
public void run() {
HttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet(url);
HttpResponse response = null;
FileOutputStream fos = null;
try {
response = client.execute(get);
HttpEntity entity = response.getEntity();
InputStream is = entity.getContent();
if (is != null) {
File file = new File(
Environment.getExternalStorageDirectory(),
getFileNameFromUrl(url));
fos = new FileOutputStream(file);
fileSize = (int)entity.getContentLength();
progress = 0;
downloadStart();
byte[] buf = new byte[1024];
int ch = -1;
while ((ch = is.read(buf)) != -1) {
fos.write(buf, 0, ch);
progress = progress+ch;
downloading();
}
}
fos.flush();
fos.close();
fos = null;
downloadFinished();
} catch (Exception e) {
Log.e(TAG, e.getMessage(), e);
downloadError(e);
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
Log.e(TAG, e.getMessage(), e);
}
fos = null;
}
}
}
}.start();
}
// 下载开始
private void downloadStart() {
handler.post(new Runnable() {
public void run() {
pBarDownload.setMax(fileSize);
pBarDownload.setProgress(0);
}
});
}
/**
* 设置下载进度百分比,
*/
private void setDownloadPercent() {
float percent = (float)progress/(float)fileSize*100;
int iPercent = (int)percent;
tvProgressBarPercent.setText(String.valueOf(iPercent)+"%");
}
// 下载中.
private void downloading() {
handler.post(new Runnable() {
public void run() {
pBarDownload.setProgress(progress);
setDownloadPercent();
}
});
}
// 下载成功结束
private void downloadFinished() {
handler.post(new Runnable() {
public void run() {
pBarDownload.setProgress(fileSize);
btnHandlerPostRunnable.setText("下载成功,点击再开始下载");
btnHandlerPostRunnable.setClickable(true);
setDownloadPercent();
new AlertDialog.Builder(HandlerPostRunnable.this)
.setTitle("提示").setMessage("下载成功")
.setPositiveButton("确定", null).show();
}
});
}
// 下载失败
private void downloadError(final Exception err) {
handler.post(new Runnable() {
public void run() {
btnHandlerPostRunnable.setText("下载失败,点击再开始下载");
btnHandlerPostRunnable.setClickable(true);
new AlertDialog.Builder(HandlerPostRunnable.this)
.setTitle("提示").setMessage("下载失败:"+err.getMessage())
.setPositiveButton("确定", null).show();
}
});
}
}
代码运行结果如下图:
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
机房租用,北京机房租用,IDC机房托管, http://www.fwqtg.net
相关推荐: 文字流光效果
一、html代码helloworld
二、css代码
总结提示:文字流光动画效果,炫酷标题 前言 提示:以下是本篇文章的代码内容,供大家参考,相互学习 一、html代码 好玩的聚光灯效果 helloworld 二、css代码 *{ /* 初始化 取消页面元素内外边距 */ margin: 0; padding: …