okHttp封装,使用超简单的网络请求实现

文章内容概要:

  1. 框架需要解决的问题,及思路;
  2. 具体实施。

说明

okHttp是一款实用高效,使用简单的网络模块实现,虽然使用简单,但要在项目中使用还是得进行简单的封装,不可能每次请求都去写十几,甚至几十行相同的代码,这样是相当低效的,说这么多都算是废话。
来看看本次封装我想要达到的效果:
1. 调用起来要简单,我可以选择请求方式:getAsyn、getSync、post、fileUpload、fileDownload、displayImage。调用者只提供请求url,请求参数。至于内部如何发起请求,肯定是调用者所不关心的。
2. 返回值是调用者所关心的,调用成功或失败是调用者关心的,成功后我可以拿到返回结果,调用失败我可以选择是否处理,或者我不处理的时候可以默认提示请求失败。像显示图片这种请求,请求完后希望能直接更新UI。当然也可以选择显示完后进行回调。反正一句话,调用者想做什么都能做,什么都不做的时候程序不会出错。

实现

首先想到下面第一种方法。
1.在okHttp几大方法已经封装在一个思HttpUtil的类里,而且假设都是静态方法。这里在Activity中只需要调用譬如,HttpUtil.getAsyn(url,param);类似这样的调用即可,看起来调用还是挺方便的。来看返回,返回有成功和失败两种情况,okHttp本身提供了Callback接口,我们是否可以实现这个接口就可以拿到返回了,于是调用就成这样了

HttpUtil.getAsyn(url,param,new Callback() {
       @Override
       public void onFailure(Request request, IOException e) {
       }
       @Override
       public void onResponse(final Response response) throws IOException {
       }
       });

但是这样有一个问题,就是我调用方法的时候,我必须去实现这个接口,如果我不想去关心返回结果,那我还要去实现这个接口就太不友好了。那如果你不关心,大不了Activity实现这个接口,实现两个空方法,调用方法就变成了

HttpUtil.getAsyn(url,param,this);//this指的是Activity,必须实现Callback接口。

这样看起来是比匿名内部类简洁一点。如果实在不愿意去实现接口,那大不了HttpUtil多重载一个方法出来,不要求传Callback实现就行了。这也不失为一种解决办法。呵呵,这是我写之前没有想到的,似乎这么简单封装就能达到我们的要求了。

HttpUtil.getAsyn(url,param);//不关心返回时调用。

下面把我的封装说一下,用的java三大特性:封闭、继承、多态。呵呵,瞬间高大上了。
给所有 Activity 创建了一个父类:BaseActivity,父类中定义了一个属性:HttpUtil(非静态),在父类OnCreate中初始化HttpUtil。HttpUtil中保有BaseActivity的引用。

//BaseActivity部分代码
public abstract class BaseActivity extends Activity {
    public static final String TAG = BaseActivity.class.getSimpleName();
    protected Handler mHandler = null;
    public BaseUtil baseUtil;
    public HttpUtil httpUtil;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        baseUtil = new BaseUtil(this);
        //初始化httpUtil,并将this引用作为参数
        httpUtil = new HttpUtil(this);
        //初始化mHandler,用于子线程向主线程发消息
        initHandler();
    }
    //实现了一个http请求返回调用的空方法
    protected void httpResponse(String url, Map<String, Object> params, Object result) {

    }
    //文件下载完成后回调,空方法
    protected void completeDownload(String abstractPath) {
    }

    请求出错回调,默认提示网络请求失败
    void httpError(String url, Map<String, Object> params) {
        mHandler.post(new Runnable() {

            @Override
            public void run() {
                Toast.makeText(BaseActivity.this, "网络请求失败", 300).show();
            }
        });
    }
    .
    .
    .
}
//HttpUtil部分代码,这里也并非面对真正的okHttp封装,而在之上又包了一层。
//边写边想的时候发现这一层如果拿掉也不是不可以,但这样至少我们直接面对的代码是比较简洁的。
public class HttpUtil {
    private BaseActivity activity;
    public HttpUtil(BaseActivity activity) {
        this.activity = activity;
    }
    public Map<String, Object> getSyncHttp(String url) {
        try {
            Response response = OkHttpEngine.getInstance().getSyncHttp(activity, url);
            Map<String, Object> result = new HashMap<>();
            return result;
        } catch (IOException e) {
            return null;
        }
    }
    .
    .
    .
 }

