Android okhttp3来进行网络数据请求和发送

来源:互联网 发布:华为手机网络诊断 编辑:程序博客网 时间:2024/06/06 13:58

在开发过程中我们很多地方都要和服务器进行交互以及请求数据,本篇博客简单的介绍下okhttp3。

1.get请求

2.post请求

3.上传文件

4.下载文件

ok,下面我们就要准备下如何封装使用okhttp3。

在Android studio中我们可以在app---->build.gradle   添加

  compile 'com.squareup.okhttp3:okhttp:3.4.1'(如下图所示)

这样我们就把okhttp3所需的jar导入成功了 下面我们开始进行okhttp3进行get、post封装。

Get请求

/** *  创建OkHttpClient对象 */OkHttpClient client = new OkHttpClient();/** * get请求 */public String Get(String url) throws IOException { /** * 创建一个Request  */    Request request = new Request.Builder()            .url(url)            .build();    Response response = client.newCall(request).execute();    return response.body().string();}

以上就是发送一个get请求的步骤,首先构造一个Request对象,参数最起码有个url,当然你可以通过Request.Builder设置更多的参数。

然后通过request的对象去构造得到一个Call对象,类似于将你的请求封装成了任务,既然是任务,就会有execute()cancel()等方法。

最后,我们希望以异步的方式去执行请求,所以我们调用的是call.enqueue,将call加入调度队列,然后等待任务执行完成,我们在Callback中即可得到结果。

说的再多 也就是封装使用 使用起来方便快捷。

Post请求

/** * post请求 */  public String Post(String url, FormBody form) throws IOException {      Request request = new Request.Builder()              .url(url)              .post(form)              .build();      Response response = client.newCall(request).execute();      if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);      return response.body().string();  }

在进行Post的时候,参数是包含在请求体中的;所以我们通过FormBody。添加多个String键值对,然后去构造RequestBody,最后完成我们Request的构造。后面的就和Get一样。

这里上传文件和下载文件 无非就是把数据提交到服务器(后台接口)、获取数据并  在这里没有必要再进行封装。下面会有Demo作为解释说明。 

注意上传图片是采用流的形式进行上传并后台一般是携带参数的 当时在这块遇到很多坑。下面贴出我封装的上传图片以及携带参数。

