教你写Http框架(三)

一拖拖一年系列…… Orz
其实发这篇是因为最近正好有机会写了个小的http框架,其实根本都不能叫框架,就是个工具类,不过呢,经过几年的磨练我也深刻的感受到了一点:设计是个好东西,但是设计过度却是一个魔鬼。看多了Android的源码会感受到其实设计时度的把握可能比设计本身还重要,比如800多k的一个View类,如果用设计模式强行设计重构的话,估计能写出来几百个文件吧。把理论用到实践中是技术,但是这个度的把握就是艺术了,继续努力,学无止境。

直接上代码:

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Looper;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import cn.cmgame.miguim.utils.gson.Gson;
import cn.cmgame.miguim.utils.gson.GsonBuilder;

/**
 * Created by Amuro on 2017/10/20.
 */

public class HttpUtils
{
    private static final String TAG = "http";
    private static final int HTTP_CONNECT_TIMEOUT = 10 * 1000;
    private static final int HTTP_READ_TIMEOUT = 10 * 1000;
    public static final String GET = "GET";
    public static final String POST = "POST";
    private static final String DEFAULT_ENCODING = "UTF-8";
    private static Logger logger = Logger.getLogger(TAG);

    public interface IHttpListener<T>
    {
        void onSuccess(T result);

        void onFailed();
    }

    public static <T> void request(
            final String url, final Map<String, String> params,
            final Class<T> classOfT, final IHttpListener<T> listener)
    {
        request(url, POST, DEFAULT_ENCODING, null, params, classOfT, listener, false, null);
    }

    public static <T> void request(
            final String url, final Map<String, String> params,
            final Class<T> classOfT, final IHttpListener<T> listener,
            boolean isMock, String mockJson)
    {
        request(url, POST, DEFAULT_ENCODING, null, params, classOfT, listener, isMock, mockJson);
    }

    public static <T> void request(
            final String url, final String method, final String encoding,
            final Map<String, String> headers, final Map<String, String> params,
            final Class<T> classOfT, final IHttpListener<T> listener,
            final boolean isMock, final String mockJson)
    {
        final ExecutorService thread = Executors.newSingleThreadExecutor();
        thread.execute(new Runnable()
        {
            @Override
            public void run()
            {
                if (isMock)
                {
                    try
                    {
                        Thread.sleep(new Random().nextInt(3));
                    }
                    catch (InterruptedException e)
                    {
                        e.printStackTrace();
                    }

                    Gson gson = new GsonBuilder().create();
                    T result = gson.fromJson(mockJson, classOfT);
                    ;
                    deliverToMainThread(result, listener);
                }
                else
                {
                    final T result = syncRequest(
                            url, method, encoding, headers, params, classOfT);
                    deliverToMainThread(result, listener);
                }

                thread.shutdown();
            }
        });
    }

    private static <T> void deliverToMainThread(
            final T result, final IHttpListener<T> listener)
    {
        Handler handler = new Handler(Looper.getMainLooper());
        handler.post(new Runnable()
        {
            @Override
            public void run()
            {
                if (result == null)
                {
                    listener.onFailed();
                }
                else
                {
                    listener.onSuccess(result);
                }

            }
        });
    }

    public static <T> T syncRequest(
            String url, String method, String encoding,
            Map<String, String> headers, Map<String, String> params, Class<T> classOfT)
    {
        HttpURLConnection urlConnection = null;
        T result = null;

        try
        {
            urlConnection = createUrlConnection(url);
            urlConnection.setRequestMethod(method);
            setRequestHeaders(urlConnection, headers);
            setRequestParams(urlConnection, encoding, params);

            int responseCode = urlConnection.getResponseCode();
            if (responseCode != 200)
            {
                throw new Exception("response code not 200. It it " + responseCode);
            }
            else
            {
                InputStream inputStream = urlConnection.getInputStream();
                if (inputStream == null)
                {
                    throw new Exception("input stream is null");
                }
                else
                {

                    // 内存流
                    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                    byte[] data = new byte[1024];
                    int len = 0;
                    String resultStr = null;

                    while ((len = inputStream.read(data)) != -1)
                    {
                        byteArrayOutputStream.write(data, 0, len);
                    }
                    resultStr = new String(byteArrayOutputStream.toByteArray(), encoding);

                    Gson gson = new GsonBuilder().create();
                    result = gson.fromJson(resultStr, classOfT);
                }
            }
        }
        catch (Exception e)
        {
            logger.e("http exception: " + e.getMessage());
        }
        finally
        {
            if (urlConnection != null)
            {
                urlConnection.disconnect();
            }
        }

        return result;

    }

