最近在进行Android项目的网络编程阶段,所以用到了许多网络方面的知识,在Android4.0版本以上,对网络的访问有了更加严格的限制,如果此时需要一个耗时的操作,例如: 联网读取数据,或者读取本地较大的一个文件的时候,你不能把这些操作放在主线程中,而是要开启另一条线程来进行网络操作,如果你放在主线程中的话,界面会出现假死现象, 如果5秒钟还没有完成的话,会收到Android系统的一个错误提示 "强制关闭"。但是如果是要将从网络中获取到的数据进行页面显示的话,那么就需要我们在Android的主线程中进行UI更新,这就出现了一种矛盾。这时候对于线程间的通信,那么我们需要一种方式来传递数据。Handler应运而生。
如何使用Handler呢,下面我们就对Handler的详细用法进行说明。
package org.qust.mp3player;
import java.io.Serializable;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import javax.xml.parsers.SAXParserFactory;
import org.qust.domain.MP3Info;
import org.qust.download.DownLoad;
import org.qust.utils.MyHandler;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ListView;
import android.widget.Toast;
public class MainActivity extends Activity {
private static final String LOCATION = "http://223.81.87.84:8080/examples/mp3.xml";
private static final int UPDATE = 1;
private static final int ABOUT = 2;
ListView listview = null;
Handler myHandler;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//创建一个ListView对象
listview = (ListView) findViewById(R.id.listview1);
//在主线程中创建Handler对象,并且复写它的handlerMessage方法,这个方法负责接收从子线程中所传递过来的数据
myHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
//Bundle对象负责数据接收
Bundle b = msg.getData();
List<HashMap<String, String>> list_msg = new ArrayList<HashMap<String, String>>();
list_msg = (List<HashMap<String, String>>) b.get("list");
//通过Myadapter对象将数据映射到ListView控件上面
Myadapter myadapter = new Myadapter(MainActivity.this);
myadapter.setList(list_msg);
listview.setAdapter(myadapter);
myadapter.notifyDataSetChanged();
}
};
}
//创建菜单按钮
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// TODO Auto-generated method stub
menu.add(0, 1, 1, R.string.update);
menu.add(0, 2, 2, R.string.about);
return super.onCreateOptionsMenu(menu);
}
//判断点击那个按钮
@Override
public boolean onMenuItemSelected(int featureId, MenuItem item) {
// TODO Auto-generated method stub
if (item.getItemId() == UPDATE) {
//开启线程
Thread thread = new Thread(downThread);
thread.start();
}
if (item.getItemId() == ABOUT) {
Toast.makeText(MainActivity.this, "作者是KingAnty,版本为1.0",
Toast.LENGTH_LONG).show();
}
return super.onMenuItemSelected(featureId, item);
}
//获取XML文件中解析所得的数据,我的XML文件是在Tomcat服务器上
public List<HashMap<String, String>> getInfoList() {
try {
// 获得一个解析工厂
SAXParserFactory sf = SAXParserFactory.newInstance();
// 通过SaxParser获取一个XMLReader解析器
XMLReader xr = sf.newSAXParser().getXMLReader();
// 设置解析所用的Handler对象
List<MP3Info> mp3Infos = new ArrayList<MP3Info>();
MyHandler mh = new MyHandler(mp3Infos);
xr.setContentHandler(mh);
// 获取一个输入流,输入流中包含未被解析的数据
xr.parse(new InputSource(new StringReader(new DownLoad()
.downLoad(LOCATION))));
List<HashMap<String, String>> list = new ArrayList<HashMap<String, String>>();
for (MP3Info mp3Info : mp3Infos) {
HashMap<String, String> map = new HashMap<>();
map.put("map3Name", mp3Info.getMp3Name());
map.put("mp3Size", mp3Info.getMp3Size().toString());
list.add(map);
}
return list;
} catch (Exception e) {
// TODO: handle exception
e.getMessage().toString();
}
return null;
}
//通过实现Runnable接口来创建一个子线程
Runnable downThread = new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
try {
List<HashMap<String, String>> list = getInfoList();
//将子线程获得的数据放入Message对象中,通过Handler进行发送
Message msg = new Message();
Bundle b = new Bundle();// 存放数据
b.putSerializable("list", (Serializable) list);
msg.setData(b);
myHandler.sendMessage(msg);
} catch (Exception e) {
e.getMessage().toString();
}
}
};
}