Android网络技术之OkHttp框架

       Android网络请求是个耗时的操作,一定要在子线程中运行,添加网络权限,目前有很多流行的网络框架。比如okhttp,volley,xutils等等。使用okhttp很简单,它的请求/响应 API设计,运用了流利的builder,确保方式多样而又固定,支持异步请求和回调。它支持android 2.3或以上,jdk版本要求不低于1.7。

      在使用OkHttp之前,需要先在项目中添加OkHttp库的依赖。编辑app/build.gradle文件,在dependencies闭包中添加如下内容,下载OkHttp库和Okio库.

 

dependencies {
compile 'com.squareup.okhttp3:okhttp:3.4.1'

}

还有另外一种添加OkHttp库依赖包的方法:

按Android Studio中快捷键Ctrl+Shift+Alt+s,在库中搜索OKhttp并添加:

Android网络技术之OkHttp框架_第1张图片

Android网络技术之OkHttp框架_第2张图片

在日常开发中最常用到的网络请求就是GET和POST两种请求方式。

OkHttp通过“GET”发送HTTP请求核心代码:

 
/**
 *由于Android本身是不允许在UI线程做网络请求操作的,
 * 同步写法,需要放在子线程中使用.
 */
new Thread(new Runnable() {
@Override
public void run() {
        try {
        //创建一个OkHttpClient实例
         OkHttpClient client=new OkHttpClient();
        //创建一个Request对象,在build()之前连缀很多其他方法来丰富
         //这个Request对象,比如用url()方法来设置网络地址。
         Request request= new Request.Builder().
        url("https://www.baidu.com/").build();
        //调用OkHttpClient的newCall()方法来创建一个对象Call对象,
         //并调用它的execute()方法来发送请求并获取返回的数据。
         Response response=client.newCall(request).execute();
        //获取服务器返回的具体数据
         String responseData=response.body().string();
        }catch (Exception e){
           e.printStackTrace();
        }
     }
}).start();
Request是OkHttp中访问的请求,Builder是辅助类,Response即OkHttp中的响应。
同步的get请求方法还有另外一种写法;
 
Responses(响应),  响应则包含一个回复代码(200代表成功,404代表未找到),Header和定制可选的body。
 
OkHttpClient client = new OkHttpClient(); String run(String url) throws IOException { Request request = new Request.Builder().url(url).build();  Response response = client.newCall(request).execute();  if (response.isSuccessful()) { return response.body().string();  } else { throw new IOException("Unexpected code " + response);  } 
}
 

那如果是通过“POST”来发送HTTP请求,我们需要考虑提交的数据存放在那?如何提交?

//POST:只需改动GET方法的Request对象,其他的一样 //创建一个RequestBody对象来存放待提交的数据 RequestBody requestBody=new FormBody.Builder() .add("name","aichuan") .add("password","123456") .build(); //Request().Builder()中调用post()方法,并将RequestBody对象传入 Request request=new Request().Builder() .url("https://www.baidu.com/") .post(requestBody) .build();

Response类:

public boolean isSuccessful()
Returns true if the code is in [200..300), which means the request was successfully received, understood, and accepted.
response.body()返回ResponseBody类
response.body()返回ResponseBody类

可以更方便的获取string:

public final String string() throws IOException
Returns the response as a string decoded with the charset of the Content-Type header. If that header is either absent or lacks a charset, this will attempt to decode the response body as UTF-8.
Throws:
IOException

 

以上的请求都是同步请求,下面异步请求:

OkHttp通过“GET”发送异步请求核心代码:

//创建OkHttpClient对象,用于稍后发起请求
OkHttpClient client = new OkHttpClient();
//根据请求URL创建一个Request对象
Request request = new Request.Builder().url("url").build();
//根据Request对象发起Get同步Http请求
Response response = client.newCall(request).execute();
//根据Request对象发起Get异步Http请求,并添加请求回调
client.newCall(request).enqueue(new Callback() {
@Override
public void onResponse(final Response response) {
        //请求成功,此处对请求结果进行处理
        //String result = response.body().string();
       //InputStream is = response.body().byteStream();
       //byte[] bytes = response.body().bytes();
 }

@Override
public void onFailure(Request request, IOException e) {
        //请求失败
    }
});

HTTP异步 POST请求。

POST异步提交Json数据:

try {
     public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
     OkHttpClient client = new OkHttpClient();
     RequestBody body = RequestBody.create(JSON, json);
     Request request = new Request.Builder()
              .url(url)
              .post(body)
              .build();
     Response response = client.newCall(request).execute();
     if(response.isSuccessful()) {
        return response.body().string();
     } else {
        throw new IOException("Unexpected code " + response);
     }
   }catch (Exception e){
       e.printStackTrace();
 }

POST异步提交键值对:

