Android入门第55天-在Android里使用OKHttp组件访问网络资源

news2024/12/23 18:05:08

简介

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

下面就进入课程。

课程目标

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

  1. 使用OKHttp组件;
  2. 使用OKHttp组件加载网络图片显示在APP的ImgView里;
  3. 使用OKHttp组件加载给定网页代码显示在ScrollView里;
  4. 使用OKHttp组件加载给定网页显示在WebView里;

以上过程都为异步加载。

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

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

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

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

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

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

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

 加完后的AndroidManifest.xml长这样

 代码

菜单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()了。

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/111710.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

《北京市数字经济促进条例》图解来了

《北京市数字经济促进条例》 2023/1/1 二十大对建设数字经济作出重要部署。党的二十大报告中指出&#xff0c;“加快建设网络强国、数字中国”、“加快发展数字经济&#xff0c;促进数字经济和实体经济深度融合&#xff0c;打造具有国际竞争力的数字产业集群”。习总书记强调…

【算法】P1 算法简介

算法什么是算法正确与错误的算法算法可以解决什么问题本专栏有哪些算法什么是算法 算法 (Algorithm) 取某个值或集合作为 输入&#xff0c;并产生某个值或集合作为 输出。算法就是把输入转换为输出的计算&#xff0c;描述这个计算的过程来实现输入与输出的关系。 正确与错误的…

学习Elasticsearch这一篇就够了(2)

DSL查询文档 elasticsearch的查询依然是基于JSON风格的DSL来实现的。 DSL查询分类 Elasticsearch提供了基于JSON的DSL&#xff08;Domain Specific Language&#xff09;来定义查询。常见的查询类型包括&#xff1a; 查询所有&#xff1a;查询出所有数据&#xff0c;一般测试…

12_SpringMVC_拦截器

在之前学习JAVAWEB 的时候&#xff0c;我们学习了过滤器的知识。过滤器的作用是保护请求的服务器资源&#xff0c;在请求资源被执行之前&#xff0c;如果请求地址符合拦截范围&#xff0c;则会先执行过滤器。过滤器的执行时机&#xff0c;是在Servlet之前执行的。但是在使用了S…

Vue 3 技术揭秘

作者介绍 muwoo&#xff0c;前端技术专家。曾就职于蚂蚁集团&#xff0c;之前对 Vue 2.x 源码有过深层次的研究和探索&#xff0c;并在 Github 上开源了相关的技术文章&#xff1a;Vue 2.x 技术揭秘&#xff0c;目前已有超过 2k star 。 自 Vue 3 诞生以来&#xff0c;就一直关…

30 岁转行做程序员,晚了吗?

2019年&#xff0c;我从某大型国有企业正式辞职&#xff0c;告别了工作了6年的北锤小城。这时候&#xff0c;鄙人年芳30&#xff0c;曾经一批来这里奋斗的同事们&#xff0c;要么走上管理岗位、要么成家立业买房买车&#xff0c;他们是打算把一生奉献给这里的&#xff0c;然而也…

【Javascript基础】--零基础--超详细且简洁的Javascript笔记--Javascript基础知识(02)

Hello, world! 首先&#xff0c;让我们看看如何将脚本添加到网页上。 对于服务器端环境&#xff08;如 Node.js&#xff09;&#xff0c;你只需要使用诸如 "node my.js" 的命令行来执行它。 “script” 标签 比如&#xff1a; <!DOCTYPE HTML> <html>…

搭建Seata分布事务(基于Nacos注册+Mysql配置)

文章目录一&#xff1a;拉取Seata镜像二&#xff1a;运行Seata容器2.1. 容器内目录拷贝到宿主机2.2. 编辑 registry.conf 和 file.conf2. 2.1. 编辑注册中心相关文件2.2.2. 编辑Seata存储数据的相关配置文件2.3. 宿主机文件拷贝至容器内部三&#xff1a;Nacos注册中心相关配置操…

TikTok发布What‘s Next趋势报告,2023年有哪些增长机会?

获悉&#xff0c;近日TikTok for Business发布了《Whats Next 2023 TikTok 全球流行趋势报告》&#xff0c;帮助营销人员了解消费者的需求在来年将如何变化&#xff0c;以及这对他们在TikTok内外的策略将产生怎样的影响。这份报告将有趣与实用相结合&#xff0c;重点剖析了品牌…

阿里巴巴新产“Java架构核心宝典”,全是流行技术,限时开放