进行了这两层封装,请求的返回方法已经被BaseActivity实现,子类Activity如果不关心,完全不用实现任何接口,请求之后的事情完全可以由BaseActivity消化吸收。若需要对返回值进行处理,子类实现httpResponse()方法即可。
Activity中调用网络请求方法:

public void httpTest(){
    this.httpUtil.getAsynHttp("https://www.baidu.com", p1);
    ImageView view = findView(R.id.imageview);
    // 加载图片
    this.httpUtil.displayImage(mHandler, view, "https://www.baidu.com/img/bd_logo1.png", R.drawable.no_image);
    String p = MyApplication.mkdirs("/net_image/a/b");
    //下载文件保存到sdcard/net_image/a/b文件夹下。
    this.httpUtil.downloadFile("http://a4.att.hudong.com/23/09/01300000165488122547095974400.jpg", p);
}

直接上代码了。来一张代码结构图
这里写图片描述
从上到下

BaseActivity.java

创建了mHandler,保证了如果子类不创建handler时,子类调用http请求后,父类可以代为处理响应,更新UI,显示提示信息等。
创建了httpUtil,将父类的引用传递到httpUtil中,请求返回后,直接调用响应成功或失败方法,如果子类实现了响应方法,调用会直达子类实现,这就是继承时多态。
实现了响应回调方法,若子类未实现时,父类可以代为处理。

package com.mydemo.common;

import java.util.Map;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.Toast;

public abstract class BaseActivity extends Activity {

    public static final String TAG = BaseActivity.class.getSimpleName();

    protected Handler mHandler = null;

    public BaseUtil baseUtil;

    public HttpUtil httpUtil;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        baseUtil = new BaseUtil(this);
        httpUtil = new HttpUtil(this);
        initHandler();
    }

    protected void initHandler() {
        mHandler = new Handler();
    }

    public <T> T findView(int id) {

        View view = findViewById(id);
        if (view == null || view.toString().equals("")) {
            return null;
        }
        return (T) view;
    }

    /**
     * 通过类名启动Activity
     * 
     * @param pClass
     */
    protected void openActivity(Class<?> pClass) {
        openActivity(pClass, null);
    }

    /**
     * 通过类名启动Activity,并且含有Bundle数据
     * 
     * @param pClass
     * @param pBundle
     */
    protected void openActivity(Class<?> pClass, Bundle pBundle) {
        Intent intent = new Intent(this, pClass);
        if (pBundle != null) {
            intent.putExtras(pBundle);
        }
        startActivity(intent);
    }

    /**
     * 通过Action启动Activity
     * 
     * @param pAction
     */
    protected void openActivity(String pAction) {
        openActivity(pAction, null);
    }

    /**
     * 通过Action启动Activity,并且含有Bundle数据
     * 
     * @param pAction
     * @param pBundle
     */
    protected void openActivity(String pAction, Bundle pBundle) {
        Intent intent = new Intent(pAction);
        if (pBundle != null) {
            intent.putExtras(pBundle);
        }
        startActivity(intent);
    }

    protected void httpResponse(String url, Map<String, Object> params, Object result) {

    }

    protected void completeDownload(String abstractPath) {
    }

    protected void httpError(String url, Map<String, Object> params, final Exception e) {
        mHandler.post(new Runnable() {

            @Override
            public void run() {
                Toast.makeText(BaseActivity.this, "网络请求失败:" + e.getMessage(), 4000).show();
            }
        });
    }

    void httpError(String url, Map<String, Object> params) {
        mHandler.post(new Runnable() {

            @Override
            public void run() {
                Toast.makeText(BaseActivity.this, "网络请求失败", 300).show();
            }
        });
    }

}
BaseUtil

这个类是工具类,一并承上,非本人原创。

package com.mydemo.common;

import java.util.Locale;

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.telephony.TelephonyManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.Toast;

public class BaseUtil {
    private Context context;

    protected InputMethodManager imm;

    private TelephonyManager tManager;

    public BaseUtil(Context context) {
        this.context = context;
        tManager = (TelephonyManager) context.getSystemService(context.TELEPHONY_SERVICE);
        imm = (InputMethodManager) context.getSystemService(context.INPUT_METHOD_SERVICE);
    }

