AsyncTask结合HttpHrlConnection的例子

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_28963915/article/details/52118831

最近打算换工作了,看了一下面试题 发现我原来知识是如此的匮乏 吓得我赶紧去写个Demo冷静下,异步和网络请求在Android开发中是最基本的东西,在Android6.0中抛弃了Httpclient 我们只能使用Httpurlconnection了
在上一篇博客中我们看了AsyncTask 我们知道 它是采用handler+线程池的方式来实现的异步请求,自己再写一个http网络请求工具类就行了
开搞:
先看http请求

import android.util.Log;

import org.json.JSONException;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Map;

/**
 * Http请求的工具类
 * 
 * @author zhy
 * 
 */
public class HttpUtils{
    private static final int TIMEOUT_IN_MILLIONS = 5000;
    public interface CallBack{
        void onRequestComplete(byte[] arr);
    }


    /**
     * 异步的Get请求
     * 
     * @param urlStr
     * @param callBack
     */
    public static void doGetAsyn(final String urlStr, final CallBack callBack){
        new Thread(){
            public void run(){
                try{
                    byte []arr = doGet(urlStr);
                    if (callBack != null){
                        callBack.onRequestComplete(arr);
                    }
                } catch (Exception e){
                    e.printStackTrace();
                }
            }
        }.start();
    }

    /**
     * 异步的Post请求
     * @param urlStr
     * @param params
     * @param callBack
     * @throws Exception
     */
    public static void doPostAsyn(final String urlStr, final Map<String, String> params,
            final CallBack callBack) throws Exception{
        new Thread(){
            public void run(){
                try{
                    byte []arr = doPost(urlStr, params);
                    if (callBack != null){
                        callBack.onRequestComplete(arr);
                    }
                } catch (Exception e){
                    e.printStackTrace();
                }
            }
        }.start();
    }

    /**
     * Get请求,获得返回数据
     * 
     * @param urlStr
     * @return
     * @throws Exception
     */
    public static byte[] doGet(String urlStr){
        URL url = null;
        HttpURLConnection conn = null;
        InputStream is = null;
        ByteArrayOutputStream baos = null;
        int len =0;
        byte[] buf = new byte[1024];
        try{
            url = new URL(urlStr);
            conn = (HttpURLConnection) url.openConnection();
            conn.setReadTimeout(TIMEOUT_IN_MILLIONS);
            conn.setConnectTimeout(TIMEOUT_IN_MILLIONS);
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(10000);//连接超时 单位毫秒
            conn.setReadTimeout(2000);//读取超时 单位毫秒
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");//维持长链接
            conn.setRequestProperty("Charset", "UTF-8");
            if (conn.getResponseCode() == 200){
                is = conn.getInputStream();
                baos = new ByteArrayOutputStream();
                while ((len = is.read(buf)) != -1){
                    baos.write(buf, 0, len);
                }
                baos.flush();
                return baos.toByteArray();
            } else{
                Log.i("iiiiiiiii", "请求失败" + conn.getResponseCode());
            }
        } catch (Exception e){
            e.printStackTrace();
        }finally{
            try{
                if (is != null)
                    is.close();
                if (baos != null)
                    baos.close();
            } catch (IOException e){
                e.printStackTrace();
            }
            conn.disconnect();
        }
        return null ;
    }