OkHttpClient client = new OkHttpClient();
String post(String url, String json) throws IOException {       
     RequestBody formBody = new FormEncodingBuilder()
            .add("platform", "android")
            .add("name", "bug")
            .add("subject", "XXXXXXXXXXXXXXX")
            .build();
         
     Request request = new Request.Builder()
              .url(url)
              .post(body)
              .build();
         
     Response response = client.newCall(request).execute();
     if (response.isSuccessful()) {
         return response.body().string();
     } else {
         throw new IOException("Unexpected code" + response);
     }
}

使用OkHttp下载网络图片栗子:

activity_main.xml



    
Java代码:
public class MainActivity extends AppCompatActivity {
    private String url="http://photocdn.sohu.com/20110927/Img320705637.jpg";
    private static final int SUCCESS = 1;
    private static final int FALL = 2;
    private OkHttpClient client;
    private Button getButton;
    private ImageView getImageView;

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

    }
    public void initLayout(){
        getImageView=(ImageView) findViewById(R.id.imageView);
        getButton=(Button) findViewById(R.id.button);
        getButton.setOnClickListener(new View.OnClickListener() {
            /**
             * 异步get,直接调用
             */
            @Override
            public void onClick(View v) {
                //1.创建一个client对象
                 client=new OkHttpClient();
                //2.创建Request.Builder对象,设置参数,
                 //请求方式如果是Get,就不用设置,默认就是Get
                Request request=new Request.Builder().url(url).build();
                //3.创建一个Call对象,参数是request对象,发送请求
                  Call call=client.newCall(request);
                //4.异步请求,请求加入调度
                  call.enqueue(new Callback() {
                    @Override
                    public void onFailure(Call call, IOException e) {

                    }

                    @Override
                    public void onResponse(Call call, Response response)
                            throws IOException {
                        //得到从网上获取资源,转换成我们想要的类型
                        byte[] getData=response.body().bytes();
                        //通过handler更新UI
                        Message message=handler.obtainMessage();
                        message.obj=getData;
                        message.what=SUCCESS;
                        handler.sendMessage(message);
                    }
                });
            }
        });
    }
    Handler handler=new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what){
                case SUCCESS:
                    //通过message,拿到字节数组
                    byte[] data=(byte[]) msg.obj;
                    //使用BitmapFactory工厂,把字节数组转化为bitmap
                    Bitmap bitmap= BitmapFactory
                            .decodeByteArray(data,0,data.length);
                    //通过imageview,设置图片
                    getImageView.setImageBitmap(bitmap);
                    break;
                    //当加载网络失败执行的逻辑代码
                case FALL:
                    Toast.makeText(MainActivity.this, "网络出现了问题",
                            Toast.LENGTH_SHORT).show();
                    break;
            }
        }
    };
}

记得申请网络权限:

同步get请求下载网络图片代码:由上面的栗子改下点击事件里的逻辑代码即可

    @Override
    public void onClick(View v) {
        /**
         * 同步写法,需要放在子线程中使用
         */
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    //创建一个client实例对象
                    client=new OkHttpClient();
                    //获取请求对象
                    Request request=new Request.Builder()
                            .url(url).build();
                    Response response=client.newCall(request)
                            .execute();
                    InputStream ism=response.body().byteStream();
//                      //获取响应体(也可以这样写)
//                      ResponseBody Body=client.newCall(request)
//                                    .execute().body();
//                      //获取流
//                      InputStream ism=Body.byteStream();
                    //转化为bitmap
                    Bitmap bitmap= BitmapFactory.decodeStream(ism);
                    //使用Hanlder发送消息
                      Message msg=handler.obtainMessage();
                    msg.obj=bitmap;
                    msg.what=SUCCESS;
                    handler.sendMessage(msg);
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }).start();
    }
private Handler handler=new Handler(){
    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        switch (msg.what){
            case SUCCESS:
                getImageView.setImageBitmap((Bitmap) msg.obj);
                break;
            case FALL:
                Toast.makeText(OkHttpActivity.this,
                        "连接超时", Toast.LENGTH_SHORT).show();
                break;
        }
    }
};
异步同步效果图都一样,成功下载图片:

Android网络技术之OkHttp框架_第3张图片

 

总结一下:

OkHttp 是一个相对成熟的解决方案,据说 Android4.4 的源码中可以看到 HttpURLConnection 已经替换成 OkHttp 实现了。在 Android 6.0 中底层的源码已经使用了 OKHttp 。OkHttp 处理了很多网络疑难杂症:会从很多常用的连接问题中自动恢复。如果您的服务器配置了多个IP地址,当第一个 IP 连接失败的时候,OkHttp 会自动尝试下一个 IP。OkHttp 还处理了代理服务器问题和 SSL握手失败问题。使用 OkHttp 无需重写您程序中的网络代码。

 

你可能感兴趣的:(Android,网络技术)