    public void DisPlay(String content) {
        Toast.makeText(context, content, 1).show();
    }

    public void DisplayToast(String str) {
        Toast.makeText(context, str, Toast.LENGTH_SHORT).show();
    }

    public void hideOrShowSoftInput(boolean isShowSoft, EditText editText) {
        if (isShowSoft) {
            imm.showSoftInput(editText, 0);
        } else {
            imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);
        }
    }

    // 获得当前程序版本信息
    public String getVersionName() throws Exception {
        // 获取packagemanager的实例
        PackageManager packageManager = context.getPackageManager();
        // getPackageName()是你当前类的包名,0代表是获取版本信息
        PackageInfo packInfo = packageManager.getPackageInfo(context.getPackageName(), 0);
        return packInfo.versionName;
    }

    // 獲得設備信息
    public String getDeviceId() throws Exception {
        String deviceId = tManager.getDeviceId();

        return deviceId;
    }

    /**
     * 获取SIM卡序列号
     * 
     * @return
     */
    public String getToken() {
        return tManager.getSimSerialNumber();
    }

    /* 獲得系統版本 */

    public String getClientOs() {
        return android.os.Build.ID;
    }

    /* 獲得系統版本號 */
    public String getClientOsVer() {
        return android.os.Build.VERSION.RELEASE;
    }

    // 獲得系統語言包
    public String getLanguage() {
        return Locale.getDefault().getLanguage();
    }

    public String getCountry() {

        return Locale.getDefault().getCountry();
    }

}
HttpUtil

该类在BaseActivity中创建,并且保存BaseActivity对象引用。
1.使得调用都不需要将自身作为参数进行传递,减小了调用复杂度,
2.使得OkHttpEngine不需要BaseActivity进行绑定,使OkHttpEngine作为完全独立的存在。

package com.mydemo.common;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import android.os.Handler;
import android.widget.ImageView;

import com.squareup.okhttp.Response;

public class HttpUtil {

    private BaseActivity activity;

    public HttpUtil(BaseActivity activity) {
        this.activity = activity;
    }

    public void getAsynHttp(String url, Map<String, Object> params) {
        OkHttpEngine.getInstance().getAsynHttp(activity, url);
    }

    public Map<String, Object> getSyncHttp(String url) {
        try {
            Response response = OkHttpEngine.getInstance().getSyncHttp(activity, url);
            Map<String, Object> result = new HashMap<>();
            return result;
        } catch (IOException e) {
            return null;
        }
    }

    public void post(String url, Map<String, Object> params) {
        OkHttpEngine.getInstance().postAsynHttp(activity, url, params);
    }

    public void downloadFile(final String url, final String destFileDir) {
        OkHttpEngine.getInstance().downloadFile(activity, url, destFileDir);
    }

    public void displayImage(final Handler mHandler, final ImageView view, final String imgUrl, final int errorResId) {
        OkHttpEngine.getInstance().displayImage(mHandler, view, imgUrl, errorResId);
    }

    public void fileUpload(final String url, final Map<String, Object> params, File[] files, String[] fileKeys) {
        OkHttpEngine.getInstance().fileUpload(activity, url, params, files, fileKeys);
    }

}
ImageUtil

与图片处理相关工具类,非本人原创,一并承上。

package com.mydemo.common;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.lang.reflect.Field;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;

/**
 */
