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 ...
随机推荐
- java基础之JDBC三:简单工具类的提取及应用
简单工具类: public class JDBCSimpleUtils { /** * 私有构造方法 */ private JDBCSimpleUtils() { } /** * 驱动 */ publ ...
- 使用DevStack安装openstack(单机环境)
DevStack是一系列可扩展的脚本,用于根据git master的最新版本快速启动完整的OpenStack环境.它以交互方式用作开发环境,并作为OpenStack项目功能测试的基础. 参考源码. 警 ...
- python子进程模块subprocess详解与应用实例 之一
subprocess--子进程管理器 一.subprocess 模块简介 subprocess最早是在2.4版本中引入的. subprocess模块用来生成子进程,并可以通过管道连接它们的输入/输出/ ...
- codeforce 462DIV2 C题
题意 给出一个只含有1和2的序列,有n个元素,可以选择一段区间进行翻转操作,求再反转后的最大非递减子序列的长度 分析 太菜了只想出了N^2的做法.序列只有1和2,那么每个非递减子序列都会有一个分界点, ...
- mfs教程(一)
对于mfs文件系统也用了半年了,确实不错,最近又翻译了作者的三篇文章,再此一同发上,希望对大家有所帮助.不足之处还请指出,以便完善,谢谢! 感谢网友nonamexz做了精美的pdf文档 MFS文件系统 ...
- 配置springboot在访问404时自定义返回结果以及统一异常处理
在搭建项目框架的时候用的是springboot,想统一处理异常,但是发现404的错误总是捕捉不到,总是返回的是springBoot自带的错误结果信息. 如下是springBoot自带的错误结果信息: ...
- 线程dump
当应用程序运行变慢或者发生故障时,可能通过分析java的Thread Dumps得到分析他们得到阻塞和存在瓶颈的线程. 线程堆栈是虚拟机中线程(包括锁)状态的一个瞬间状态的快照,即系统在某一个时刻所有 ...
- 多个if和一个ifelse的区别
一个程序的要求如下,输入一个学生的数学成绩,如果大于等于60,那么就输出good,如果小于60那么输出not good int a scanf_s("%d",&a) if( ...
- c语言学习笔记 if语句的条件判断
可能经常会看到错误的if语句示范,比如这样的: if(a=6) { printf("hello"); } if语句块执行的条件是if条件的运算结果不是0则执行if语句块. a=6这 ...
- xgboost 调参 !
https://jessesw.com/XG-Boost/ http://blog.csdn.net/u010414589/article/details/51153310