Android学习笔记 day04 _ 网络编程
一、查看网页源码
获取网络数据模板:
new Thread() {
public void run() {
try {
// 1. 创建一个url对象 参数就是网址
String path = "url";
URL url = new URL(path);
// 2. 获取HttpURLConnection 链接对象
HttpURLConnection conn = (HttpURLConnection) url
.openConnection();
// 3. 设置参数 发送get请求
conn.setRequestMethod("GET"); // 必须大写
// 4. 设置链接网络的超时时间
conn.setConnectTimeout(5000);
// 5. 获取服务器返回的状态码
int code = conn.getResponseCode();
if (code == 200) {
// 6. 获取服务器给我们返回的数据
InputStream in = conn.getInputStream();
// 7. 处理结果
// 子线程不能更新UI,报错:android.view.ViewRootImplCalledFromWrongThreadException
// 使用Handler或runOnUiThread更新UI界面
runOnUiThread(new Runnable() {
@Override
public void run() {
// 8. 更新UI界面
}
});
}
} catch (Exception e) {
e.printStackTrace();
}
};
}.start();
二、 Android消息处理机制
执行过程:
1. 在主线程创建一个Handler对象 private Handler handler = new Handler() { // 重写handleMassage()方法 public void handleMessage(android.os.Message msg) { String result = (String) msg.obj; // 更新UI界面 }; }; 2. 创建一个message对象 Message msg = new Message(); 3. 把数据存入msg中 msg.obj = result; 4. 发送消息到handle中,handle自动执行handleMessage()方法 handler.sendMessage(msg);
执行原理:
前提知识:
所有使用UI界面的操作系统,后台都运行着一个死循环,在不停的监听和接收用户发出的指令,一旦接收指令就立即执行。
当我们的Android应用程序的进程一创建的时候,系统就给这个进程提供了一个Looper,Looper是一个死循环,它内部维护这个一个消息队列,
Loop不停地从消息队列中取消息(Message),取到消息就发送给了Handler,最后Handler根据接收到的消息去修改UI。
三、 常用消息处理API
runOnUiThread(Runnable action)方法:
原理:当执行线程是主线程的时候直接执行,不是主线程的时候加入主线程消息队列等待主线程执行
runOnUiThread(new Runnable() { @Override public void run() { // 更新UI界面 } });
handler.postAtTime(Runnable action)方法:
Runnable 线程的接口类,uptimeMillis从开机到现在间隔的毫秒数
handler.postAtTime(new Runnable() { @Override public void run() { // 更新界面操作 } }, 5000);
四、 两种更新UI界面的方法
原理:子线程不能更新UI(Android 2.3除外),报错:android.view.ViewRootImpl$CalledFromWrongThreadException,因此要将更新UI的操作交给主线程执行
1. 使用Handler消息传递机制 2. 使用runOnUiThread()方法
五、 综合案例:新闻客户端
画新闻客户端界面:
整个界面用一个ListView实现,在ListView中填充一个item布局,显示每条新闻样式
使用HttpURLConnection联网获取服务器上的xml数据文件
使用XmlPullParser解析xml文件读取数据存入List集合中
使用BaseAdapter适配器填充读取的数据到ListView中,更新UI界面
六、 使用开源工具:SmartImageView更新ImageView图片
开源工具的使用方法:
- 把smartImageView的源代码/src/com文件夹拷到自己的代码的src目录中 - 调用image.setImageUrl(item.getImage())方法加载图片
SmartImageView工作原理
由于ImageVIew没有直接根据图片路径填充图片的方法,需要获取获取网络图片后再转换成通过消息机制 交给UI线程绘制ImageView的图片,比较麻烦,而SmartImageView封装了这些操作
执行过程
1. 获取网络数据流 // 1. 创建一个url对象 参数就是网址 URL url = new URL(path); // 2. 获取HttpURLConnection 链接对象 HttpURLConnection conn = (HttpURLConnection) url .openConnection(); // 3. 设置参数 发送get请求 conn.setRequestMethod("GET"); // 必须大写 // 4. 设置链接网络的超时时间 conn.setConnectTimeout(5000); // 5. 获取服务器返回的状态码 int code = conn.getResponseCode(); if (code == 200) { // 6. 获取服务器给我们返回的数据 InputStream in = conn.getInputStream(); } 2. 将数据流转换为Bitmap // 7. 处理结果 bitmap = BitmapFactory.decodeStream(in); 3. 通过消息处理机制将Bitmap传递给UI线程 // 8. 使用handler机制传递消息 handler.sendEmptyMessage(1); 4. UI线程更新ImageView的界面 // 9. 更新UI界面 MySmartImageView.this.setImageBitmap(bitmap);
七、 第一种向服务器获取数据方式:HttpURLConnection
GET方式执行过程:
// 1. 创建一个url对象 参数就是网址 String path = "http://192.168.19.91/web/LoginServlet?username=" + name + "&password=" + pwd + ""; URL url = new URL(path); // 2. 获取HttpURLConnection 链接对象 HttpURLConnection conn = (HttpURLConnection) url .openConnection(); // 3. 设置参数 发送get请求 conn.setRequestMethod("GET"); // 必须大写 // 4. 设置链接网络的超时时间 conn.setConnectTimeout(5000); // 5. 获取服务器返回的状态码 int code = conn.getResponseCode(); if (code == 200) { // 6. 获取服务器给我们返回的数据 InputStream in = conn.getInputStream(); // 7. 处理结果 final String content = StreamUtils.readStream(in); // 8. 更新UI界面 }
POST方式执行过程:
// 1. ☆☆☆ 和get请求方式不同之处一 路径不同 String path = "http://192.168.1.102/web/servlet/LoginServlet"; URL url = new URL(path); // 2. 获取HttpURLConnection 链接对象 HttpURLConnection conn = (HttpURLConnection) url .openConnection(); // 3. 设置参数 发送get请求 conn.setRequestMethod("POST"); // 必须大写 // 4. 设置链接网络的超时时间 conn.setConnectTimeout(5000); // 5. 获取服务器返回的状态码 // ☆☆☆ 和get请求方式不同之处二 路径不同 需要设置2个头信息 String data = "username=" + name + "&password=" + pwd; conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); conn.setRequestProperty("Content-Length", data.length() + ""); // ☆☆☆ 和get请求方式不同之处三 以流的形式写给服务器 conn.setDoOutput(true); conn.getOutputStream().write(data.getBytes()); int code = conn.getResponseCode(); if (code == 200) { // 6. 获取服务器给我们返回的数据 InputStream in = conn.getInputStream(); // 7. 处理结果 final String content = StreamUtils.readStream(in); // 8.更新UI界面 }
两种提交方法的不同之处:
1. 路径不同: get方式:组拼URL的方式 post方式:直接访问URL 2. 头信息不同:post方式需要设置2个头信息 String data = "username=" + name + "&password=" + pwd; conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); conn.setRequestProperty("Content-Length", data.length() + ""); 3. post方式以流的形式写给服务器 conn.setDoOutput(true); conn.getOutputStream().write(data.getBytes());