public class ImageUtils {
    /**
     * 根据InputStream获取图片实际的宽度和高度
     */
    public static ImageSize getImageSize(InputStream imageStream) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(imageStream, null, options);
        return new ImageSize(options.outWidth, options.outHeight);
    }

    public static class ImageSize {
        int width;

        int height;

        public ImageSize() {
        }

        public ImageSize(int width, int height) {
            this.width = width;
            this.height = height;
        }

        @Override
        public String toString() {
            return "ImageSize{" + "width=" + width + ", height=" + height + '}';
        }
    }

    public static int calculateInSampleSize(ImageSize srcSize, ImageSize targetSize) {
        // 源图片的宽度
        int width = srcSize.width;
        int height = srcSize.height;
        int inSampleSize = 1;

        int reqWidth = targetSize.width;
        int reqHeight = targetSize.height;

        if (width > reqWidth && height > reqHeight) {
            // 计算出实际宽度和目标宽度的比率
            int widthRatio = Math.round((float) width / (float) reqWidth);
            int heightRatio = Math.round((float) height / (float) reqHeight);
            inSampleSize = Math.max(widthRatio, heightRatio);
        }
        return inSampleSize;
    }

    /**
     * 根据ImageView获适当的压缩的宽和高
     */
    public static ImageSize getImageViewSize(View view) {

        ImageSize imageSize = new ImageSize();

        imageSize.width = getExpectWidth(view);
        imageSize.height = getExpectHeight(view);

        return imageSize;
    }

    /**
     * 根据view获得期望的高度
     */
    private static int getExpectHeight(View view) {

        int height = 0;
        if (view == null) return 0;

        final ViewGroup.LayoutParams params = view.getLayoutParams();
        // 如果是WRAP_CONTENT,此时图片还没加载,getWidth根本无效
        if (params != null && params.height != ViewGroup.LayoutParams.WRAP_CONTENT) {
            height = view.getWidth(); // 获得实际的宽度
        }
        if (height <= 0 && params != null) {
            height = params.height; // 获得布局文件中的声明的宽度
        }

        if (height <= 0) {
            height = getImageViewFieldValue(view, "mMaxHeight");// 获得设置的最大的宽度
        }

        // 如果宽度还是没有获取到,憋大招,使用屏幕的宽度
        if (height <= 0) {
            DisplayMetrics displayMetrics = view.getContext().getResources().getDisplayMetrics();
            height = displayMetrics.heightPixels;
        }

        return height;
    }

    /**
     * 根据view获得期望的宽度
     */
    private static int getExpectWidth(View view) {
        int width = 0;
        if (view == null) return 0;

        final ViewGroup.LayoutParams params = view.getLayoutParams();
        // 如果是WRAP_CONTENT,此时图片还没加载,getWidth根本无效
        if (params != null && params.width != ViewGroup.LayoutParams.WRAP_CONTENT) {
            width = view.getWidth(); // 获得实际的宽度
        }
        if (width <= 0 && params != null) {
            width = params.width; // 获得布局文件中的声明的宽度
        }

        if (width <= 0)

        {
            width = getImageViewFieldValue(view, "mMaxWidth");// 获得设置的最大的宽度
        }
        // 如果宽度还是没有获取到,憋大招,使用屏幕的宽度
        if (width <= 0)

        {
            DisplayMetrics displayMetrics = view.getContext().getResources().getDisplayMetrics();
            width = displayMetrics.widthPixels;
        }

        return width;
    }

    /**
     * 通过反射获取imageview的某个属性值
     */
    private static int getImageViewFieldValue(Object object, String fieldName) {
        int value = 0;
        try {
            Field field = ImageView.class.getDeclaredField(fieldName);
            field.setAccessible(true);
            int fieldValue = field.getInt(object);
            if (fieldValue > 0 && fieldValue < Integer.MAX_VALUE) {
                value = fieldValue;
            }
        } catch (Exception e) {
        }
        return value;

    }

    public static Bitmap getLoacalBitmap(String url) {
        try {
            FileInputStream fis = new FileInputStream(url);
            return BitmapFactory.decodeStream(fis);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return null;
        }
    }
}
okHttp封装

说明,这里方法调用里,使用BaseActivity作为参数,可能不是最好的方法,可以考虑使用实现了接口,可能更为妥当。本次暂不深究了。

package com.mydemo.common;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.FileNameMap;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.widget.ImageView;

import com.squareup.okhttp.Cache;
import com.squareup.okhttp.Call;
import com.squareup.okhttp.Callback;
import com.squareup.okhttp.FormEncodingBuilder;
import com.squareup.okhttp.Headers;
import com.squareup.okhttp.MediaType;
import com.squareup.okhttp.MultipartBuilder;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.Response;

public class OkHttpEngine {

    private static OkHttpEngine okHttpEngine;

    private OkHttpClient mOkHttpClient;

    public static synchronized void initEngine() {
        okHttpEngine = new OkHttpEngine();
    }

    public static OkHttpEngine getInstance() {
        if (okHttpEngine == null) {
            initEngine();
        }
        return okHttpEngine;
    }

    private OkHttpEngine() {
        mOkHttpClient = new OkHttpClient();
        mOkHttpClient.setConnectTimeout(15, TimeUnit.SECONDS);
        mOkHttpClient.setWriteTimeout(20, TimeUnit.SECONDS);
        mOkHttpClient.setReadTimeout(20, TimeUnit.SECONDS);
    }

