这篇文章实现了OKhttp的二次封装,在封装里实现了请求Json数据,表单的提交,下载图片.
封装的好处:
1.节约内存,使所有的网络请求都用一个OKhttpclient和handler对象 2.解决OKhttp,网络请求成功,代码在子线程的问题,把请求成功后的逻辑代码放到主线程中执行 3.简化代码
OKhttp的中级封装,实现两个功能,从服务端下载数据;从客户端提交数据
封装优秀的OKhttp:OKhttpUtils,OKGO(更深入的封装,研究OKGO)
这次封装用到了那些知识点:
1.单例模式
2.handler
3.接口
4.OKhttp
我们在使用单例模式时,构造方法一般权限私有,这样保证了对象的唯一性(EventBus,如果看源码的话,他的构造方法是public,所以一方面可以通过单例方法拿到对象,一方面可以通过new方式拿到)首先,导依赖
compile 'com.squareup.okhttp3:okhttp-ws:3.4.2'添加网络权限
<uses-permission android:name="android.permission.INTERNET"/>添加布局
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:onClick="okhttp_json" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="获取Json数据" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:id="@+id/button2"/> <Button android:onClick="okhttp_table" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="表单提交" android:id="@+id/button3" android:layout_below="@+id/button2" android:layout_centerHorizontal="true"/> <Button android:onClick="okhttp_picture" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="下载图片" android:id="@+id/button4" android:layout_below="@+id/button3" android:layout_centerHorizontal="true"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/text" android:layout_below="@id/button4" android:layout_centerHorizontal="true" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/imageView" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true"/> </RelativeLayout>创建一个工具类OKhttpManager
public class OkhttpManager { 定义成员变量// private OkHttpClient mClient; private static Handler mHandler; private volatile static OkhttpManager sManager;//防止多个线程同时访问,volatile 使用构造方法,完成初始化// private OkhttpManager() { mClient = new OkHttpClient(); mHandler = new Handler(); } 使用单例模式,通过获取的方式拿到对象// public static OkhttpManager getInstance() { OkhttpManager instance = null; if (sManager == null) { synchronized (OkhttpManager.class) { if (instance == null) { instance = new OkhttpManager(); sManager = instance; } } } return instance; } 定义接口// interface Func1 { void onResponse(String result); } interface Func2 { void onResponse(byte[] result); } interface Func3 { void onResponse(JSONObject jsonObject); } 使用handler,接口,保证处理数据的逻辑在主线程// //处理请求网络成功的方法,返回的结果是json字符串 private static void onSuccessJsonStringMethod(final String jsonValue, final Func1 callBack) { //这里我用的是mHandler.post方法,把数据放到主线程中,你们以后可以用EvenBus或RXJava的线程调度器去完成 mHandler.post(new Runnable() { @Override public void run() { if (callBack != null) { try { callBack.onResponse(jsonValue); } catch (Exception e) { e.printStackTrace(); } } } }); } //请求网络成功的方法,返回的结果是byte数组 private static void onSuccessJsonByteMethod(final byte[] json,final Func2 callBack){ //把数据放到主线程,以后可以用EventBus或RxJava的线程调度器去完成 mHandler.post(new Runnable() { @Override public void run() { if (callBack!=null){ try { callBack.onResponse(json); }catch (Exception e){ e.printStackTrace(); } } } }); } 暴露提供给外界调用的方法// /** * 请求指定的URL返回的结果是json字符串 */ public void asyncJsonStringByURL(String url, final Func1 callBack) { Request request = new Request.Builder().url(url).build(); mClient.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException { //判断response是否有对象,成功 if (response!=null&&response.isSuccessful()){ onSuccessJsonStringMethod(response.body().string(),callBack); } } }); } /** * 提交表单 */ public void sendComplexForm(String url, Map<String,String> params,final Func1 callBack){ //表单对象 FormBody.Builder form_builder = new FormBody.Builder(); //健值非空判断 if (params!=null&&!params.isEmpty()){ for (Map.Entry<String,String> entry :params.entrySet()){ form_builder.add(entry.getKey(),entry.getValue()); } } FormBody request_body = form_builder.build(); Request request = new Request.Builder().url(url).post(request_body).build(); mClient.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException { if (response!=null&&response.isSuccessful()){ onSuccessJsonStringMethod(response.body().string(),callBack); } } }); } //下载图片 public void asyncJsonByteByUrl(String url,final Func2 callBack){ Call call = mClient.newCall(new Request.Builder().url(url).build()); call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException { if(response!=null){ byte[] bytes = response.body().bytes(); onSuccessJsonByteMethod(bytes,callBack); } } }); } }最后再MainActivity中实现效果
public class MainActivity extends AppCompatActivity { private String json_path = "http://publicobject.com/helloworld.txt"; private String Login_path = "http://169.254.53.96:8080/web/LoginServlet"; private String Picture_path = "https://10.url.cn/eth/ajNVdqHZLLAxibwnrOxXSzIxA76ichutwMCcOpA45xjiapneMZsib7eY4wUxF6XDmL2FmZEVYsf86iaw/"; private ImageView mImageView; private OkhttpManager mOkhttpManager; private TextView mTextView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mImageView = (ImageView) findViewById(imageView); mTextView= (TextView) findViewById(R.id.text); mOkhttpManager = OkhttpManager.getInstance(); } /** * 通过点击事件执行okhttp里封装的根据网址,获取字符串的逻辑操作. * * @param view */ public void okhttp_json(View view) { mOkhttpManager.asyncJsonStringByURL(json_path,new OkhttpManager.Func1(){ @Override public void onResponse(String result) { mTextView.setText(result); } }); } //像服务器提交账号及密码 public void okhttp_table(View view) { HashMap<String, String> map = new HashMap<>(); map.put("qq","10000"); map.put("pwd","abcde"); mOkhttpManager.sendComplexForm(Login_path, map, new OkhttpManager.Func1() { @Override public void onResponse(String result) { mTextView.setText(result); } }); } //下载图片 public void okhttp_picture(View view) { mOkhttpManager.asyncJsonByteByUrl(Picture_path, new OkhttpManager.Func2() { @Override public void onResponse(byte[] result) { Bitmap bitmap = BitmapFactory.decodeByteArray(result, 0, result.length); mImageView.setImageBitmap(bitmap); } }); } }
好了,这就简单的实现OKhttp的二次封装.