public static String postString(String url, Map<String, String> params, Map<String, File> files)        throws IOException {    String BOUNDARY = java.util.UUID.randomUUID().toString();    String PREFIX = "--", LINEND = "\r\n";    String MULTIPART_FROM_DATA = "multipart/form-data";    String CHARSET = "UTF-8";    URL uri = new URL(url);    HttpURLConnection conn = (HttpURLConnection) uri.openConnection();    conn.setReadTimeout(10 * 1000); // 缓存的最长时间    conn.setDoInput(true);// 允许输入    conn.setDoOutput(true);// 允许输出    conn.setUseCaches(false); // 不允许使用缓存    conn.setRequestMethod("POST");    conn.setRequestProperty("connection", "keep-alive");    conn.setRequestProperty("Charsert", "UTF-8");    conn.setRequestProperty("Content-Type", MULTIPART_FROM_DATA + ";boundary=" + BOUNDARY);    // 首先组拼文本类型的参数    StringBuilder sb = new StringBuilder();    for (Map.Entry<String, String> entry : params.entrySet()) {        sb.append(PREFIX);        sb.append(BOUNDARY);        sb.append(LINEND);        sb.append("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"" + LINEND);        sb.append("Content-Type: text/plain; charset=" + CHARSET + LINEND);        sb.append("Content-Transfer-Encoding: 8bit" + LINEND);        sb.append(LINEND);        sb.append(entry.getValue());        sb.append(LINEND);    }    DataOutputStream outStream = new DataOutputStream(conn.getOutputStream());    outStream.write(sb.toString().getBytes());    // 发送文件数据    if (files != null)        for (Map.Entry<String, File> file : files.entrySet()) {            StringBuilder sb1 = new StringBuilder();            sb1.append(PREFIX);            sb1.append(BOUNDARY);            sb1.append(LINEND);            sb1.append("Content-Disposition: form-data; name=\"upfile\"; filename=\""                    + file.getValue().getName() + "\"" + LINEND);            sb1.append("Content-Type: application/octet-stream; charset=" + CHARSET + LINEND);            sb1.append(LINEND);            outStream.write(sb1.toString().getBytes());            InputStream is = new FileInputStream(file.getValue());            byte[] buffer = new byte[1024];            int len = 0;            while ((len = is.read(buffer)) != -1) {                outStream.write(buffer, 0, len);            }            is.close();            outStream.write(LINEND.getBytes());        }    // 请求结束标志    byte[] end_data = (PREFIX + BOUNDARY + PREFIX + LINEND).getBytes();    outStream.write(end_data);    outStream.flush();    // 得到响应码    int res = conn.getResponseCode();    InputStream in = conn.getInputStream();    StringBuilder sb2 = new StringBuilder();    if (res == 200) {        int ch;        while ((ch = in.read()) != -1) {            sb2.append((char) ch);        }    }    outStream.close();    conn.disconnect();    return sb2.toString();}

  URL是上传到服务器所需的接口,

  Params是上传到服务器携带的参数

  File就是我们的获取图片

 通过拼接的方式构造请求的数据内容,实现参数之间的传输和文件传输


有些知识点是百度的 但很实用,图片上传过大,可能会导致上传失败,出现一些问题,所以咱们前端还是要进行图片的压缩上传。代码如下:
public static File scal(Uri fileUri){   String path = fileUri.getPath();   File outputFile = new File(path);   long fileSize = outputFile.length();   final long fileMaxSize = 200 * 1024;   if (fileSize >= fileMaxSize) {      BitmapFactory.Options options = new BitmapFactory.Options();      options.inJustDecodeBounds = true;      BitmapFactory.decodeFile(path, options);      int height = options.outHeight;      int width = options.outWidth;      double scale = Math.sqrt((float) fileSize / fileMaxSize);      options.outHeight = (int) (height / scale);      options.outWidth = (int) (width / scale);      options.inSampleSize = (int) (scale + 0.5);      options.inJustDecodeBounds = false;      Bitmap bitmap = BitmapFactory.decodeFile(path, options);      outputFile = new File(path);      FileOutputStream fos = null;      try {         fos = new FileOutputStream(outputFile);         bitmap.compress(Bitmap.CompressFormat.JPEG, 50, fos);         fos.close();      } catch (IOException e) {         // TODO Auto-generated catch block         e.printStackTrace();      }      Log.d("", "sss ok " + outputFile.length());      if (!bitmap.isRecycled()) {         bitmap.recycle();      }else{         File tempFile = outputFile;         outputFile = new File(PhotoUtil.createImageFile().getPath());         PhotoUtil.copyFileUsingFileChannels(tempFile, outputFile);      }   }   return outputFile;}

下面我们讲下如何使用我们封装好的okhttp3进行与服务器交互

  1 . Get请求使用方法

        final String url="http://app.1nuantong.com/api/app.php?act=systime";//        请求数据是耗时操作 故放在工作线程中        ThreadPool pool=new ThreadPool();        pool.submit(new Runnable() {            @Override            public void run() {                try {                    String  jsonString= OkHttpUtils.getInstance().Get(url);                    long systime=JSONObject.parseObject(jsonString).getLong("systime");//                    通过handler 从其它线程来操作界面的 有很多方法//                    比如Activity.runOnUiThread(Runnable)  View.post(Runnable) View.postDelayed(Runnable,long) 看个人喜好                    Message message=Message.obtain();                    message.what=mEssAge;                    message.obj=systime;//                  Handler(子线程调用Handler的handle.sendMessage(msg);                    mHandler.sendMessage(message);                } catch (IOException e) {                    e.printStackTrace();                }            }        });    }

注意事项:不要阻塞界面线程   不要在界面线程之外操作界面否则出现未定义的异常,难以进行调试处理。

在通过handlerMessage得到数据来更新Ui效果

private Handler mHandler=new Handler(){    @Override    public void handleMessage(Message msg) {        super.handleMessage(msg);        switch (msg.what){            case mEssAge:                long systime= (long) msg.obj;                getTextView.setText(DateUtils.getDateToString(systime*1000));                break;        }    }};

这里的DateUtils是进行时间戳的转换。

public class DateUtils {    /*时间戳转换成字符窜*/    public static String getDateToString(long time) {        Date d = new Date(time);        SimpleDateFormat sf = new SimpleDateFormat("yyyy年MM月dd日HH时mm分ss秒");        return sf.format(d);    }}

Post请求数据

/** * Post请求,参数是包含在请求体中的; 所以我们通过FormBody。添加多个String键值对。 */final String url="http://app.1nuantong.com/api/app.php";ThreadPool pool=new ThreadPool();final FormBody body=new FormBody.Builder()        .add("act","systime")        .build();pool.submit(new Runnable() {    @Override    public void run() {        try {            String  jsonString= OkHttpUtils.getInstance().Post(url,body);            long systime= JSONObject.parseObject(jsonString).getLong("systime");            Message message=Message.obtain();            message.what=mEssAge;            message.obj=systime;            mHandler.sendMessage(message);        } catch (IOException e) {            e.printStackTrace();        }    }});

效果也是和Get请求一样 通过HandlerMessage来进行展示效果。

下载文件

我们这里下载一个图片 并保存到本地上去。如后期需求 可以上传到服务器  我们也可以拿到图片的路径转化为流

压缩上传。在下载之前我们需要存放图片的路径和文件名。如需要上传服务器,还可以创建一个File来进行操作文件

因为下载 需要进行网络访问(耗时操作)所以避免造成ANR我们开辟一个线程来进行数据访问

private Runnable connectNet = new Runnable(){        @Override        public void run() {            try {                String filePath = ImageUrl;                // 准备拼接新的文件名(保存在存储卡后的文件名)               //  UUID.randomUUID().toString()是javaJDK提供的一个自动生成主键的方法                mFileName = UUID.randomUUID().toString() + ".jpg";//                通过Bitmap decodeStream 解码获取图片                mBitmap = BitmapFactory.decodeStream(getImageStream(filePath));                // 发送消息,通知handler在主线程中更新UI                connectHanlder.sendEmptyMessage(0);            } catch (Exception e) {                e.printStackTrace();            }        }    };
在这里我们已经从一个图片的地址 转化为bitmap 通过Handler来更新Ui显示到imageView这个控件上面。(非主线程不能操作Ui界面)

private Handler connectHanlder = new Handler() {    @Override    public void handleMessage(Message msg) {        // 更新UI,显示图片        if (mBitmap != null) {            image.setImageBitmap(mBitmap);        }    }};
getImageStream(图片地址);将图片地址转化为流的方法。

 public static InputStream getImageStream(String path) throws Exception{        // 构造URL        URL url = new URL(path);        // 打开连接        HttpURLConnection conn = (HttpURLConnection) url.openConnection();//        设置链接超出时间        conn.setConnectTimeout(5 * 1000);//        设置请求方式        conn.setRequestMethod("GET");//        得到响应码与200(HTTP_OK)比对 成功则返回输入流        if(conn.getResponseCode() == HttpURLConnection.HTTP_OK){            return conn.getInputStream();        }        return null;    }

接着下面我们将进行下载图片保存到本地

public static void saveFile(Bitmap bm, String fileName) throws IOException {    // 获得存储卡路径,构成 保存文件的目标路径    File dirFile = new File(ALBUM_PATH);    if(!dirFile.exists()){        dirFile.mkdir();    }    File myCaptureFile = new File(ALBUM_PATH + fileName);    BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(myCaptureFile));    bm.compress(Bitmap.CompressFormat.JPEG, 100, bos);    bos.flush();    bos.close();}

这样下载图片到本地 我们就完成了。

上传文件到服务器

需要后台给你一个上传的接口以及上传参数


Demo下载地址

http://download.csdn.net/download/sqj199567/9957065

这样我们就把okhttp的使用方法和与服务器间进行交互完成了。有不明白的,可以留言。




阅读全文
1 0
原创粉丝点击