科百科
当前位置: 首页 科技资讯

okhttp可以用于电脑客户端吗(Okhttp的使用记录)

时间:2023-05-29 作者: 小编 阅读量: 1 栏目名: 科技资讯

第一步,添加依赖库'com.squareup.okhttp3:okhttp:3.10.0'自动下载两个库,OkHttp和Okio,后者是前者的通信基础第二步,具体用法创建OkHttpClient实例实现一个默认的客户端,没有连接时间限制OkHttpClientclient=newOkHttpClient();实现一个对连接时间读取时间有限制的客户端,超过时间限制,强制失败OkHttpClientc

第一步,添加依赖库'com.squareup.okhttp3:okhttp:3.10.0'

自动下载两个库,OkHttp和Okio,后者是前者的通信基础

第二步,具体用法

创建OkHttpClient实例

实现一个默认的客户端,没有连接时间限制

OkHttpClient client=new OkHttpClient();

实现一个对连接时间读取时间有限制的客户端,超过时间限制,强制失败

OkHttpClient client=new OkHttpClient.builder().connectTimeout(8000, TimeUnit.MILLISECONDS).readTimeout(8000,TimeUnit.MILLISECONDS).build();

发起Http请求(GET)

有同步和异步两种

同步需要自己开一个线程,执行网络连接

创建request请求,并在build()方法前连缀属性;

调用client的newCall()方法创建Call对象;

调用Call对象的excute()方法获取服务器返回的数据response;

返回结果数据格式依赖服务器实现

  1. new Thread(new Runnable() {
  2. @Override
  3. public void run() {
  4. OkHttpClient client=new OkHttpClient.Builder().connectTimeout(8000, TimeUnit.MILLISECONDS).readTimeout(8000,TimeUnit.MILLISECONDS).build();
  5. Request request= new Request.Builder().url(address).build();
  6. try {
  7. Response response=client.newCall(request).execute();
  8. if (response.body() != null) {
  9. String strResponse = response.body().string();
  10. }
  11. } catch (IOException e) {
  12. e.printStackTrace();
  13. }
  14. }
  15. }).start();

异步get请求,因为onResponse和onFailure()默认开启子线程,需要更新UI时,需要跳转主UI线程

  1. OkHttpClient client=new OkHttpClient.Builder().connectTimeout(8000, TimeUnit.MILLISECONDS).readTimeout(8000,TimeUnit.MILLISECONDS).build();
  2. Request request= new Request.Builder().url(address).build();
  3. client.newCall(request).enqueue(new callback() {
  4. @Override
  5. public void onFailure(Call call, IOException e) {
  6. // do something
  7. Log.d("http connect","失败");
  8. Log.d("http connect","e" e.toString());
  9. }
  10. @Override
  11. public void onResponse(Call call, Response response) throws IOException {
  12. if (response.isSuccessful()){
  13. // do something
  14. Log.d("http connect","获取数据");
  15. Log.d("http connect","response.code()==" response.code());
  16. Log.d("http connect","response.body().string()==" response.body().string());
  17. }
  18. }
  19. });

发起POST请求

创建RequestBody对象来存放待提交数据;

新建request请求,在build()前调用post()方法,并把body对象传入;

后续操作与get并没有区别

  1. OkHttpClient client=new OkHttpClient.Builder().connectTimeout(8000, TimeUnit.MILLISECONDS).readTimeout(8000,TimeUnit.MILLISECONDS).build();
  2. RequestBody body=new FormBody.Builder().add("account",account).add("password",password).build();
  3. Request request= new Request.Builder().url(address).post(body).build();
  4. client.newCall(request).enqueue(new Callback() {
  5. @Override
  6. public void onFailure(Call call, IOException e) {
  7. // do something
  8. Log.d("http connect","失败");
  9. Log.d("http connect","e" e.toString());
  10. }
  11. @Override
  12. public void onResponse(Call call, Response response) throws IOException {
  13. if (response.isSuccessful()){
  14. // do something
  15. Log.d("http connect","获取数据");
  16. Log.d("http connect","response.code()==" response.code());
  17. Log.d("http connect","response.body().string()==" response.body().string());
  18. }
  19. }
  20. });

response.code(),这个是http协议自带的,200表示连接成功

response.body().string()要放在子线程,且只执行一次