    private static HttpURLConnection createUrlConnection(String url) throws Exception
    {
        URL newURL = new URL(url);
        URLConnection urlConnection = newURL.openConnection();
        urlConnection.setConnectTimeout(HTTP_CONNECT_TIMEOUT);
        urlConnection.setReadTimeout(HTTP_READ_TIMEOUT);
        urlConnection.setDoInput(true);
        urlConnection.setUseCaches(false);
        return (HttpURLConnection) urlConnection;
    }

    private static void setRequestHeaders(
            HttpURLConnection connection, Map<String, String> headers)
    {
        if (headers == null)
        {
            return;
        }

        Set<String> headersKeys = headers.keySet();
        for (String headerName : headersKeys)
        {
            connection.addRequestProperty(
                    headerName, headers.get(headerName));
        }
    }

    private static void setRequestParams(
            HttpURLConnection connection, String encoding, Map<String, String> params) throws Exception
    {

        byte[] body = null;
        if (params != null && params.size() > 0)
        {
            body = encodeParameters(params, encoding);
        }
        if (body != null)
        {
            connection.setDoOutput(true);
            connection.addRequestProperty(
                    "Content-Type", "application/x-www-form-urlencoded; charset=" + encoding);
            DataOutputStream dataOutputStream =
                    new DataOutputStream(connection.getOutputStream());
            dataOutputStream.write(body);
            dataOutputStream.close();
        }
    }

    private static byte[] encodeParameters(
            Map<String, String> params, String paramsEncoding) throws Exception
    {
        StringBuilder encodedParams = new StringBuilder();
        for (Map.Entry<String, String> entry : params.entrySet())
        {
            encodedParams.append(
                    URLEncoder.encode(entry.getKey(), paramsEncoding));
            encodedParams.append('=');
            encodedParams.append(
                    URLEncoder.encode(entry.getValue(), paramsEncoding));
            encodedParams.append('&');
        }
        return encodedParams.toString().getBytes(paramsEncoding);
    }

    public interface IBitmapListener
    {
        void onSuccess(Bitmap bitmap);
        void onFailed();
    }

    public static void getImage(final String url, final IBitmapListener bitmapListener)
    {
        final ExecutorService thread = Executors.newSingleThreadExecutor();
        thread.execute(new Runnable()
        {
            @Override
            public void run()
            {
                final Bitmap bitmap = syncGetImage(url);
                if(bitmapListener != null)
                {
                    Handler handler = new Handler(Looper.getMainLooper());
                    handler.post(new Runnable()
                    {
                        @Override
                        public void run()
                        {
                            if(bitmap != null)
                            {
                                bitmapListener.onSuccess(bitmap);
                            }
                            else
                            {
                                bitmapListener.onFailed();
                            }
                        }
                    });
                }

                thread.shutdown();
            }

        });
    }

    private static Bitmap syncGetImage(String url)
    {
        Bitmap bm = null;
        // 1、确定网址
        // http://pic39.nipic.com/20140226/18071023_164300608000_2.jpg
        // 2、获取Uri
        try
        {
            URL uri = new URL(url);

            // 3、获取连接对象、此时还没有建立连接
            HttpURLConnection connection = (HttpURLConnection) uri.openConnection();
            // 4、初始化连接对象
            // 设置请求的方法,注意大写
            connection.setRequestMethod("GET");
            // 读取超时
            connection.setReadTimeout(5000);
            // 设置连接超时
            connection.setConnectTimeout(5000);
            // 5、建立连接
            connection.connect();

            // 6、获取成功判断,获取响应码
            if (connection.getResponseCode() == 200)
            {
                // 7、拿到服务器返回的流,客户端请求的数据,就保存在流当中
                InputStream is = connection.getInputStream();
                // 8、从流中读取数据,构造一个图片对象GoogleAPI
                bm = BitmapFactory.decodeStream(is);

            }

        }
        catch (Exception e)
        {
            e.printStackTrace();
        }

        return bm;
    }

