005 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.效果图

posted @   雨后观山色  阅读(463)  评论(0编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示