网络编程原理
### A:Socket套接字概述:
网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字。
### B:Socket原理机制:
通信的两端都有Socket。
网络通信其实就是Socket间的通信。
数据在两个Socket间通过IO传输。
### C:画图演示: Socket原理机制
网络编程(网络编程三要素概述)
A:IP地址:InetAddress: 网络中设备的标识,不易记忆,可用主机名
B:端口号: 用于标识进程的逻辑地址,不同进程的标识
C:传输协议: 通讯的规则常见协议:TCP,UDP
通过网络从服务器获取数据
文本、图片、音频、视频、文件
网络通信
1 网络图片查看器
/**
* 1. 请求网络获取输入流
* 2. 把服务器返回的二进制输入流转成图片对象
* 3. 把图片对象显示在imageview上
*/
public void look(View v) {
System.out.println("哥哥,点击了按钮。。。");
String path = etPath.getText().toString().trim();
if (TextUtils.isEmpty(path)) {
Toast.makeText(this, "亲,网址不能为空 :) ", 0).show();
return;
}
try {
// 1. 写Url网址
URL url = new URL(path);
// 2. 用Url打开连接
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// 3. 设置请求方法和请求参数
// 不设置的话,默认就是get
conn.setRequestMethod("GET");
conn.setConnectTimeout(3000);
// 4. 获取服务器返回的状态码
int code = conn.getResponseCode();
// - 2xxx 请求成功 3xxx重定向 4xxx客户端错误 5xxx服务器错误
if (200 == code) {
// 5. 获取服务器返回的二进制输入流
InputStream is = conn.getInputStream();
// (2)把输入流转成图片对象
Bitmap bmp = BitmapFactory.decodeStream(is);
// (3)给imageview 设置图片
ivPic.setImageBitmap(bmp);
}
} catch (Exception e) {
e.printStackTrace();
}
}
6. 重要,添加网络通信的权限
<uses-permission android:name="android.permission.INTERNET"/>
2 子线程不能修改UI界面
android.os.NetworkOnMainThreadException
网络在主线程异常google为了保证主线程的流畅,不被阻塞,在Android4.0以后网络访问不能再主线程中进行。
解决方案:在子线程中进行网络访问
ANR Application not response应用程序无响应
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
从错误线程调用异常
谁创建,谁修改解决方案:消息机制
3 消息处理机制的原理(重点)
- 如图
编写步骤:
1. 在主线程中初始化Handler对象 2. 在子线程中用Handler发一消息 3. 在handlemessage()方法中更新UI
消息机制(Handler message MessageQueue Looper之间的关系)
任何带有界面的操作系统都运行在一个死循环当中。
当启动应用程序是,Android系统就给应用准备了一个Looper轮询器,
当我们点击按钮时,系统就会发送一个点击按钮的消息到消息队列中,轮询器从消息队列取出消息给handler,在handlemessage方法中处理这个消息。
4 网络源码查看器
/**
* 1. 在子线程中请求网络,获取服务器返回的输入流
* 2. 把服务器返回的输入流转成字符串
* 3. 给textview设置文字(handler)
*/
public void look(View v) {
final String path = etPath.getText().toString().trim();
if (TextUtils.isEmpty(path)) {
Toast.makeText(this, "哥哥,请输入网址呗", 0).show();
return;
}
// 开启线程进行网络通信
new Thread() {
public void run() {
try {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url
.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(3000);
int code = conn.getResponseCode();
if (code == 200) {
InputStream is = conn.getInputStream();
// 把输入流转成字符串
String text = StreamUtils.parserStream2String(is);
// (2)在子线程中发消息
Message msg = Message.obtain();
msg.obj = text;
msg.what = MSG_SUCC;
mHandler.sendMessage(msg);
} else {
// (2)在子线程中发消息
Message msg = Message.obtain();
msg.obj = code;
msg.what = MSG_ERR_CODE;
mHandler.sendMessage(msg);
}
} catch (Exception e) {
e.printStackTrace();
// (2)在子线程中发消息
Message msg = Message.obtain();
msg.what = MSG_ERR;
mHandler.sendMessage(msg);
}
};
}.start();
}
5 消息处理常用的另一个API
runOnUiThread(new Runnable() {
//运行在主线程里
@Override
public void run() {
Toast.makeText(MainActivity.this, text, 0).show();
}
});
阶段总结
6 新闻客户端
- 网络通信获取服务器的新闻数据
- 写一个Url
- 打开连接
- 设置请求方式和参数
- 获取返回码
- 获取服务器返回的输入流
- 添加网络权限
解析Xml文件
- 初始化Xml解析器
- 设置输入流
- 解析数据
单元测试解析Xml文件的方法
用listview显示新闻数据
- 在Xml布局文件中声明listview控件
- 在mainactivity中获取lv
- 给listview设置数据适配器
- 采用内部类的方式实现数据适配器
采用消息机制给listview设置数据适配器
- 在主线程中初始化Handler
- 在子线程中发消息
- 在handlemessage()方法中给listview设置数据适配器
显示图片
使用开源框架
7 使用SmartImageView显示新闻图片
- www.github.com 下载开源框架
- 阅读开源框架的介绍 readme.md 或者sample示例代码
- 复制代码到我们的工程中
- 在item.xml中使用smartimageview替换imageview,在代码中使用smartimageview替换 imageview,调用setImageUrl();