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

  • 相关阅读:
    Linux 分区与挂载
    Linux Shell 编程总结
    Java AtomicIntegerFieldUpdater 抽象类
    Java 内部类加载顺序
    Java AtomicIntegerArray 类
    Java AtomicInteger 类
    Java ReentrantLock 类
    Java Runnable 接口
    Java Supplier 接口
    Java Consumer 接口
  • 原文地址:https://www.cnblogs.com/luckyplj/p/10628852.html
Copyright © 2020-2023  润新知