Android入门之使用OKHttp组件访问网络资源

作者:TGITCIC 时间:2023-08-28 10:57:03 

简介

今天的课程开始进入高级课程类了,我们要开始接触网络协议、设备等领域编程了。在今天的课程里我们会使用OKHttp组件来访问网络资源而不是使用Android自带的URLConnection。一个是OKHttp组件更方便二个是OKHttp组件本身就带有异步回调功能。

下面就进入课程。

课程目标

Android入门之使用OKHttp组件访问网络资源

Android入门之使用OKHttp组件访问网络资源

Android入门之使用OKHttp组件访问网络资源

我们的课程目标有4个点:

  • 使用OKHttp组件;

  • 使用OKHttp组件加载网络图片显示在APP的ImgView里;

  • 使用OKHttp组件加载给定网页代码显示在ScrollView里;

  • 使用OKHttp组件加载给定网页显示在WebView里;

以上过程都为异步加载。

代码前在gradle里要先声明对于OKHttp组件的引用

要使用OKHttp组件,我们必须要在build.gradle中加入以下语句:

implementation 'com.squareup.okhttp3:okhttp:3.10.0'

以下是加完上述语句后的build.gradle。

Android入门之使用OKHttp组件访问网络资源

访问网络资源需要给到APP以权限

我们因为要访问网络资源,因此我们需要给到APP以相应的权限。编辑AndroidManifest.xml文件,并加入以下两行声明。

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

加完后的AndroidManifest.xml长这样

Android入门之使用OKHttp组件访问网络资源

代码

菜单res\menu\pop_menu.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
   <item android:id="@+id/menuItemDisplayPic" android:title="加载图片" />
   <item android:id="@+id/menuItemDisplayHtmlCode" android:title="加载网页代码" />
   <item android:id="@+id/menuItemDisplayHtmlPage" android:title="加载网页" />
</menu>

主UI界面

<?xml version="1.0" encoding="utf-8"?>
<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:orientation="vertical"
   tools:context=".MainActivity">

<Button
       android:id="@+id/buttonShowMenu"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:layout_below="@+id/textColor"
       android:layout_centerHorizontal="true"
       android:layout_marginTop="10dp"
       android:text="展示弹出菜单" />

<ImageView
       android:id="@+id/imgPic"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:visibility="gone" />

<ScrollView
       android:id="@+id/scroll"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:visibility="gone">

<TextView
           android:id="@+id/htmlTxt"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content" />
   </ScrollView>
   <WebView
       android:id="@+id/webView"
       android:layout_width="match_parent"
       android:layout_height="match_parent" />

</LinearLayout>

MainActivity

package org.mk.android.demo.http;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.webkit.WebView;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.PopupMenu;
import android.widget.ScrollView;
import android.widget.TextView;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import okhttp3.OkHttpClient;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.Buffer;
import okio.BufferedSource;
public class MainActivity extends AppCompatActivity {

private String TAG = "DemoOkHttp";
   private Button buttonShowMenu;
   private TextView htmlTxt;
   private ImageView imgPic;
   private WebView webView;
   private ScrollView scroll;
   private Bitmap bitmap;
   private String htmlContents;

@Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);
       buttonShowMenu = (Button) findViewById(R.id.buttonShowMenu);
       htmlTxt = (TextView) findViewById(R.id.htmlTxt);
       imgPic = (ImageView) findViewById(R.id.imgPic);
       webView = (WebView) findViewById(R.id.webView);
       scroll = (ScrollView) findViewById(R.id.scroll);
       buttonShowMenu.setOnClickListener(new View.OnClickListener() {
           @Override
           public void onClick(View view) {
               PopupMenu popup = new PopupMenu(MainActivity.this, buttonShowMenu);
               popup.getMenuInflater().inflate(R.menu.pop_menu, popup.getMenu());
               popup.setOnMenuItemClickListener(new MenuItemClick());
               popup.show();
           }
       });
   }