导言 什么是架构师&#xff1f;对于程序员来说&#xff0c;聊架构是一个永不过时的话题。实际上&#xff0c;每一家公司都有自己对架构师不同的定位&#xff0c;因为不同的公司&#xff0c;所处的阶段、业务模式以及应用场景都不一样&#xff0c;因此对架构师的要求不一样&…

直播带货不再独揽大旗,货架电商神秘崛起,链动2+1模式助力引流

​“WXG&#xff08;微信事业群&#xff09;最亮眼的业务是视频号&#xff0c;基本上是全场&#xff08;全公司&#xff09;的希望。”12月22日&#xff0c;在线上召开内部员工大会时&#xff0c;腾讯CEO马化腾再度把视频号推至C位。这句话昨天也一度冲上热搜。 马化腾在内部员…

后台Service限制

每次在后台运行时&#xff0c;应用都会消耗一部分有限的设备资源&#xff0c;例如 RAM。 这可能会影响用户体验&#xff0c;如果用户正在使用占用大量资源的应用&#xff08;例如玩游戏或观看视频&#xff09;&#xff0c;影响会尤为明显。 为了提升用户体验&#xff0c;Androi…

ESP8266-C开发-3串口下载固件失败方案

一、串口下载固件失败 以下是报错信息。 …………………………[2022-12-23 09:01:17,338][ESP8266Loader_spi[1]][espDownloader.pyo][line:351][ERROR]: Chip sync error: Failed to connect to ESP8266: Timed out waiting for packet header [2022-12-23 09:01:17,338][ESP…

Zookeeper 4 Zookeeper JavaAPI 操作 4.1 Curator 介绍 4.2 Curator API 常用操作【建立连接】

Zookeeper 【黑马程序员Zookeeper视频教程&#xff0c;快速入门zookeeper技术】 文章目录Zookeeper4 Zookeeper JavaAPI 操作4.1 Curator 介绍4.1.1 Curator 介绍4.2 Curator API 常用操作4.2.1 Curator API 常用操作4.2.2 建立连接4 Zookeeper JavaAPI 操作 4.1 Curator 介绍…

使用形态学处理相关算法对芯片电路图焊接锡点缺陷进行检测

up目录 一、理论基础 二、核心程序 三、测试结果 一、理论基础 当前我国信息科技的发展&#xff0c; 产业界自动化生产水平越来越高。 具体在电子产品行业&#xff0c; 随着精细化和自动化的发展&#xff0c; 电子产品的焊点质量的好坏&#xff0c; 深刻地影响着产品成品的质…

Unity下如何实现RTMP或RTSP流播放和录制

技术背景 在探讨Unity平台RTMP或RTSP直播流数据播放和录制之前&#xff0c;我们先简单回顾下RTSP或RTMP直播流数据在Unity平台的播放流程&#xff1a; 通过Native RTSP或RTSP直播播放SDK回调RGB/YUV420/NV12等其中的一种未压缩的图像格式&#xff1b;Unity下创建相应的RGB/YU…

工作几年后想转行学编程,如何操作才靠谱?

30岁转行来得及么&#xff1f;继结婚、生子、就业、买房后&#xff0c;又一个对30岁的灵魂拷问来了。 在一档综艺节目里&#xff0c;有位年过30的“实习生”为了能让孩子有更好的生活条件、也为了自己的事业与发展&#xff0c;她选择在而立之年放下自己曾经所擅长的&#xff0c…

微信键盘终于正式发布,张小龙说:其目的并不是为了抢夺输入法市场

自从2021年1月份&#xff0c;张小龙在微信公开课透露&#xff1a;微信将上线属于自己的专属输入法&#xff0c;到现在已经快2年过了。 今天终于正式发布了&#xff0c;下面我们一起来体验下。 1、安装 打开App Store&#xff0c;输入“微信键盘”&#xff0c;点击获取就可以…

刷爆力扣之字符串中的单词数

刷爆力扣之字符串中的单词数 HELLO&#xff0c;各位看官大大好&#xff0c;我是阿呆 &#x1f648;&#x1f648;&#x1f648; 今天阿呆继续记录下力扣刷题过程&#xff0c;收录在专栏算法中 &#x1f61c;&#x1f61c;&#x1f61c; 该专栏按照不同类别标签进行刷题&#…

STATIC和静态分析的必要性

​有一款正常工作的软件。那么可以说正常工作的软件都是好软件吗&#xff1f;在漫威的《黑豹》电影中有一个场景我深深地看过。 <图 1> 电影《黑豹》的场景 就算做的好&#xff0c;也有进步的空间! 我认为好的软件也是如此。 即使它可以工作并且没有问题&#xff0c;但总…