Android - 获取网络数据,Bitmap,ANR,主线程模型,消息机制,UserAgent,乱码问题,xml生成与解析,JSON解析,MVC,SmartImageView
Android - 获取网络数据,Bitmap,ANR,主线程模型,消息机制,UserAgent,乱码问题,xml生成与解析,JSON解析,MVC,SmartImageView
转载请注明出处:https://blog.csdn.net/mythmayor/article/details/72869155
1.获取网络数据的步骤
添加权限<uses-permission android:name="android.permission.INTERNET"/>
// 1.得到图片的url路径
URL url = new URL(path);
// 2.通过路径打开一个http的连接,并设置请求参数
HttpURLConnection conn = (HttpURLConnection) url.openConnection();// http
// 3.得到响应码,判断与服务器连接是否正常
int code = conn.getResponseCode(); // 200 OK 404 资源没找到 503服务器内部错误
if (code == 200) {
// 4.得到服务器返回的数据流
InputStream is = conn.getInputStream();
}
2.将流转换为Bitmap
Bitmap bitmap = BitmapFactory.decodeStream(is);
iv.setImageBitmap(bitmap);
3.Http请求的小细节
//初始化时的设置
conn.setRequestMethod("GET");//设置请求参数为get, 默认的请求方式就是get,此处区分大小写
conn.setConnectTimeout(5000);//设置请求服务器的超时时间.
//服务器返回数据属性的获取
String type = conn.getContentType();//获取返回数据的类型
int length = conn.getContentLength();//获取返回数据的长度
//User-Agent
当前浏览器的类型,服务器可以根据浏览器的类型的不同,返回不同的页面
4.ANR
Application Not Response 应用程序无响应,在主线程里执行了耗时操作或阻塞式操作
一个应用的主线程(又叫UI线程),负责的事情较多,如消息的监听、界面的更新。如果主线程被阻塞,会让整个应用卡住。如果阻塞的时间过长,会导致ANR异常
网络访问就是一个阻塞式的操作
结论:不能在主线程里执行耗时操作或阻塞式操作
5.主线程模型
- 只有主线程可以修改UI
- 子线程修改UI,会有UI数据同步的问题,为了避免过于复杂的多线程同步操作,google设计为UI中的数据只能在主线程修改。
6.Android下的消息机制
- 子线程不可以修改UI
- 只有主线程才可以修改UI
- 如果子线程想修改UI,必须利用消息机制处理
7.Message、Handler、MessageQueue、Looper
Message:消息,其中包含了子线程想让主线程处理的数据,由Handler从子线程发送到主线程的MessageQueue中,终由Looper从MessageQueue中取出交给Handler处理。
Handler(消息处理器, 可以发送消息给主线程的消息队列.):处理者,负责Message的发送及处理。使用Handler时,需要实现handleMessage(Message msg)方法来对特定的Message进行处理。
MessageQueue(消息队列,主线程里面的一个消息队列.):消息队列,用来存放Handler发送过来的消息,并按照FIFO(先进先出)规则执行。当然,存放Message并非实际意义的保存,而是将Message以链表的方式串联起来的,等待Looper的取出。
Looper(轮询器,检查消息队列里面是否有消息.—> HandleMessage();):轮询器,不断地从MessageQueue中抽取Message交给Handler执行。
public class MainActivity extends Activity { private TextView tv; //1.定义一个消息处理器(秘书) private Handler handler = new Handler(){ //3.秘书处理消息的方法 @Override public void handleMessage(Message msg) { String text = (String) msg.obj; tv.setText(text); super.handleMessage(msg); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv = (TextView) findViewById(R.id.tv); new Thread(){ public void run() { for(int i = 0;i<10;i++){ //需求:子线程里面想去更新ui //tv.setText("嘎嘎,哈哈哈,呱呱呱----"+i); //2.利用秘书给老板发消息,让主线程更新ui Message msg = new Message(); msg.obj ="嘎嘎,哈哈哈,呱呱呱----"+i; handler.sendMessage(msg); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }; }.start(); } }
8.Message
Message的创建方式
//利用obtain()方法创建,系统会维护一个消息池,使用的时候从池里取出更节省内存 Message msg = Message.obtain();
Message的两个重要的属性
Message msg = Message.obtain(); msg.what = SUCCESS; //用来区分是哪个消息 msg.obj = bitmap; //用来携带要传递的数据
9.将流转化为字符串
public static String readStream(InputStream is) throws Exception{
//ByteArrayOutputStream类是在创建它的实例时,程序内部创建一个byte型数组的缓冲区,
//缓冲区会随着数据的不断写入而自动增长。可使用 toByteArray()和 toString()获取数据
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = -1;
while((len = is.read(buffer))!=-1){
baos.write(buffer, 0, len);
}
is.close();
String temp = baos.toString();
if(temp.contains("charset=utf-8")){
return temp;
}else if(temp.contains("gb2312")){
return baos.toString("gb2312");
}return null;
}
10.ScrollView
- 可实现控件在超出屏幕范围的情况下滚动显示
- 支持横向滚动的为HorizontalScrollView
11.UserAgent
- 服务器可以利用UserAgent来区分访问的设备
可以通过手动的指定User-Agent来修改该属性
conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET4.0C; InfoPath.2"); 利用抓包工具获取User-Agent及其参数,通过设置请求属性可以在手机上访问电脑的网站。
12.乱码问题产生的原因
- 服务器与客户端使用的码表不一致
如果服务器的数据不是UTF-8,如何转换
ByteArrayOutputStream baos = new ByteArrayOutputStream(); ... ... baos.toString("gb2312");
常见的乱码
* 黑色菱形里面带问号 gbk的数据 以utf-8方式显示.
* 只要保证服务器端和客户端的编码同一就可以解决乱码问题.
13.xml的生成与解析
XmlSerializer序列化:
//1.初始化
XmlSerializer serializer = Xml.newSerializer(); //创建一个Serializer解析器
serializer.setOutput(out,"utf-8"); //设置输出流及输出的编码为UTF-8
//2.头
serializer.startDocument("UTF-8",true); //输出开始文档<?xml version="1.0" encoding="UTF-8" standalone="true"?>
//3.内容,根据需求写出节点结构
serializer.startTag(null,"tagname"); //输出<tagname>
serializer.attribute(null,"name","value"); //输出<tagname name="value">
serializer.text("value"); //输出两个标签中间的值
serializer.endTag(null,"tagname");//结束标签</tagname>
//4.结束
serializer.endDocument();//结束文档
XmlPullParser解析:
Pull解析的特点:需要手动获取事件
//1.初始化
XmlPullParser parser = Xml.newPullParser(); //创建一个PULL解析器
parser.setInput(in,"UTF-8"); //读取的编码为UTF-8
//2.获取第一个事件
int even t = parser.getEventType(); //开始解析时调用
//3.循环判断事件,直到达到文档结束节点,根据节点类型进行不同操作
while(event!=XmlPullParser.END_DOCUMENT){
//parser.getName(); //获得当前指向的标签的标签名
//parser.getAttributeValue(0); //获得当前指向的标签的第1个属性值
//parser.nextText(); //获得当前标签的标签值
switch(event){
case XmlPullParser.START_DOCUMENT: //如果指向的是START_DOCUMENT
//处理
break;
case XmlPullParser.START_TAG: //如果指向的是START_TAG
//处理
break;
case XmlPullParser.END_TAG: //如果指向的是END_TAG
//处理
break;
}
event = parser.next(); //指向下一个标签
}
14.JSON数据格式
天气预报网址 http://wthrcdn.etouch.cn/weather_mini?city=%E6%B7%B1%E5%9C%B3
{
"desc": "OK",
"status": 1000,
"data": {
"wendu": "18",
"ganmao": "天气较凉,较易发生感冒,请适当增加衣服。体质较弱的朋友尤其应该注意防护。",
"forecast": [
{
"fengxiang": "无持续风向",
"fengli": "微风级",
"high": "高温 19℃",
"type": "多云",
"low": "低温 12℃",
"date": "13日星期三"
},
{
"fengxiang": "无持续风向",
"fengli": "微风级",
"high": "高温 19℃",
"type": "阴",
"low": "低温 14℃",
"date": "14日星期四"
}
],
"yesterday": {
"fl": "微风",
"fx": "无持续风向",
"high": "高温 18℃",
"type": "多云",
"low": "低温 14℃",
"date": "12日星期二"
},
"aqi": "48",
"city": "深圳"
}
}
- JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。
- JSON 语法规则
- 数据在键值对中
- 数据由逗号分隔
- 花括号保存对象
- 方括号保存数组
- JSON 值可以是
- 数字(整数或浮点数)
- 字符串(在双引号中)
- 逻辑值(true 或 false)
- 数组(在方括号中)
- 对象(在花括号中)
- null
- JSON数据有两种结构
- 对象:表示为“{}”括起来的内容,数据结构为 {key:value, key:value, …}
- 数组:表示为“[]”括起来的内容,数据结构为 [“java”, “javascript”, “vb”, …]
15.JSON数据格式的解析
1. JSONObject
2. JSONArray
16.当URL中有中文时,要进行URL编码
//参数为 (要编码的字符串,码表)
URLEncoder.encode(cityname,"utf-8");
17.采用MVC设计模式如何开发一个模块
- 编写数据操作类NewsInfoService
- 定义要使用到的业务实体类NewsItem
- 通过网络或其他途径获取数据并返回
18.控制View显示和隐藏的方法
//View.VISIBLE 显示
//View.INVISIBLE 隐藏
view.setVisibility(View.VISIBLE);
19.正在加载进度的实现原理
- 设置进度条显示
- 开启子线程获取数据
- 获取数据后隐藏进度条
- 使用Handler更新UI界面
20.TextView
只显示一行
android:singleLine="true"
设置文字颜色
android:textColor="#BB000000"
设置文字大小
android:textSize="18sp"
设置显示几行
android:lines="2"
21.常用的开源代码的网站
22.在布局中使用自定义控件
//这里要写全类名
<com.mythmayor.smartimageview.ui.SmartImageView
android:id="@+id/iv_item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher" />
23.新闻客户端代码流程
创建工程
在activity_main.xml中定义控件
在MainActivity.java中找到关心的控件
创建service包,创建NewsInfoService类
创建domain包,创建NewsItem类
在values 文件夹下创建config.xml文件
回到NewsInfoService类中写代码
创建test包,创建TestNewsInfoService类,编写代码
回到MainActivity类中编写代码
在layout中创建item.xml
处理图片,用SmartImageView
复制com.loopj.android.image包到项目中
将ImageView改为全包名的SmartImageView
回到MainActivity类找到控件,编写代码
24总结
- 从服务器获取数据
- 通过HttpURLConnection向服务器请求数据API的使用
- 主线程模型——访问网络要在子线程中进行
- Android下的消息机制——只有主线程可以更新UI,子线程要想更新UI,需要使用Handler,将更新UI的数据发送给主线程去处理
- 常用数据格式XML与JSON的解析
- 耗时操作的处理——子线程处理+进度条
- 乱码产生的原因、如何处理
- 当URL中有中文时,要进行URL编码
- 消息机制:Message、Handler、MessageQueue、Looper的理解
- Message的创建方式、Message的两个重要属性
- 图片的处理
- 利用开源框架加载显示图片
- SmartImageView的大致实现原理
- 小知识点
- ANR
- User-Agent
- 将流转化为Bitmap、将流转化为字符串
- ScrollView的使用
- 控制view的显示和隐藏
更多推荐
所有评论(0)