    public interface IDownloadListener
    {
        void onSuccess(File file);
        void onFailed();
    }

    public static void downloadFile(
            final String url, final String fileName, final IDownloadListener downloadListener)
    {
        final ExecutorService thread = Executors.newSingleThreadExecutor();
        thread.execute(new Runnable()
        {
            @Override
            public void run()
            {
                final File file = syncGetFile(url, fileName);

                if(downloadListener != null)
                {
                    Handler handler = new Handler(Looper.getMainLooper());
                    handler.post(new Runnable()
                    {
                        @Override
                        public void run()
                        {
                            if(file != null)
                            {
                                downloadListener.onSuccess(file);
                            }
                            else
                            {
                                downloadListener.onFailed();
                            }
                        }
                    });
                }

                thread.shutdown();
            }
        });
    }

    private static File syncGetFile(String url, String fileName)
    {
        File file = null;

        try
        {
            URL uri = new URL(url);

            // 3、获取连接对象、此时还没有建立连接
            HttpURLConnection connection = (HttpURLConnection) uri.openConnection();
            // 4、初始化连接对象
            // 设置请求的方法,注意大写
            connection.setRequestMethod("GET");
            // 读取超时
            connection.setReadTimeout(5000);
            // 设置连接超时
            connection.setConnectTimeout(5000);
            // 5、建立连接
            connection.connect();

            // 6、获取成功判断,获取响应码
            if (connection.getResponseCode() == 200)
            {
                // 7、拿到服务器返回的流,客户端请求的数据,就保存在流当中
                InputStream is = connection.getInputStream();
                // 8、开启文件输出流,把读取到的字节写到本地缓存文件
                file = new File(fileName);
                FileOutputStream fos = new FileOutputStream(file);
                int len = 0;
                byte[] b = new byte[1024];
                while ((len = is.read(b)) != -1)
                {
                    fos.write(b, 0, len);
                }
                fos.close();
                is.close();
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }

        return file;
    }


}

麻雀虽小五脏俱全,该小框架可提供给小项目或sdk所有基础的http请求能力:正常请求,图片,下载。同时正常请求还提供了mock能力,可以在服务端接口不存在时客户端本地配置假数据进行测试。

从这个类的代码中我们也可以总结出所有和http有关操作的本质,无非就是从网络上拿回来一个流,正常就是把流写到内存里变成一个javabean供应用层使用;图片就是把流解析成bitmap,放到内存里或者写入文件;而下载就是把流写到文件中持久化。其实三者做的事本质一样。

真正的框架,只是基于这三个基础能力引入设计模式进行解耦和拓展罢了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
简介: 本框架是在Netroid的基础之上进行了封装,节省了其中配置的过程和一些不必要的操作 主要进行文本请求和图片请求,图片请求都进行了缓存(内存缓存和sd卡缓存)的封装,sd卡缓存时间可自行更改. 文本请求可传入解析的泛型clazz,即可返回解析后的clazz对象进行数据 操作,如果不需要进行数据解析,可通过另一种方式获取原生的string; 单图请求,单图请求可执行对本地asset文件夹,sd卡,http三种请求模式.只需传入相应的路径即可; 多图请求,多图请求主要是针对listview这种图文混排模式而生,能快速加载图片并实现缓存,不需要考虑 图片错位问题.只需传入相应的url即可完成全部功能. 使用说明: 1:在新创建的Manifest.xml中application中申明: <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" android:name="com.aqs.application.UApplication" > 并初始化Const.init();此处的初始化主要是对内存缓存,SD卡缓存大小,缓存时间等进行设置,如果不初始化,则按使用默认配置; 2:依赖HttpAqs-library或者jar包 3:通过公有方法进行网络请求,示例如下: >文本请求: >解析后的文本请求: HttpRequest.reqquest(int,String,Parse,Class){....}; >原生string文本请求: HttpRequest.getString(String,AqsString){...} >单张图片请求: HttpRequest.setImage(ImageView,String,int,int){...} >多张图片请求: 可使用AQSImageView控件来加载图片;特别是针对listview图文混排 实现方法: >在布局中添加 >在代码中 av.setImageUrl(url);

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值