做一个小小的封装

  1. public class OkHttpUtils {
  2. private static OkHttpClient client ;
  3. private static final String TAG = "OkHttpUtils";
  4. private static ConcurrentHashMap<String, List<Cookie>> cookiestore = new ConcurrentHashMap<>();
  5. //单例模式返回一个实例
  6. public static OkHttpClient getInstance(){
  7. if (client==null)
  8. synchronized (OkHttpClient.class){
  9. if (client==null){
  10. //添加cookieJar,自动化管理cookie,获得一致的sessions值
  11. //添加连接超时和读取超时,在网络状况不好的时候可以做出提示.
  12. client=new OkHttpClient.Builder().cookieJar(new CookieJar() {
  13. @Override
  14. public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
  15. Log.i(TAG, "saveFromResponse: cookies=" cookies);
  16. Log.i(TAG, "saveFromResponse: cookieStore=" cookieStore.size());
  17. cookieStore.put(url.host(), cookies);
  18. }
  19. @Override
  20. public List<Cookie> loadForRequest(HttpUrl url) {
  21. List<Cookie> cookies = cookieStore.get(url.host());
  22. Log.i(TAG, "loadForRequest: cookies=" cookies);
  23. return cookies != null ? cookies : new ArrayList<Cookie>();
  24. }
  25. }).connectTimeout(8000, TimeUnit.MILLISECONDS).readTimeout(8000,TimeUnit.MILLISECONDS).build();
  26. }
  27. }
  28. return client;
  29. }
  30. //封装了一个静态方法.用来实现登录,url是你要访问的网址或者接口.在使用时可以通过匿名类,根据实际情况实现一个callback,在callback方法中,分别对成功和失败做处理
  31. public static void sendHttpLoginRequest( String account, String password, Callback callback) {
  32. OkHttpClient client=OkHttpUtils.getInstance();
  33. RequestBody body=new FormBody.Builder().add("account",account).add("password",password).build();
  34. Request request= new Request.Builder().url("url").post(body).build();
  35. client.newCall(request).enqueue(callback);
  36. }
  37. }

下面实际使用下,demo,点击获取按钮,会把获取到的信息设置到TextView中

  1. public class Main2Activity extends AppCompatActivity implements View.OnClickListener{
  2. private TextView mContent;
  3. private Button bInsquire;
  4. private Button bInfor;
  5. private Button bModifyPhone;
  6. private static final String TAG = "Main2Activity";
  7. //定义常量
  8. public static final int GET_CONTACT=1;
  9. public static final int GET_INFOR=2;
  10. public static final int MODIFY_PHONE=3;
  11. //定义一个内部Handler,用来获取callback发送的消息,重写内部方法,并处理消息
  12. private Handler handler=new Handler(){
  13. @Override
  14. public void handleMessage(Message msg) {
  15. if (msg!=null){
  16. switch (msg.what){
  17. case GET_CONTACT:
  18. mContent.setText((String)msg.obj);
  19. case GET_INFOR:
  20. mContent.setText((String)msg.obj);
  21. case MODIFY_PHONE:
  22. mContent.setText((String)msg.obj);
  23. }
  24. }else{
  25. Log.i(TAG, "hanlderNews: msg null");
  26. }
  27. }
  28. });
  29. @Override
  30. protected void onCreate(Bundle savedInstanceState) {
  31. super.onCreate(savedInstanceState);
  32. setContentView(R.layout.activity_main2);
  33. mContent=findViewById(R.id.tv_content);
  34. bInsquire=findViewById(R.id.b_inquire_contacts);
  35. bInfor=findViewById(R.id.b_Information);
  36. bModifyPhone=findViewById(R.id.b_modify_phone);
  37. bInsquire.setOnClickListener(this);
  38. bInfor.setOnClickListener(this);
  39. bModifyPhone.setOnClickListener(this);
  40. }
  41. @Override
  42. public void onClick(View view) {
  43. switch (view.getId()){
  44. case R.id.b_inquire_contacts:
  45. Log.i(TAG, "onClick: bInsquire");
  46. //匿名类,重写了失败和成功的处理,成功的时候,给Handler发送消息,消息内容为获得的相应体Response的内容
  47. OkHttpUtils.sendHttpContactsRequest(new Callback() {
  48. @Override
  49. public void onFailure(Call call, IOException e) {
  50. Log.i(TAG, "onFailure: connect failed");
  51. }
  52. @Override
  53. public void onResponse(Call call, Response response) throws IOException {
  54. if (response!=null){
  55. String strResponse=response.body().string();
  56. Log.d("http connect","response.code()==" response.code());
  57. Log.d("http connect","response.body().toString()==" strResponse);
  58. Message msg=Message.obtain();
  59. msg.what=GET_CONTACT;
  60. msg.obj=strResponse;
  61. mHanlderUtils.sendMessage(msg);
  62. }else {
  63. Log.i(TAG, "onResponse: response failed");
  64. }
  65. }
  66. });
  67. break;
  68. case R.id.b_Information:
  69. case R.id.b_modify_phone:
  70. }
  71. }
  72. }