    public OkHttpEngine setCache(Context mContext) {
        File sdcache = mContext.getExternalCacheDir();
        int cacheSize = 10 * 1024 * 1024;
        mOkHttpClient.setCache(new Cache(sdcache.getAbsoluteFile(), cacheSize));
        return okHttpEngine;
    }

    /**
     * @param currentActivity
     *            当前活动的activity对象
     * @param url
     *            请求地址
     * @param params
     *            参数
     */
    public void getAsynHttp(final BaseActivity currentActivity, final String url) {

        final Request request = new Request.Builder().url(url).build();
        Call call = mOkHttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Request request, IOException e) {
            }

            @Override
            public void onResponse(final Response response) throws IOException {
                String str = response.body().string();
                currentActivity.httpResponse(url, null, str);
            }
        });
    }

    public Response getSyncHttp(final BaseActivity currentActivity, final String url) throws IOException {
        // OkHttpClient mOkHttpClient = new OkHttpClient();
        final Request request = new Request.Builder().url(url).build();
        Call call = mOkHttpClient.newCall(request);
        Response mResponse = call.execute();
        if (mResponse.isSuccessful()) {
            currentActivity.httpResponse(url, null, mResponse.body().string());
            return mResponse;
        } else {
            currentActivity.httpError(url, null);
        }
        return null;
    }

    public void postAsynHttp(final BaseActivity currentActivity, final String url, final Map<String, Object> params) {
        // OkHttpClient mOkHttpClient = new OkHttpClient();
        FormEncodingBuilder builer = _getFormBuilder(params);
        Request request = new Request.Builder().url(url).post(builer.build()).build();
        Call call = mOkHttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Request request, IOException e) {
                currentActivity.httpError(url, params);
            }

            @Override
            public void onResponse(Response response) throws IOException {
                currentActivity.httpResponse(url, params, response.body().string());
            }
        });
    }

    public void fileUpload(final BaseActivity currentActivity, final String url, final Map<String, Object> params, File[] files, String[] fileKeys) {

        Request request = buildMultipartFormRequest(url, files, fileKeys, params);

        Call call = mOkHttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Request request, IOException e) {
                currentActivity.httpError(url, params);
            }

            @Override
            public void onResponse(Response response) throws IOException {
                String str = response.body().string();
                currentActivity.httpResponse(url, params, response.body().string());
            }
        });
    }

    /**
     * 下载文件,返回文件绝对路径
     * 
     * @param currentActivity
     * @param url
     *            文件网络地址
     * @param destFileDir
     *            文件存储位置
     */
    public void downloadFile(final BaseActivity currentActivity, final String url, final String destFileDir) {
        final Request request = new Request.Builder().url(url).build();
        final Call call = mOkHttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(final Request request, final IOException e) {
                currentActivity.httpError(url, new HashMap<String, Object>());
            }

            @Override
            public void onResponse(Response response) {
                InputStream is = null;
                byte[] buf = new byte[2048];
                int len = 0;
                FileOutputStream fos = null;
                try {
                    is = response.body().byteStream();
                    File file = new File(destFileDir, getFileName(url));
                    fos = new FileOutputStream(file);
                    while ((len = is.read(buf)) != -1) {
                        fos.write(buf, 0, len);
                    }
                    fos.flush();
                    Map<String, Object> params = new HashMap<String, Object>();
                    currentActivity.completeDownload(file.getAbsolutePath());
                } catch (IOException e) {
                    e.printStackTrace();
                    currentActivity.httpError(url, new HashMap<String, Object>(), e);
                } finally {
                    try {
                        if (is != null)
                            is.close();
                    } catch (IOException e) {
                    }
                    try {
                        if (fos != null)
                            fos.close();
                    } catch (IOException e) {
                    }
                }

            }
        });
    }

    public void displayImage(final Handler mHandler, final ImageView view, final String imgUrl, final int errorResId) {
        final Request request = new Request.Builder().url(imgUrl).build();
        Call call = mOkHttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Request request, IOException e) {
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        view.setImageResource(errorResId);
                    }
                });
            }

            @Override
            public void onResponse(Response response) {
                InputStream is = null;
                try {
                    is = response.body().byteStream();
                    ImageUtils.ImageSize actualImageSize = ImageUtils.getImageSize(is);
                    ImageUtils.ImageSize imageViewSize = ImageUtils.getImageViewSize(view);
                    int inSampleSize = ImageUtils.calculateInSampleSize(actualImageSize, imageViewSize);
                    try {
                        is.reset();
                    } catch (IOException e) {
                        response = _getAsyn(imgUrl);
                        is = response.body().byteStream();
                    }

                    BitmapFactory.Options ops = new BitmapFactory.Options();
                    ops.inJustDecodeBounds = false;
                    ops.inSampleSize = inSampleSize;
                    final Bitmap bm = BitmapFactory.decodeStream(is, null, ops);
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            view.setImageBitmap(bm);
                        }
                    });
                } catch (Exception e) {
                    setErrorResId(mHandler, view, errorResId);

                } finally {
                    if (is != null)
                        try {
                            is.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                }
            }
        });

    }

    /**
     * 同步的Get请求
     * 
     * @param url
     * @return Response
     */
    private Response _getAsyn(String url) throws IOException {
        final Request request = new Request.Builder().url(url).build();
        Call call = mOkHttpClient.newCall(request);
        Response execute = call.execute();
        return execute;
    }

    private FormEncodingBuilder _getFormBuilder(Map<String, Object> params) {
        FormEncodingBuilder builder = new FormEncodingBuilder();
        if (params != null && params.size() > 0) {
            Set<Entry<String, Object>> set = params.entrySet();
            Iterator<Entry<String, Object>> iterator = set.iterator();
            while (iterator.hasNext()) {
                Entry<String, Object> entry = iterator.next();
                builder.add(entry.getKey(), entry.getValue().toString());
            }
        }
        return builder;
    }

    private Request buildMultipartFormRequest(String url, File[] files, String[] fileKeys, final Map<String, Object> params) {

        MultipartBuilder builder = new MultipartBuilder().type(MultipartBuilder.FORM);

        if (params != null && params.size() > 0) {
            Set<Entry<String, Object>> set = params.entrySet();
            Iterator<Entry<String, Object>> iterator = set.iterator();
            while (iterator.hasNext()) {
                Entry<String, Object> entry = iterator.next();
                builder.addPart(Headers.of(String.format("Content-Disposition", "form-data; name=\"%s\"", entry.getKey())), RequestBody.create(null, entry.getValue().toString()));
            }
        }

        if (files != null) {
            RequestBody fileBody = null;
            for (int i = 0; i < files.length; i++) {
                File file = files[i];
                String fileName = file.getName();
                fileBody = RequestBody.create(MediaType.parse(guessMimeType(fileName)), file);
                // TODO 根据文件名设置contentType
                builder.addPart(Headers.of("Content-Disposition", "form-data; name=\"" + fileKeys[i] + "\"; filename=\"" + fileName + "\""), fileBody);
            }
        }

        RequestBody requestBody = builder.build();
        return new Request.Builder().url(url).post(requestBody).build();
    }

    private String guessMimeType(String path) {
        FileNameMap fileNameMap = URLConnection.getFileNameMap();
        String contentTypeFor = fileNameMap.getContentTypeFor(path);
        if (contentTypeFor == null) {
            contentTypeFor = "application/octet-stream";
        }
        return contentTypeFor;
    }

    private String getFileName(String path) {
        int separatorIndex = path.lastIndexOf("/");
        return (separatorIndex < 0) ? path : path.substring(separatorIndex + 1, path.length());
    }

    private void setErrorResId(final Handler mHandler, final ImageView view, final int errorResId) {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                view.setImageResource(errorResId);
            }
        });
    }
}
MainActivity
package com.mydemo.ui;

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

