Android HttpURLConnection的使用+Handler的原理及典型应用
1.介绍

总结:HttpURLConnection用来发送和接收数据。
2.ANR异常报错
(1)ANR(Application not response) 应用无响应, 主线程(UI线程)
(2)如果在主线程中进行耗时操作(比如连接网络、拷贝大量的数据),都会报ANR异常
(3)避免ANR报错,可以把耗时操作放到子线程中,自己再创建一个线程。
(4)android 4.0之后,Google公司要求连接网络不能在主线程中进行访问。
总结:主线程中不要执行耗时操作(比如连接网络、拷贝大量的数据、Thread.sleep()),应在子线程中操作。
UI的更新应该在主线程中执行。

3.handler原理
handler是更新UI界面的机制,也是消息处理的机制,我们可以发送消息,也可以处理消息
handler实现主线程与子线程之间的交互。

handler使用步骤:
(1)在主线程定义一个handler
(2)重写handler的handleMessage()方法
(3)在子线程中发送需要设置的消息内容
(4)handler中进行接收消息,并设置ui
注意:
<1>hander的作用是发送并处理消息
<2>子线程最好不要更新ui组件
<3>Looper的作用是监视消息队列,若消息队列中有消息,则取出消息并将消息交给hander处理。
Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
//在主线程里更新ui
String strTemp= (String) msg.obj;
tv_websiteShow.setText(strTemp);
}
};
4.网址测试时,网址最好复制网上的直接网址,不要自己手动输入。
5.使用技巧(避免出错):
<1>无论哪个版本的手机,只要涉及耗时操作(比如连接网络,拷贝大量的数据等),则需要开辟一个子线程
<2>获取数据后想要更新ui,就使用Handler就可以了
6.利用手机的缓存功能
//缓存图片(节省流量)
FileOutputStream fos=new FileOutputStream(file); //创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
int len=-1;
byte[] buffer=new byte[1024]; //1kb
while ((len=in.read(buffer))!=-1){ //从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。
fos.write(buffer,0,len);
}
fos.close();
in.close();
7.java代码
<1>MainActivity.class
注意:更新ui组件有两种方法:(1)利用handler发送消息,修改ui组件(必须掌握,万能) (2)调用runOnUiThread()方法,实现在子线程中更新ui的效果。(有的情况下不能使用)
package com.example.lucky.test54wanzhichakan; import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast; import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL; public class MainActivity extends AppCompatActivity {
protected static final int REQUESTSUCCESS=0;
protected static final int REQUESTNOTFOUND=1;
protected static final int REQUESTEXCEPTION=2;
protected static final int REQUESTIMAGESUCCESS=3;
Button bt_showText;
Button bt_showImage;
TextView tv_websiteShow;
EditText et_website;
ImageView iv_pic1;
@SuppressLint("HandlerLeak")
Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case REQUESTSUCCESS: //请求成功
//在主线程里更新ui
String strTemp= (String) msg.obj;
tv_websiteShow.setText(strTemp);
break;
case REQUESTNOTFOUND:
Toast.makeText(MainActivity.this,"请求未响应",Toast.LENGTH_LONG).show();
break;
case REQUESTEXCEPTION:
Toast.makeText(MainActivity.this,"服务器正忙,稍后再试",Toast.LENGTH_LONG).show();
break;
case REQUESTIMAGESUCCESS:
Bitmap bitmap= (Bitmap) msg.obj;
iv_pic1.setImageBitmap(bitmap);
break;
} }
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bt_showText=findViewById(R.id.bt_showText);
bt_showImage=findViewById(R.id.bt_showImage);
tv_websiteShow=findViewById(R.id.tv_websiteShow);
et_website=findViewById(R.id.et_website);
iv_pic1=findViewById(R.id.iv_pic1);
bt_showText.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//开启一个子线程
new Thread(){
@Override
public void run() {
String website=et_website.getText().toString().trim(); //trim()方法用于去除字符串开头和结尾的空白
try {
//1.创建URL,指定我们要访问的网址
URL url=new URL(website);
//2.获取HttpURLConnection对象,用于发送或接收数据
HttpURLConnection conn= (HttpURLConnection) url.openConnection();
System.out.println("-------------------flaglucky");
//3.设置请求格式为get
conn.setRequestMethod("GET"); //注意get要求大写,默认为get请求
//4.设置请求的超时时间
conn.setConnectTimeout(5000);
//5.获取服务器返回的状态码
int code=conn.getResponseCode();
System.out.println("--------------"+code);
//如果code==200说明请求成功
if(code==200){
System.out.println("-------------------flagif");
//6.获取服务器返回的数据(以流的形式返回)
InputStream in=conn.getInputStream();
//7.用定义的工具类将InputStream类型的数据转换为String
String contentStr=StreamTools.readStream(in); //8.1创建message对象
Message msg=new Message();
msg.obj=contentStr; //设置消息内容
msg.what=REQUESTSUCCESS; //设置消息代号
handler.sendMessage(msg); //利用handler告诉系统需要更新ui组件,则handlermessage方法就会执行
}else {
Message msg=new Message();
msg.what=REQUESTNOTFOUND;
handler.sendMessage(msg);
}
} catch (Exception e) {
e.printStackTrace();
Message msg=new Message();
msg.what=REQUESTEXCEPTION;
handler.sendMessage(msg);
}
}
}.start(); }
});
bt_showImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//开启一个子线程
new Thread(){
@Override
public void run() {
try {
File file=new File(getCacheDir(),"test.png");
//判断图片是否已经缓存
if(file.exists()&&file.length()>0){
System.out.println("使用缓存图片");
//7.利用BitmapFactory将InputStream类型的数据转换为Bitmap
Bitmap bitmap=BitmapFactory.decodeFile(file.getAbsolutePath()); //8.1创建message对象
Message msg=new Message();
msg.obj=bitmap; //设置消息内容
msg.what=REQUESTIMAGESUCCESS; //设置消息代号
handler.sendMessage(msg); //利用handler告诉系统需要更新ui组件,则handlermessage方法就会执行
}else {
System.out.println("第一次连接网络");
String picPath=et_website.getText().toString().trim();
//1.创建URL,指定我们要访问的网址
URL url=new URL(picPath);
//2.获取HttpURLConnection对象,用于发送或接收数据
HttpURLConnection conn= (HttpURLConnection) url.openConnection();
System.out.println("-------------------flaglucky");
//3.设置请求格式为get
conn.setRequestMethod("GET"); //注意get要求大写,默认为get请求
//4.设置请求的超时时间
conn.setConnectTimeout(5000);
//5.获取服务器返回的状态码
int code=conn.getResponseCode();
System.out.println("--------------"+code);
//如果code==200说明请求成功
if(code==200){
System.out.println("-------------------flagif");
//6.获取服务器返回的数据(以流的形式返回)
InputStream in=conn.getInputStream();
//缓存图片(节省流量)
FileOutputStream fos=new FileOutputStream(file); //创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
int len=-1;
byte[] buffer=new byte[1024]; //1kb
while ((len=in.read(buffer))!=-1){ //从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。
fos.write(buffer,0,len);
}
fos.close();
in.close();
//7.利用BitmapFactory将InputStream类型的数据转换为Bitmap
final Bitmap bitmap=BitmapFactory.decodeFile(file.getAbsolutePath()); // //8.1创建message对象
// Message msg=new Message();
// msg.obj=bitmap; //设置消息内容
// msg.what=REQUESTIMAGESUCCESS; //设置消息代号
// handler.sendMessage(msg); //利用handler告诉系统需要更新ui组件,则handlermessage方法就会执行 //使用runOnUiThread()方法相当于在主线程中执行run()方法
runOnUiThread(new Runnable() {
@Override
public void run() {
iv_pic1.setImageBitmap(bitmap);
}
});
}else {
Message msg=new Message();
msg.what=REQUESTNOTFOUND;
handler.sendMessage(msg);
}
}
} catch (Exception e) {
e.printStackTrace();
Message msg=new Message();
msg.what=REQUESTEXCEPTION;
handler.sendMessage(msg);
}
}
}.start();
}
});
}
}
<2>工具类
package com.example.lucky.test54wanzhichakan; import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream; //流操作的工具类
public class StreamTools {
//把一个inputStream转换为String
public static String readStream(InputStream in) throws Exception {
//定义一个内存输出流
ByteArrayOutputStream baos=new ByteArrayOutputStream();
int len=-1;
byte[] buffer=new byte[1024];//大小为1kb
while ((len=in.read(buffer))!=-1){ //read()方法:从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中,若到文件结尾返回-1
baos.write(buffer,0,len);
}
in.close(); //关闭流
String content=new String(baos.toByteArray());
return content;
}
}
7.效果图