注意,在新建Handler的时候,AS3.0版本以后会出现告警信息

This Handler class should be static or leaks might occur (anonymous android.os.Handler)

这是由于handler获取到activity的引用,可能由于消息处理的不及时,延时任务会导致activity不能被成功finish(),出现内存泄漏的风险,这里参考 https://blog.csdn.net/banxiali/article/details/51494842

对hanlder进行封装,持有当前活动的弱引用,由于封装的hanlder会处理不同的message,所以在封装Handler的handlerMessage()方法中回调接口方法,在不同的活动里根据情况实现这个接口即可

接口方法

  1. public interface HandlerNewsInterface {
  2. void hanlderNews(Message msg);
  3. }

封装handler

  1. public class HandlerUtils extends Handler {
  2. private WeakReference<Activity> mActivityReference;
  3. private HandlerNewsInterface mHanlderNews;
  4. HandlerUtils(Activity mActivity,HandlerNewsInterface mHanlderNews) {
  5. this.mActivityReference = new WeakReference<>(mActivity);
  6. this.mHanlderNews=mHanlderNews;
  7. }
  8. @Override
  9. public void handleMessage(Message msg) {
  10. mHanlderNews.hanlderNews(msg);
  11. super.handleMessage(msg);
  12. }
  13. }

所以上面的Demo中的Handler就可以这样实现

  1. private HandlerUtils mHanlderUtils=new HandlerUtils(this, new HandlerNewsInterface() {
  2. @Override
  3. public void hanlderNews(Message msg) {
  4. if (msg!=null){
  5. switch (msg.what){
  6. case GET_CONTACT:
  7. mContent.setText((String)msg.obj);
  8. case GET_INFOR:
  9. mContent.setText((String)msg.obj);
  10. case MODIFY_PHONE:
  11. mContent.setText((String)msg.obj);
  12. }
  13. }else{
  14. Log.i(TAG, "hanlderNews: msg null");
  15. }
  16. }
  17. });

记得要在活动消失前,移除hanlder中添加的消息

  1. @Override
  2. protected void onDestroy() {
  3. mHandlerUtils.removeMessages(GET_CONTACT);
  4. mHandlerUtils.removeMessages(GET_INFOR);
  5. mHandlerUtils.removeMessages(MODIFY_PHONE);
  6. super.onDestroy();
  7. }

注意,

A.网络请求,需要在配置文件中声明权限

记得在AndroidManifest.xml中配置网络权限。

<uses-permission android:name="android.permission.INTERNET"></uses-permission>

B.对okhttp进行底层封装

对okHttp的更多用法,参考

https://www.jianshu.com/p/ef9282217d07

1.单例模式,获取客户端实例保证

这个唯一的实例,可以在初始化时就设置连接超时,读取超时和写入超时,cookieJar自动管理cookie,可以设置缓存大小和目录

2 对网络连接超时和读取超时的处理

首先,在设置客户端的时候,我们在build()方法中添加了connectTimOut()和ReadTimeOut()方法,添加了超时属性

接下来,在callBack中返回失败的接口中分情况处理

  1. @Override
  2. public void onFailure(Call call, IOException e) {
  3. // do something
  4. Log.d("http connect","失败");
  5. //连接失败,一般是没有网络或者服务器问题
  6. if (e instanceof ConnectException){
  7. Log.d("http connect","ConnectException e=" e.toString());
  8. }
  9. //超时异常,一般是网络不好,可以设置重连以及重连次数
  10. if (e instanceof SocketTimeoutException){
  11. Log.d("http connect","SocketTimeoutException e=" e.toString());
  12. }
  13. }

3 psot数据的类型

表单数据(键值对)

RequestBody body=new FormBody.Builder().add("pwd",pwd).add("newPwd1",new1).add("newPwd2",new2).build();

json数组

  1. //设置媒体类型。application/json表示传递的是一个json格式的对象
  2. MediaType mediaType = MediaType.parse("application/json");
  3. //使用JSONObject封装参数
  4. JSONObject jsonObject = new JSONObject();
  5. try {
  6. jsonObject.put("参数名","参数值");
  7. } catch (JSONException e) {
  8. e.printStackTrace();
  9. }
  10. //创建RequestBody对象,将参数按照指定的MediaType封装
  11. RequestBody requestBody = RequestBody.create(mediaType,jsonObject.toString());