import com.mydemo.MyApplication;
import com.mydemo.common.BaseActivity;
import com.mydemo.common.ImageUtils;
import com.mydemo.okhttp.R;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.ImageView;
import android.widget.TextView;

public class MainActivity extends BaseActivity {

    private final String BAIDU_INDEX1 = "http://www.baidu.com";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mHandler = new Handler(getMainLooper()) {

            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                switch (msg.what) {
                case 1:
                    break;
                }
            }
        };
        Map<String, Object> p1 = new HashMap<String, Object>();
        this.httpUtil.getAsynHttp(BAIDU_INDEX1, p1);

        // this.getAsynHttp(BAIDU_INDEX2, p1);
        //
        // this.getAsynHttp(BAIDU_INDEX3, p1);
        // 要调用同步GET方法,但需要另起一个子线程发起请求,而不能直接在主线程发起请求。
        /*
         * Thread t = new Thread(new Runnable() {
         * @Override
         * public void run() {
         * Map<String, Object> p1 = new HashMap<>();
         * p1.put("s", System.currentTimeMillis());
         * MainActivity.this.getSyncHttp(BAIDU_INDEX4, p1);
         * }
         * });
         * t.start();
         */
        this.httpUtil.getAsynHttp(BAIDU_INDEX1, p1);
        ImageView view = findView(R.id.imageview);
        // 加载图片
        this.httpUtil.displayImage(mHandler, view, "https://www.baidu.com/img/bd_logo1.png", R.drawable.no_image);
        String p = MyApplication.mkdirs("/net_image/a/b");
        this.httpUtil.downloadFile("http://a4.att.hudong.com/23/09/01300000165488122547095974400.jpg", p);
    }

    @Override
    public void httpResponse(String url, Map<String, Object> params, Object result) {
        Message msg = new Message();
        switch (url) {
        case BAIDU_INDEX1:
            msg.what = 1;
            msg.obj = result;
            mHandler.sendMessage(msg);
            break;
        }

    }

    @Override
    public void completeDownload(final String abstractPath) {
        super.completeDownload(abstractPath);
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                ImageView view5 = findView(R.id.imageview2);
                view5.setImageBitmap(ImageUtils.getLoacalBitmap(abstractPath));
                TextView view1 = findView(R.id.result5);
                view1.setText("存储位置:" + abstractPath);
            }
        });
    }

    @Override
    protected void httpError(String url, Map<String, Object> params, final Exception e) {
        mHandler.post(new Runnable() {

            @Override
            public void run() {
                TextView view4 = findView(R.id.result5);
                view4.setText(e.getMessage());
            }
        });
    }

}
Application
package com.mydemo;