    /**
     * 向指定 URL 发送POST方法的请求
     * 
     * @param url
     *            发送请求的 URL
     * @param params
     *            请求参数,请求参数应该是 name1=value1&name2=value2 的形式。遍历map 然后拼接
     * @return 所代表远程资源的响应结果
     */
    public static byte[] doPost(String url, Map<String, String> params){
        // StringBuilder是用来组拼请求参数
        StringBuilder sb = new StringBuilder();
        if (params != null && params.size() != 0) {
            for (Map.Entry<String, String> entry : params.entrySet()) {
                try {
                    sb.append(entry.getKey()).append("=").append(URLEncoder.encode(entry.getValue(), "utf-8"));
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                sb.append("&");
            }
            sb.deleteCharAt(sb.length() - 1);
        }
        // entity为请求体部分内容
        // 如果有中文则以UTF-8编码为username=%E4%B8%AD%E5%9B%BD&password=123
        byte[] entity = sb.toString().getBytes();

        PrintWriter out = null;
        InputStream in = null;
        //本地的输出流
        ByteArrayOutputStream os;
        HttpURLConnection conn=null;
        //每次读的字节数
        byte[] data =new byte[1024];
        //每次读到的字节数,一般是1024,如果到了最后一行就会少于1024,到了末尾就是 -1
        int len=0;
        try{
            URL realUrl = new URL(url);
            // 打开和URL之间的连接
            conn = (HttpURLConnection) realUrl.openConnection();
            // 设置通用的请求属性
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestMethod("POST");
            //设置连接主机的超时时间(单位:毫秒)
            conn.setConnectTimeout(5000);
            // 从主机读取数据的超时时间(单位:毫秒)
            conn.setReadTimeout(5000);
            conn.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
            conn.setRequestProperty("charset", "utf-8");
            conn.setUseCaches(false);
            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setReadTimeout(TIMEOUT_IN_MILLIONS);
            conn.setConnectTimeout(TIMEOUT_IN_MILLIONS);
            //此处getOutputStream会隐含的进行connect(即:如同调用上面的connect()方法,
            //所以在开发中不调用上述的connect()也可以)。添加参数
            OutputStream ops = conn.getOutputStream();
            // 以POST方式发送请求体
            ops.write(entity);
            ops.close();

            if (conn.getResponseCode() == 200){
                in = conn.getInputStream();
                os=new ByteArrayOutputStream();
                while ((len=in.read(data))!=-1){
                    os.write(data,0,len);
                }
                return os.toByteArray();
                //return new String(os.toByteArray());//此处可以返回字节 字符串 流三种形式
            }else{
                Log.i("iiiiiiiii", "请求失败" + conn.getResponseCode());
            }
        } catch (Exception e){
            e.printStackTrace();
        }
        // 使用finally块来关闭输出流、输入流
        finally{
            try{
                if (out != null){
                    out.close();
                }
                if (in != null){
                    in.close();
                }
            } catch (IOException ex){
                ex.printStackTrace();
            }
            conn.disconnect();
        }
        return null;
    }
    /**
     * 向指定 URL 发送POST方法的请求
     * 请求体为json
     * @param path
     * 发送请求的 URL
     * @param obj
     * @return 所代表远程资源的响应结果
     */
    public static String doJson(String  path,String obj) throws IOException, JSONException {
        //创建连接
        URL url = new URL(path);
        HttpURLConnection connection ;
        StringBuffer sbuffer=null;
        try {
            //添加 请求内容
            connection= (HttpURLConnection) url.openConnection();
            //设置http连接属性
            connection.setDoOutput(true);// http正文内,因此需要设为true, 默认情况下是false;
            connection.setDoInput(true);// 设置是否从httpUrlConnection读入,默认情况下是true;
            connection.setRequestMethod("PUT"); // 可以根据需要 提交 GET、POST、DELETE、PUT等http提供的功能
            connection.setUseCaches(false);//设置缓存,注意设置请求方法为post不能用缓存
            // connection.setInstanceFollowRedirects(true);
            connection.setRequestProperty("Host", "*******");  //设置请 求的服务器网址,域名,例如***.**.***.***
            connection.setRequestProperty("Content-Type", " application/json");//设定 请求格式 json,也可以设定xml格式的
            connection.setRequestProperty("Accept-Charset", "utf-8");  //设置编码语言
            connection.setRequestProperty("X-Auth-Token", "token");  //设置请求的token
            connection.setRequestProperty("Connection", "keep-alive");  //设置连接的状态
            connection.setRequestProperty("Transfer-Encoding", "chunked");//设置传输编码
            connection.setRequestProperty("Content-Length", obj.toString().getBytes().length + "");  //设置文件请求的长度
            connection.setReadTimeout(10000);//设置读取超时时间
            connection.setConnectTimeout(10000);//设置连接超时时间
            connection.connect();
            OutputStream out = connection.getOutputStream();//向对象输出流写出数据,这些数据将存到内存缓冲区中
            out.write(obj.toString().getBytes());            //out.write(new String("测试数据").getBytes());            //刷新对象输出流,将任何字节都写入潜在的流中
            out.flush();
            // 关闭流对象,此时,不能再向对象输出流写入任何数据,先前写入的数据存在于内存缓冲区中
            out.close();
            //读取响应
            if (connection.getResponseCode()==200){
                // 从服务器获得一个输入流
                InputStreamReader   inputStream =new InputStreamReader(connection.getInputStream());//调用HttpURLConnection连接对象的getInputStream()函数, 将内存缓冲区中封装好的完整的HTTP请求电文发送到服务端。
                BufferedReader reader = new BufferedReader(inputStream);
                String lines;
                sbuffer= new StringBuffer("");
                while ((lines = reader.readLine()) != null) {
                    lines = new String(lines.getBytes(), "utf-8");
                    sbuffer.append(lines);
                }
                    reader.close();
                return  sbuffer.toString();
            }else{
                Log.i("iiiiiiiii", "请求失败" + connection.getResponseCode());
            }
            //断开连接
            connection.disconnect();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}

再写两个自定义的AsyncTask 借助接口回调 一个普通的异步任务 一个图片下载的异步任务

import android.os.AsyncTask;


import com.longlian.asynctask.util.HttpUtils;

import java.util.HashMap;
import java.util.Map;

public class MyAsyncTask extends AsyncTask<String, Void, String> {
    // 获取到JSON后的接口回调的实现类对象
        private JsonCallback callback;

        Map<String, String>map = new HashMap<String, String>();

        public MyAsyncTask(JsonCallback callback,Map<String, String> map2) {
            super();
            this.callback = callback;
            this.map = map2;
        }

        @Override
        protected String doInBackground(String... params) {
            byte [] array = HttpUtils.doPost(params[0], map);
            return new String(array,0,array.length);        
        }

        @Override
        protected void onPostExecute(String result) {
            // 调用回调接口中的方法
            callback.onListObtained(result);
            super.onPostExecute(result);
        }
        /**
         * 获取到JSON后的回调接口
         * @author Administrator
         */
        public interface JsonCallback {
            public void onListObtained(String result);
        }
}

//图片下载

import android.graphics.Bitmap;
import android.os.AsyncTask;

import com.longlian.asynctask.util.BitmapUtils;
import com.longlian.asynctask.util.HttpUtils;


public class ImageTask extends AsyncTask<String, Void, Bitmap> {

    //图片下载回调接口
    private ImageCallback callback; 
    public ImageTask(ImageCallback imageCallback) {
        this.callback = imageCallback;
    }
    String url = null;
    @Override
    protected Bitmap doInBackground(String... params) {
        url = params[0];
        try {
            byte[] imageData = HttpUtils.doGet(params[0]);
            Bitmap bitmap = BitmapUtils.doParse(imageData);
            return bitmap;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    protected void onPostExecute(Bitmap result) {       
        // 调用回调接口中的方法
        callback.onImageDownloaded(url, result);
        super.onPostExecute(result);
    }

    /**
     * 获取到JSON后的回调接口
     * @author Administrator
     */
    public interface ImageCallback {
        //传这个url是为了防止图片错位,给图片贴标签
        public void onImageDownloaded(String url, Bitmap bmp);
    }

}

再贴一个二次采样工具类

import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;

/**
 * 
 * @类名称: BitmapUtils
 * @类描述: 处理图片的工具类,用于图片的二次采样
 * @创建时间:2015年7月27日 下午1:09:13
 * @备注:
 * @version V1.0
 */
public class BitmapUtils {

    private static Config mDecodeConfig;
    private static int mMaxWidth;
    private static int mMaxHeight;

    /**
     * Creates a new image request, decoding to a maximum specified width and
     * height. If both width and height are zero, the image will be decoded to
     * its natural size. If one of the two is nonzero, that dimension will be
     * clamped and the other one will be set to preserve the image's aspect
     * ratio. If both width and height are nonzero, the image will be decoded to
     * be fit in the rectangle of dimensions width x height while keeping its
     * aspect ratio.
     *
     *            Listener to receive the decoded bitmap
     * @param maxWidth
     *            Maximum width to decode this bitmap to, or zero for none
     * @param maxHeight
     *            Maximum height to decode this bitmap to, or zero for none
     * @param decodeConfig
     *            Format to decode the bitmap to
     *            Error listener, or null to ignore errors
     */
    public void ImageRequest(int maxWidth, int maxHeight, Config decodeConfig) {
        mDecodeConfig = decodeConfig;
        mMaxWidth = maxWidth;
        mMaxHeight = maxHeight;
    }

    /**
     * 获取图片尺寸 Scales one side of a rectangle to fit aspect ratio.
     *
     * @param maxPrimary
     *            Maximum size of the primary dimension (i.e. width for max
     *            width), or zero to maintain aspect ratio with secondary
     *            dimension
     * @param maxSecondary
     *            Maximum size of the secondary dimension, or zero to maintain
     *            aspect ratio with primary dimension
     * @param actualPrimary
     *            Actual size of the primary dimension
     * @param actualSecondary
     *            Actual size of the secondary dimension
     */
    private static int getResizedDimension(int maxPrimary, int maxSecondary,
            int actualPrimary, int actualSecondary) {
        // If no dominant value at all, just return the actual.
        if (maxPrimary == 0 && maxSecondary == 0) {
            return actualPrimary;
        }

        // If primary is unspecified, scale primary to match secondary's scaling
        // ratio.
        if (maxPrimary == 0) {
            double ratio = (double) maxSecondary / (double) actualSecondary;
            return (int) (actualPrimary * ratio);
        }

        if (maxSecondary == 0) {
            return maxPrimary;
        }

        double ratio = (double) actualSecondary / (double) actualPrimary;
        int resized = maxPrimary;
        if (resized * ratio > maxSecondary) {
            resized = (int) (maxSecondary / ratio);
        }
        return resized;
    }

    /**
     * 对图片进行二次采样. The real guts of parseNetworkResponse. Broken out for
     * readability.
     */
    public static Bitmap doParse(byte[] data) {
        // byte[] data = data;
        BitmapFactory.Options decodeOptions = new BitmapFactory.Options();
        Bitmap bitmap = null;
        if (mMaxWidth == 0 && mMaxHeight == 0) {
            decodeOptions.inPreferredConfig = mDecodeConfig;
            bitmap = BitmapFactory.decodeByteArray(data, 0, data.length,
                    decodeOptions);
        } else {
            // If we have to resize this image, first get the natural bounds.
            decodeOptions.inJustDecodeBounds = true;

            BitmapFactory.decodeByteArray(data, 0, data.length, decodeOptions);
            int actualWidth = decodeOptions.outWidth;
            int actualHeight = decodeOptions.outHeight;

            // Then compute the dimensions we would ideally like to decode to.
            int desiredWidth = getResizedDimension(mMaxWidth, mMaxHeight,
                    actualWidth, actualHeight);
            int desiredHeight = getResizedDimension(mMaxHeight, mMaxWidth,
                    actualHeight, actualWidth);

            // Decode to the nearest power of two scaling factor.
            decodeOptions.inJustDecodeBounds = false;
            // (ficus): Do we need this or is it okay since API 8 doesn't
            // support it?
            // decodeOptions.inPreferQualityOverSpeed =
            // PREFER_QUALITY_OVER_SPEED;
            decodeOptions.inSampleSize = findBestSampleSize(actualWidth,
                    actualHeight, desiredWidth, desiredHeight);
            Bitmap tempBitmap = BitmapFactory.decodeByteArray(data, 0,
                    data.length, decodeOptions);

            // If necessary, scale down to the maximal acceptable size.
            if (tempBitmap != null
                    && (tempBitmap.getWidth() > desiredWidth || tempBitmap
                            .getHeight() > desiredHeight)) {
                bitmap = Bitmap.createScaledBitmap(tempBitmap, desiredWidth,
                        desiredHeight, true);
                tempBitmap.recycle();
            } else {
                bitmap = tempBitmap;
            }

        }

        return bitmap;

    }

    /**
     * 获取最佳图片压缩率. Returns the largest power-of-two divisor for use in
     * downscaling a bitmap that will not result in the scaling past the desired
     * dimensions.
     *
     * @param actualWidth
     *            Actual width of the bitmap
     * @param actualHeight
     *            Actual height of the bitmap
     * @param desiredWidth
     *            Desired width of the bitmap
     * @param desiredHeight
     *            Desired height of the bitmap
     */
    static int findBestSampleSize(int actualWidth, int actualHeight,
            int desiredWidth, int desiredHeight) {
        double wr = (double) actualWidth / desiredWidth;
        double hr = (double) actualHeight / desiredHeight;
        double ratio = Math.min(wr, hr);
        float n = 1.0f;
        while ((n * 2) <= ratio) {
            n *= 2;
        }

        return (int) n;
    }
}

Demo下载

猜你喜欢

转载自blog.csdn.net/qq_28963915/article/details/52118831