更多的媒体类型(MediaType)信息 https://baike.baidu.com/item/Internet Media Type?fr=aladdin

图片格式 参考https://blog.csdn.net/zhan10001/article/details/78461143

  1. private void sendMessage(String fileName,File file) {
  2. RequestBody requestBody = new MultipartBody.Builder()
  3. .setType(MultipartBody.FORM)
  4. .addFormDataPart("headPic", fileName,
  5. RequestBody.create(MediaType.parse("image/jpg"), file))
  6. .build();
  7. OkHttpClient client=OkHttp3Utils.getInstance();
  8. Request request=new Request.Builder().url(DataUtil.ModifyHeadPic).post(requestBody).build();
  9. client.newCall(request).enqueue(new Callback() {
  10. @Override
  11. public void onFailure(Call call, IOException e) {
  12. Log.i(TAG, "onFailure: failed");
  13. }
  14. @Override
  15. public void onResponse(Call call, Response response) throws IOException {
  16. if (response.isSuccessful()){
  17. String result=response.body().string();
  18. Log.i(TAG, "onResponse: result=" result);
  19. }
  20. }
  21. });

关于FileName和File的获取

需要知道路径信息imagePath;

  1. String fileName=imagePath.substring(imagePath.lastIndexOf("/") 1);
  2. File file=new File(imagePath);

表单数据提交能完成大部分的网络请求,毕竟一般发送少,下载多

如果需要发送大量的数据,或者需要接受不同格式的数据,就需要包装成json数组

https://blog.csdn.net/muyi_amen/article/details/58586605

4.添加拦截器

squareup公司自己提供了一个okhttp拦截器方便我们观察网络请求中的数据

使用方法

添加依赖 版本号 与okhttp一致

implementation 'com.squareup.okhttp3:logging-interceptor:3.10.0'

新建一个实例并配置参数

  1. HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
  2. logging.setLevel(HttpLoggingInterceptor.Level.BODY);

setlevel用来设置日志打印的级别,共包括了四个级别:NONE,BASIC,HEADER,BODY

BASEIC:请求/响应行

HEADER:请求/响应行头

BODY:请求/响应航头体

给okhttp.client添加拦截器

  1. client=new OkHttpClient.Builder()
  2. .addInterceptor(logging)
  3. .build();

5 cookie的持久化

https://www.jianshu.com/p/ef9282217d07

移动端和服务端连接的过程中,为了保证安全,

在okhttp3.0以后,新增了专门的CookieJar类来保存Cookie

  1. new CookieJar() {
  2. private HashMap<String, List<Cookie>> cookieStore = new HashMap<>();
  3. @Override
  4. public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
  5. cookieStore.put(url.scheme(), cookies);
  6. }
  7. @Override
  8. public List<Cookie> loadForRequest(HttpUrl url) {
  9. List<Cookie> cookies = cookieStore.get(url.scheme());
  10. return cookies != null ? cookies : new ArrayList<Cookie>();
  11. }
  12. }

主要原理:

Url的不变的一部分,比如Url.host()作为key,服务器返回的cookie作为value

saveFromResponse()中建立一个Map,并保存

