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 ...
 
随机推荐
- linux 压力测试工具 webbench
			
webbench最多可以模拟3万个并发连接去测试网站的负载能力,个人感觉要比Apache自带的ab压力测试工具好,安装使用也特别方便. 1.适用系统:Linux 2.编译安装: 1. wget htt ...
 - laravel 中的Gates,以及修改模型
			
Gates 是一个用于判断用户是否有权进行某项操作的闭包,通常使用Gate 门面定义在 App\Providers\AuthServiceProvider类中.Gates 总是接收用户实例作为第一个参 ...
 - C++ 中 dynamic_cast 浅析
			
简述:dynamic_cast 操作符,将基类的指针或引用安全的转换为派生类的指针或引用.主要讲解,dynamic_cast操作符的原理.使用方式.编译器设置.返回值等相关知识. dynamic_ca ...
 - 编写高质量代码改善C#程序的157个建议——建议50:在Dispose模式中应区别对待托管资源和非托管资源
			
建议50:在Dispose模式中应区别对待托管资源和非托管资源 真正资源释放代码的那个虚方法是带一个bool参数的,带这个参数,是因为我们在资源释放时要区别对待托管资源和非托管资源. 提供给调用者调用 ...
 - c# .NET开发邮件发送功能的全面教程(含邮件组件源码)
			
http://www.cnblogs.com/heyuquan/p/net-batch-mail-send-async.html
 - C#调用OCX控件的常用方法[转]
			
小伙伴们在使用ICP提供的各种能力进行集成开发时常常会遇到一些技术上的困扰,例如ICP中很多接口是通过OCX控件的方式提供的,如何调用这些接口,就成了一个不大不小的问题,毕竟开发指南上可没这些内容啊~ ...
 - dubbo 安装部署Windows
			
1 安装zookeeper 2 安装dubbo 1 下载源码 https://github.com/alibaba/dubbo 2 编译 mvn clean package install -D ...
 - PHP删除目录
			
function delDir($directory) { if(file_exists($directory)) { $dir_handle = @opendir($directory); if($ ...
 - 「POJ 2699」The Maximum Number of Strong Kings
			
题目链接 戳我 \(Describe\) 一场联赛可以表示成一个完全图,点表示参赛选手,任意两点u, v之间有且仅有一条有向边\((u, v)\)或\((v, u)\),表示\(u\)打败\(v\)或 ...
 - 十三、Node.js-fs模块(上)
			
Node.js内置的fs模块就是文件系统模块,负责读写文件以及对文件进行相关操作. 下面直接可参考下面的代码进行fs模块里面基本方法的学习: /** * Created by Administrato ...