// 定义一个隐藏所有控件的方法:
   private void hideAllWidget() {
       imgPic.setVisibility(View.GONE);
       scroll.setVisibility(View.GONE);
       webView.setVisibility(View.GONE);
   }

private class MenuItemClick implements PopupMenu.OnMenuItemClickListener {
       @Override
       public boolean onMenuItemClick(MenuItem item) {
           String imgPath = "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.alicdn.com%2Fi2%2F2542318073%2FO1CN01fJvTi029VTwR16EvP_%21%212542318073.jpg&refer=http%3A%2F%2Fimg.alicdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1673938156&t=69e5ee87fbf4b81b5f6eea53ed5b5158";
           String htmlPagePath = "https://www.baidu.com";
           switch (item.getItemId()) {
               case R.id.menuItemDisplayPic:
                   downLoadImgFromPath(imgPath);
                   break;
               case R.id.menuItemDisplayHtmlCode:
                   getHtmlAsync(htmlPagePath, 102);
                   break;
               case R.id.menuItemDisplayHtmlPage:
                   getHtmlAsync(htmlPagePath, 103);

break;
           }
           return true;
       }
   }

private Handler httpHandler = new Handler(new Handler.Callback() {
       @Override
       public boolean handleMessage(@NonNull Message msg) {
           Log.i(TAG, ">>>>>>receive handler Message msg.what is: " + msg.what);
           switch (msg.what) {
               case 101:
                   hideAllWidget();
                   imgPic.setVisibility(View.VISIBLE);
                   Log.i(TAG, "begin to show img from bitmap type's data");
                   imgPic.setImageBitmap(bitmap);
                   break;
               case 102:
                   hideAllWidget();
                   Log.i(TAG, "begin to show html contents");
                   scroll.setVisibility(View.VISIBLE);
                   Log.d(TAG, ">>>>>>htmlContents->\n" + htmlContents);
                   htmlTxt.setText(htmlContents);
                   break;
               case 103:
                   hideAllWidget();
                   Log.i(TAG, "begin to show html page in webview");
                   webView.setVisibility(View.VISIBLE);
                   Log.d(TAG, ">>>>>>htmlContents->\n" + htmlContents);
                   webView.loadDataWithBaseURL("", htmlContents, "text/html", "UTF-8", "");
                   break;
           }
           return false;
       }
   });
   /**
    * 使用okhttp 异步下载图片
    */
   private void downLoadImgFromPath(String path) {

OkHttpClient client = new OkHttpClient();

Request request = new Request.Builder()
               .url(path)
               .build();
       Log.i(TAG, ">>>>>>into doanloadImgFromPath method");
       try {
           Call call = client.newCall(request); // 使用client去请求

call.enqueue(new Callback() { // 回调方法,>>> 可以获得请求结果信息
               InputStream inputStream = null;

@Override
               public void onFailure(Call call, IOException e) {
                   Log.e(TAG, ">>>>>>下载失败", e);
               }

@Override
               public void onResponse(Call call, Response response) throws IOException {
                   Log.i(TAG, ">>>>>>into onResponse method");
                   try {
                       inputStream = response.body().byteStream();
                       Log.i(TAG, ">>>>>>the response code is: " + response.code());
                       if (200 == response.code()) {
                           bitmap = BitmapFactory.decodeStream(inputStream);
                           Log.i(TAG, ">>>>>>sendEmptyMessage 101 to handler");
                           httpHandler.sendEmptyMessage(101);
                       } else {
                           Log.i(TAG, ">>>>>>下载失败");
                       }
                   } catch (Exception e) {
                       Log.e(TAG, ">>>>>>okHttp onResponse error: " + e.getMessage(), e);
                   } finally {
                       try {
                           inputStream.close();
                       } catch (Exception e) {
                       }
                   }
               }
           });

} catch (Exception e) {
           Log.e(TAG, ">>>>>>OkHttp调用失败", e);
       }
   }