loadForRequest()中根据url.host()来取出保存的cookie

    推荐阅读
  • 唐三重生最后成神了没(举贤不避亲的唐三重生后)

    终极斗罗最后一册的内容已经更新完毕,小舞陨落后,唐三选择了转世重生。虽然终极斗罗30册并没有交代唐三重生的细节,但是唐三在临走前却交代了诸多事宜给后代和其他神界领导者。为了让自己的儿子和儿媳继承毁灭神王和生命神王的神位,他提出了举贤不避亲。况且二人还是夫妻,唐三将神位传给他们也算是没有辜负毁灭之神和生命女神的嘱托。因此个人以为,唐三并不会将修罗神和海神的神位让给他人继承,而是会留给小舞和自己。

  • 部编四年级语文上册21课古诗三首(部编版四年级语文上册古诗三首课文解析)

    《古诗三首》收录在人教四年级语文上册教材,需要掌握:19个汉字。明确学习目标1、有感情地朗读课文,背诵课文,默写《题西林壁》。与其父苏洵、其弟苏辙并称“三苏”。梅花和雪花相互竞争,都认为自己是最具早春特色的,而且互不认输,这就将早春的梅花与雪花之美别出心裁、生动活泼地表现出来了。

  • 高一语文必修二知识梳理(高一语文必修二知识点整理)

    1945年在苏门达腊被日寇杀害,1952年被中央人民政府追认为革命烈士。1921年第一部小说集《沉沦》问世,1923年《春风沉醉的晚上》、《薄奠》。著有散文集《海星》《竹刀》《囚绿记》等,译著有《罗亭》《鲁宾逊漂流记》等。开创了我国古代诗歌的现实主义创作传统。②相当于“而”。⑤为,成为,引申为充当,充作。引申为承担,承受。

  • 赛鲸电脑桌怎么样(赛鲸床上电脑桌使用感受)

    赛鲸在设计方面与德国Patzak,spinn等多家设计学院合作,设计追求完美,在结构和工艺方面获得多项专利。赛鲸电脑桌设计的三大特点是超易用、超耐用、超稳固。赛鲸电脑桌一个动作完成桌面角度调节。德国设计的支架结构,采用轻钢架。靠结构控制力度和状态,赛鲸电脑桌的耐用性增强。

  • 最强蜗牛吃蘑菇任务攻略(蘑菇有多少种)

    最强蜗牛吃蘑菇任务攻略获得蘑菇的方法:蘑菇宝箱,蘑菇园,每日任务,馆长的头盔,地球晚宴转盘,解锁蜗牛壳,白蝌蚪礼包,氪金礼包。每食用一定数量后可额外增加食盒容量。生命蘑菇,食用后可额外获得四维加成。

  • 啵乐乐韩国进口饮料(韩国进口啵乐乐饮料新品)

    九日冰祖食品出品的啵乐乐牛奶盒装含乳饮料目前已获得啵乐乐品牌正版授权,由山东冰祖食品股份有限公司独家代理。当然,除了可爱爆棚的卡通形象,更重要的是啵乐乐饮料的优异品质。除此之外,啵乐乐牛奶含乳饮料富含人体所需要的各种营养,同时富含维生素A、维生素B1等多种元素。啵乐乐大牌饮品,线下线上均有售目前,啵乐乐牛奶含乳饮料已经问鼎各大市场渠道,备受年轻消费者喜爱。

  • 病毒感染可以引起贫血(这种细菌感染会引发贫血等血液病)

    相关研究表明,幽门螺旋杆菌与某些血液疾病的发生是密切相关的,比如说不明原因的缺铁性贫血。我们说贫血的患者啊,有幽门螺旋杆菌的患者感染率明显高于未感染的患者。再有就是许多研究发现,根除幽门螺旋杆菌后特发性血小板减少性紫癜患者的血小板数会明显增多,并伴随血清血小板抗体,IgG水平的下降,幽门螺旋杆菌可能是部分特发性或者是原发性血小板减少症的这种疾病的致病因素之一。

  • 很甜的小短句(36句微信超火的情话短句)

    36句微信超火的情话短句❤️想牵着你的手给各位来宾敬酒❤️我什么都知道但还是想听你娓娓道来❤️我家的狗挺喜欢你的随我❤️你主动找我的时候我激动的都能做完整套广播体操❤️你是我最爱的宝贝给我甜甜的草莓牛奶也不换❤️不许说我嘴硬。

  • 一年级家长每天需要做什么(一年级家长开学最该做什么)

    就拿小学一年级新生来说,一部分是学区或摇号或其它渠道进了心仪的学校,遂了愿,满心欢喜;一部分是各种原因找找拖拖不情愿进了备份学校,心不甘,心绪惆怅。孩子学习成绩的好坏大多数来自家长的教与养,家长对孩子的教养跟上,孩子会很好。还有就是一定要记得我们上学的目的是什么,让孩子喜欢学习,学会学习,最终学有所成,这才是重中之重,是核心。所以家长在孩子成长上学会抓重点,才能保证孩子的教育正确。

  • 少儿春晚嘉年华演出(2023嘉佳卡通华夏少年少儿春晚特邀小主持人刘思琳)

    活动以权威性、广泛性为原则,旨在向全省范围内选拔具有优秀潜质的未来之星,具有积极向上风貌的儿童优秀节目和演员,最终登上《华夏少年》少儿春节联欢晚会的舞台,通过嘉佳卡通卫视的播出展示给全国人民。哈喽大拇指语言艺术特邀优秀小主持人刘思琳同学,经过严格选拔,入选嘉佳卡通《华夏少年》少儿春节联欢晚会的主持人。据悉,嘉佳卡通卫视《华夏少年》少儿春节联欢晚会将于2023年1月21日播出。