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.主线程模型

  1. 只有主线程可以修改UI
  2. 子线程修改UI,会有UI数据同步的问题,为了避免过于复杂的多线程同步操作,google设计为UI中的数据只能在主线程修改。

6.Android下的消息机制

  1. 子线程不可以修改UI
  2. 只有主线程才可以修改UI
  3. 如果子线程想修改UI,必须利用消息机制处理
    搜狗截图20160519171620.jpg

7.Message、Handler、MessageQueue、Looper

  1. Message:消息,其中包含了子线程想让主线程处理的数据,由Handler从子线程发送到主线程的MessageQueue中,终由Looper从MessageQueue中取出交给Handler处理。

  2. Handler(消息处理器, 可以发送消息给主线程的消息队列.):处理者,负责Message的发送及处理。使用Handler时,需要实现handleMessage(Message msg)方法来对特定的Message进行处理。

  3. MessageQueue(消息队列,主线程里面的一个消息队列.):消息队列,用来存放Handler发送过来的消息,并按照FIFO(先进先出)规则执行。当然,存放Message并非实际意义的保存,而是将Message以链表的方式串联起来的,等待Looper的取出。

  4. 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

  1. Message的创建方式

    //利用obtain()方法创建,系统会维护一个消息池,使用的时候从池里取出更节省内存
    Message msg = Message.obtain();
    
  2. 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

  1. 可实现控件在超出屏幕范围的情况下滚动显示
  2. 支持横向滚动的为HorizontalScrollView

11.UserAgent

  1. 服务器可以利用UserAgent来区分访问的设备
  2. 可以通过手动的指定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.乱码问题产生的原因

  1. 服务器与客户端使用的码表不一致
  2. 如果服务器的数据不是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": "深圳"
    }
}
  1. JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。
  2. JSON 语法规则
    • 数据在键值对中
    • 数据由逗号分隔
    • 花括号保存对象
    • 方括号保存数组
  3. JSON 值可以是
    • 数字(整数或浮点数)
    • 字符串(在双引号中)
    • 逻辑值(true 或 false)
    • 数组(在方括号中)
    • 对象(在花括号中)
    • null
  4. JSON数据有两种结构
    • 对象:表示为“{}”括起来的内容,数据结构为 {key:value, key:value, …}
    • 数组:表示为“[]”括起来的内容,数据结构为 [“java”, “javascript”, “vb”, …]

15.JSON数据格式的解析

1. JSONObject  

001.jpg
2. JSONArray
002.jpg

16.当URL中有中文时,要进行URL编码

//参数为 (要编码的字符串,码表)
URLEncoder.encode(cityname,"utf-8");

17.采用MVC设计模式如何开发一个模块

  1. 编写数据操作类NewsInfoService
  2. 定义要使用到的业务实体类NewsItem
  3. 通过网络或其他途径获取数据并返回

18.控制View显示和隐藏的方法

//View.VISIBLE 显示
//View.INVISIBLE 隐藏
view.setVisibility(View.VISIBLE);

19.正在加载进度的实现原理

  1. 设置进度条显示
  2. 开启子线程获取数据
  3. 获取数据后隐藏进度条
  4. 使用Handler更新UI界面

20.TextView

  1. 只显示一行

    android:singleLine="true"
    
  2. 设置文字颜色

    android:textColor="#BB000000"
    
  3. 设置文字大小

    android:textSize="18sp"
    
  4. 设置显示几行

    android:lines="2"
    

21.常用的开源代码的网站

http://www.github.com

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总结

  1. 从服务器获取数据
    1. 通过HttpURLConnection向服务器请求数据API的使用
    2. 主线程模型——访问网络要在子线程中进行
    3. Android下的消息机制——只有主线程可以更新UI,子线程要想更新UI,需要使用Handler,将更新UI的数据发送给主线程去处理
    4. 常用数据格式XML与JSON的解析
    5. 耗时操作的处理——子线程处理+进度条
    6. 乱码产生的原因、如何处理
    7. 当URL中有中文时,要进行URL编码
  2. 消息机制:Message、Handler、MessageQueue、Looper的理解
    1. Message的创建方式、Message的两个重要属性
  3. 图片的处理
    1. 利用开源框架加载显示图片
    2. SmartImageView的大致实现原理
  4. 小知识点
    1. ANR
    2. User-Agent
    3. 将流转化为Bitmap、将流转化为字符串
    4. ScrollView的使用
    5. 控制view的显示和隐藏
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.StaggeredGridLayoutManager; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.TextView; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import org.json.JSONArray; import org.json.JSONObject; import org.xml.sax.InputSource; import org.xml.sax.XMLReader; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserFactory; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.StringReader; import java.lang.reflect.Type; import java.net.HttpURLConnection; import java.net.URL; import java.util.ArrayList; import java.util.List; import javax.xml.parsers.SAXParserFactory; import okhttp3.Call; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; public class MainActivity extends AppCompatActivity implements View.OnClickListener { RecyclerView recyclerView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button sendRequest = (Button) findViewById(R.id.send_request); sendRequest.setOnClickListener(this); recyclerView = (RecyclerView) findViewById(R.id.recycler_view); StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL); recyclerView.setLayoutManager(layoutManager); } @Override public void onClick(View v) { if (v.getId() == R.id.send_request) { // sendRequestWithHttpURLConnection(); sendRequestWithOkHttp(); /* String url = "http://cache.video.iqiyi.com/jp/avlist/202861101/1/?callback=json

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值