//异步不需要创建线程
   private void getHtmlAsync(String path, int handlerCode) {
       OkHttpClient client = new OkHttpClient();
       Request request = new Request.Builder().url(path).build();
       //请求的call对象
       Call call = client.newCall(request);
       //异步请求
       call.enqueue(new Callback() {

//失败的请求
           @Override
           public void onFailure(@NonNull Call call, @NonNull IOException e) {
               Log.e(TAG, ">>>>>>加载path失败", e);
           }

//结束的回调
           @Override
           public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
               //响应码可能是404也可能是200都会走这个方法
               Log.i(TAG, ">>>>>>the response code is: " + response.code());
               if (200 == response.code()) {
                   try {
                       ResponseBody responseBody = response.body();
                       BufferedSource source = responseBody.source();
                       source.request(Long.MAX_VALUE);
                       Buffer buffer = source.buffer();
                       Charset UTF8 = Charset.forName("UTF-8");
                       htmlContents = buffer.clone().readString(UTF8);
                       Log.i(TAG, ">>>>>>sendEmptyMessage " + handlerCode + " to handler");
                       httpHandler.sendEmptyMessage(handlerCode);
                       Log.i(TAG, "getAsyncHtmlGet成功");
                   } catch (Exception e) {
                       Log.e(TAG, ">>>>>>read htmlPage error: " + e.getMessage(), e);
                   }
               }
           }
       });
   }
}

核心代码导读

我们使用的是

Call call = client.newCall(request);

它本身就是支持异步的一个调用。 然后在得到相应的Http报文后使用一个Handler向APP主界面发起改变界面中内容的调用。

这边有一点需要注意的是OKHttp在返回的response.body()这个API,在一次请求里只能被使用一次。即如果你已经有以下一句类似的调用:

inputStream = response.body().byteStream();

你就不能再在它以下的语句中调用一次response.body()了。

自己动一下手试试看效果吧。

来源:https://blog.csdn.net/lifetragedy/article/details/128424733

标签:Android,OKHttp,网络
0
投稿

猜你喜欢

  • Java多线程产生死锁的必要条件

    2023-04-02 00:20:24
  • Spring Security中用JWT退出登录时遇到的坑

    2022-05-19 10:30:28
  • 解决springboot 部署到 weblogic 中 jar 包冲突的问题

    2021-06-06 11:32:36
  • 在C#项目中如何使用NHibernate详解

    2022-01-24 08:46:17
  • 利用Intellij Idea连接远程服务器实现远程上传部署功能

    2022-05-31 13:15:54
  • spring boot配置ssl实现HTTPS的方法

    2022-03-27 01:27:49
  • Java如何实现自定义异常类

    2023-06-21 23:44:01
  • android 大图片拖拽并缩放实现原理

    2022-11-10 05:59:55
  • Spring Security前后分离校验token的实现方法

    2023-06-26 17:00:30
  • Android中Button实现点击换图案及颜色

    2022-06-28 00:42:10
  • Java中Map遍历的九种方式汇总

    2023-05-02 21:57:27
  • Java锁擦除与锁粗化概念和使用详解

    2022-02-09 15:32:30
  • 微信公众号支付(一)如何获取用户openId

    2022-07-29 04:13:57
  • SpringMVC用JsonSerialize日期转换方法

    2021-12-06 10:59:59
  • 如何使用RequestHeaders添加自定义参数

    2023-01-10 17:37:14
  • Java WebService 简单实例(附实例代码)

    2023-01-25 07:52:18
  • Android编程使用AlarmManager设置闹钟的方法

    2023-12-11 18:37:42
  • IntelliJ IDEA 2020.2正式发布,两点多多总能助你提效

    2023-08-30 18:15:18
  • 从此不再惧怕URI编码 JavaScript及C# URI编码详解

    2022-11-03 00:17:46
  • 使用Stargate访问K8ssandra的过程之Springboot整合Cassandra

    2022-02-08 23:12:25
  • asp之家 软件编程 m.aspxhome.com