import java.io.File;

import android.app.Application;
import android.os.Environment;

public class MyApplication extends Application {

    static MyApplication application = new MyApplication();

    @Override
    public void onCreate() {
        super.onCreate();
    }

    private MyApplication() {

    }

    public static MyApplication getApplication() {
        return application;
    }

    public static String getSDPath() {
        File sdDir = null;
        boolean sdCardExist = Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED);// 判断sd卡是否存在
        if (sdCardExist) {
            sdDir = Environment.getExternalStorageDirectory();// 获取跟目录
        }
        return sdDir.toString();
    }

    public static String mkdirs(String path) {
        String sdcard = getSDPath();
        if (path.indexOf(getSDPath()) == -1) {
            path = sdcard + (path.indexOf("/") == 0 ? "" : "/") + path;
        }
        File destDir = new File(path);
        if (!destDir.exists()) {
            path = createDir(path);
            if (path == null) {
                return null;
            }
        }
        return path;
    }

    //不限层级创建文件夹,
    private static String createDir(String path) {
        String sdPath = getSDPath();
        String[] dirs = path.replace(sdPath, "").split("/");
        StringBuffer filePath = new StringBuffer(sdPath);
        for (String dir : dirs) {
            if (!"".equals(dir) && !dir.equals(sdPath)) {
                filePath.append("/").append(dir);
                File destDir = new File(filePath.toString());
                if (!destDir.exists()) {
                    boolean b = destDir.mkdirs();
                    if (!b) {
                        return null;
                    }
                }
            }
        }
        return filePath.toString();
    }
}
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginLeft="20dp"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/result1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="@string/hello_world" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="百度图片是直接显示的网络图片" />

    <ImageView
        android:id="@+id/imageview"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="5dp"
        android:contentDescription="网络图片" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:text="下面这张图是下载在本地后,再加载显示的" />

    <TextView
        android:id="@+id/result5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="@string/hello_world" />

    <ImageView
        android:id="@+id/imageview2"
        android:layout_width="300dp"
        android:layout_height="300dp"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="5dp"
        android:contentDescription="网络图片" />

</LinearLayout>

原谅,代码中注释太少,以后一定改正。
gitHub地址,欢迎Star or Fork!
https://github.com/luodengzhong/okHttpDemo
原源码奉上:
http://download.csdn.net/detail/ldz_wolf/9619513

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wolf犭良

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值