Android HttpURLConnection的使用+Handler的原理及典型应用的更多相关文章
- android handler工作原理
android handler工作原理 作用 便于在子线程中更新主UI线程中的控件 这里涉及到了UI主线程和子线程 UI主线程 它很特别.通常我们会认为UI主线程将页面绘制完成,就结束了.但是它没有. ...
- android高级---->Handler的原理
andriod提供了Handler来满足线程间的通信,上次在更新UI的时候也提到过Handler的使用,关于Handler的基本使用,参见博客(android基础---->子线程更新UI).今天 ...
- android基础---->DiskLruCache的使用及原理
DiskLruCache是谷歌推荐的用来实现硬盘缓存的类,今天我们开始对于DiskLruCache的学习.DiskLruCache的测试代码:DiskLruCache的测试代码下载.关于FidkLru ...
- Android HttpURLConnection源代码分析
Android HttpURLConnection源代码分析 之前写过HttpURLConnection与HttpClient的差别及选择.后来又分析了Volley的源代码. 近期又遇到了问题,想在V ...
- Android之——AsyncTask和Handler对照
转载请注明出处:http://blog.csdn.net/l1028386804/article/details/46952835 AsyncTask和Handler对照 1 ) AsyncTask实 ...
- 知乎1578赞:Android 中为什么需要 Handler?
要理解 Handler,就得先理解 Android 的 Message 机制. 这里以用户滑动微信朋友圈为例,讲解一下 Android 的 Message 机制是怎么运行的,Message 机制中的各 ...
- Android源码解析——Handler、Looper与MessageQueue
本文的目的是来分析下 Android 系统中以 Handler.Looper.MessageQueue 组成的异步消息处理机制,通过源码来了解整个消息处理流程的走向以及相关三者之间的关系 需要先了解以 ...
- Android开发 之 理解Handler、Looper、MessageQueue、Thread关系
本文转自博客:http://blog.csdn.net/he90227/article/details/43567073 一. 图解与概述 首先Android中 的每一个线程都会对应一个Message ...
- 【Android 开发】: Android 消息处理机制之一: Handler 与 Message
最近几讲内容,我们学习了Android中关于多线程的一些知识,上一讲我们讲解了异步任务 AsyncTask 的操作,Android中还提供了其他的线程操作,如Handler Message Messa ...
随机推荐
- Android输入法部分遮挡UI的问题(与EditText框相切)
首先,我们来看看遇到问题的图片 遇到的问题是,当点击输入框之后,输入法会切到红线的位置,理想状态应该是在绿线位置 那么,是什么原因造成的呢? 问题其实很简单,是因为drawableleft图片比该输入 ...
- docker问题:docker端口映射错误
1 docker端口映射错误 1.1 问题描述 利用docker启动nginx容器的时候报错: 1.2 解决办法 一次执行下面的命令就可以解决 pkill docker iptables -t nat ...
- 819. Most Common Word 统计高频词(暂未被禁止)
[抄题]: Given a paragraph and a list of banned words, return the most frequent word that is not in the ...
- Docker学习笔记_使用Dockerfile创建flask的一个镜像
一.实验环境 1.宿主机OS:Win10 64位 2 .虚拟机OS:Ubuntu18.04 64位 虚拟机名称:Ubuntu18VM1 虚拟机IP:192.168.8.25 3.账号:doc ...
- MySQL - pt-query-digest的下载与使用
对于脚本文件,是可以执行的,我们不用安装.所以,但是这个脚本文件没有执行的权限,所以,我们首先赋予这个脚本文件的可执行的权限. 再次查看文件的信息后. 已经有了执行的权限了. 运行脚本的时候,可要注意 ...
- Solidity payable 方法表现
pragma solidity ^; contract Person { string public name; uint age; uint private weight; string inter ...
- Codeforces 427E Police Patrol
找中间的数,然后从两头取. #include<stdio.h> ; int pos[MAX]; int main() { int n,m,tmp; int i; int pol; long ...
- Linux、Windows中的相对路径和绝对路径
获取系统的分隔符的方式:System.getProperty("file.separator") Windows为 \ Linux为/ Windows绝对路径: 以盘符开始 ...
- css总结16:HTML5 多媒体音频(Audio)视频(video )
1 显示嵌入网页中的 MP3 文件: <embed height="50" width="100" src="horse.mp3"&g ...
- aspx 与 ashx cs
1. aspx 与 ashx 我们知道 aspx :继承自 System.Web.UI.Page 然而Page:IHttpHandler public class Page : TemplateCon ...