Android应用:实现网络加载商品数据【OKHttp、Glide、Gson】

实现网络加载商品数据的功能:

1、在AndroidManifest.xml中声明网络权限;

2、在app/build.gradle中添加okhttp, glide, gson等必需的第3方库;

3、在MainActivity中通过OkHttpClient连接给定的Web服务,获取商品数据;对应的json数据为本地的json文件,名字为goods_list_data.json;数据内容为:[
{“id”:1,“count”:“5.4万”,“goodsName”:“富士拍立得相机”,“goodsPic”:“/img/polaroid.png”},
{“id”:2,“count”:“5.3万”,“goodsName”:“格兰仕微波炉”,“goodsPic”:“/img/microwave_oven.png”},
{“id”:3,“count”:“1.4万”,“goodsName”:“新国标电动车”,“goodsPic”:“/img/electric_vehicle.png”},
{“id”:4,“count”:“1.6万”,“goodsName”:“官方订制投影仪”,“goodsPic”:“/img/projector.png”},
{“id”:5,“count”:“0.4万”,“goodsName”:“美的35L烤箱”,“goodsPic”:“/img/oven.png”},
{“id”:6,“count”:“3.3万”,“goodsName”:“儿童学习桌”,“goodsPic”:“/img/learning_table.png”}
]
对应的图片也存储在本地的img文件中

4、使用gson库解析JSON格式的商品数据,转成java bean商品数据对象(Goods类)的列表;

5、创建MsgHandler类,用于异步更新商品列表;

6、在GoodsAdapter中通过glide控件加载并显示网络图片。


1.部署网络图片资源

首先,我们需要将对应的文件部署在一个简易的服务器(Tomcat)中,服务器中存放数据的目录结构如下图所示

E:.
├─goods
│  └─img
│  └─goods_list_data.json
└─WEB-INF

其中,ROOT目录在"apache-tomcat-9.0.65-windows-x64\webapps\ROOT"下,表示Tomcat服务器的根目录。

  • goods文件夹存放的是商品列表所用到的数据
  • 其中goods\img文件夹存放的是商品的图片资源
  • goods_list_data.json文件存放的是商品列表的数据,具体如下所示
[
  {"id":1,"count":"5.4万","goodsName":"富士拍立得相机","goodsPic":"/img/polaroid.png"},
  {"id":2,"count":"5.3万","goodsName":"格兰仕微波炉","goodsPic":"/img/microwave_oven.png"},
  {"id":3,"count":"1.4万","goodsName":"新国标电动车","goodsPic":"/img/electric_vehicle.png"},
  {"id":4,"count":"1.6万","goodsName":"官方订制投影仪","goodsPic":"/img/projector.png"},
  {"id":5,"count":"0.4万","goodsName":"美的35L烤箱","goodsPic":"/img/oven.png"},
  {"id":6,"count":"3.3万","goodsName":"儿童学习桌","goodsPic":"/img/learning_table.png"}
]

启动tomcat后,可访问http://localhost:8080/goods/goods_list_data.json展示信息
在这里插入图片描述

2.创建项目

  1. 打开Android Studio,并创建一个新的Android项目。
  2. 命名项目并选择适当的目标API级别和设备类型。
  3. 创建一个新的空白活动(Empty Activity)。

3.在AndroidManifest.xml中声明网络权限

在 AndroidManifest.xml 文件中添加以下权限声明,以便应用可以访问网络:

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

在这里插入图片描述由于网络安全策略导致的问题,即不允许在明文(非加密)的情况下与 localhost 进行通信。这通常涉及到网络安全配置,特别是在 Android 9.0(API级别28)及更高版本中引入了更严格的网络安全策略;因此我们还需要进行配置网络安全配置文件

解决此问题的方法之一是使用 HTTPS 协议而不是 HTTP,因为 HTTPS 是加密的。

如果在本地测试应用,可以使用 Android 的网络安全配置文件来允许明文通信。

  1. res/xml 文件夹中创建一个名为 network_security_config.xml 的网络安全配置文件。如果该文件夹不存在,请手动创建。
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <base-config cleartextTrafficPermitted="true">
        <trust-anchors>
            <certificates src="system" />
            <certificates src="user" />
        </trust-anchors>
    </base-config>
</network-security-config>

在这里插入图片描述

  1. AndroidManifest.xml 文件中,将这个网络安全配置文件应用于你的应用。在 <application> 元素内添加 android:networkSecurityConfig 属性,如下所示:
<application
    android:networkSecurityConfig="@xml/network_security_config"
    <!-- 其他属性和元素 -->
    >
    <!-- 其他元素 -->
</application>

在这里插入图片描述

这将允许你的应用在本地开发和测试过程中与 localhost 进行明文通信。但请注意,在生产环境中,强烈建议使用 HTTPS 以确保数据的安全传输。

如果你使用的是模拟器或真机设备,请确保重新构建和部署应用,以使配置生效。此外,如果你的服务器正在本地运行,请确保服务器端口和地址正确。

4.添加依赖库

app/build.gradle文件中添加OkHttp、Glide、Gson依赖库。

    implementation("com.squareup.okhttp3:okhttp:4.9.1")
    implementation("com.squareup.okhttp3:logging-interceptor:4.9.1")
    implementation("com.google.code.gson:gson:2.8.8")
    implementation("com.github.bumptech.glide:glide:4.12.0")
    annotationProcessor("com.github.bumptech.glide:compiler:4.12.0")

在这里插入图片描述

进行同步
在这里插入图片描述
等待安装依赖……

5.创建一个XML布局文件

res/layout文件夹中创建一个布局文件,例如activity_main.xml,用于显示商品数据。

<?xml version="1.0" encoding="utf-8"?>
<androidx.recyclerview.widget.RecyclerView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/recyclerView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"/>

在这里插入图片描述
创建一个XML布局文件用于显示商品项
res/layout文件夹中创建一个布局文件,例如item_goods.xml,用于显示每个商品项。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="16dp">

    <ImageView
        android:id="@+id/goodsImageView"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:scaleType="centerCrop" />

    <TextView
        android:id="@+id/goodsNameTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp" />
</LinearLayout>

在这里插入图片描述

6.创建一个Java Bean类

创建一个Goods类,用于表示商品数据。

public class Goods {
    private int id;
    private String count;
    private String goodsName;
    private String goodsPic;

    // Getters and setters
}

7.创建一个适配器类

创建一个自定义适配器类GoodsAdapter,用于将商品数据绑定到RecyclerView中。

public class GoodsAdapter extends RecyclerView.Adapter<GoodsAdapter.ViewHolder> {
    private List<Goods> goodsList;
    private Context context;

    public GoodsAdapter(Context context, List<Goods> goodsList) {
        this.context = context;
        this.goodsList = goodsList;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_goods, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        Goods goods = goodsList.get(position);
        holder.goodsNameTextView.setText(goods.getGoodsName());

        // Load and display image using Glide
        Glide.with(context)
            .load(goods.getGoodsPic())
            .into(holder.goodsImageView);
    }
    @Override
    public int getItemCount() {
        if (goodsList != null) {
            return goodsList.size();
        } else {
            return 0; // 返回0表示没有数据
        }
    }

    static class ViewHolder extends RecyclerView.ViewHolder {
        TextView goodsNameTextView;
        ImageView goodsImageView;

        ViewHolder(View itemView) {
            super(itemView);
            goodsNameTextView = itemView.findViewById(R.id.goodsNameTextView);
            goodsImageView = itemView.findViewById(R.id.goodsImageView);
        }
    }
}

8.实现网络加载数据

MainActivity.java中实现网络加载商品数据的功能。请确保你的goods_list_data.json文件位于app/src/main/assets文件夹下。

package com.leo.network;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.google.gson.Gson;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class MainActivity extends AppCompatActivity {

    private RecyclerView recyclerView;
    private GoodsAdapter adapter;
    private List<Goods> goodsList;

    private static final int MSG_UPDATE_DATA = 1;
    private Handler msgHandler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            if (msg.what == MSG_UPDATE_DATA) {
                adapter.notifyDataSetChanged();
            }
            return true;
        }
    });

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

        recyclerView = findViewById(R.id.recyclerView);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        adapter = new GoodsAdapter(this, goodsList);
        recyclerView.setAdapter(adapter);

        // Fetch data from the network
        fetchGoodsData();
    }

    private void fetchGoodsData() {

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    OkHttpClient client = new OkHttpClient();
                    Request request = new Request.Builder()
                            .url("http://10.0.2.2:8080/goods/goods_list_data.json")
                            .build();
                    Response response = client.newCall(request).execute();
                    if (response.isSuccessful()) {
                        String jsonData = response.body().string();
                        Log.d("Network", "Data fetched successfully: " + jsonData);

                        Gson gson = new Gson();
                        Goods[] goodsArray = gson.fromJson(jsonData, Goods[].class);

                        // 补全图片URL
                        for (Goods goods : goodsArray) {
                            goods.setGoodsPic("http://10.0.2.2:8080//goods" + goods.getGoodsPic());
                        }

                        goodsList = Arrays.asList(goodsArray);
                        msgHandler.sendEmptyMessage(MSG_UPDATE_DATA);

                        // 切换到主线程以更新UI
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                // 设置RecyclerView的适配器
                                adapter = new GoodsAdapter(MainActivity.this, goodsList);
                                recyclerView.setAdapter(adapter);
                            }
                        });

                    }
                } catch (IOException e) {
                    e.printStackTrace();
                    Log.e("Network", "Error fetching data: " + e.getMessage());
                }
            }
        }).start();
    }
}


替换"URL_TO_YOUR_JSON_DATA"为你的本地JSON文件的路径,例如:http://localhost:8080/goods/goods_list_data.json

注意,如果你是本地部署的tomcat,需要在Android默认的虚拟器中访问,需要改为“10.0.2.2

以下是对代码的一些说明:

  1. fetchGoodsData() 方法中创建了一个新的线程来执行网络请求。这是一个良好的实践,因为它确保网络请求不会阻塞主线程,以避免应用的响应性问题。

  2. 在网络请求成功后使用 Gson 库将 JSON 数据解析为 Goods 对象的数组,并补全了图片的URL。这确保了 Glide 能够正确加载图片。

  3. 使用 Handler 来更新UI,因为 UI更新必须在主线程中执行

  4. 在网络请求失败时,通过 Log.e 打印了错误消息,这有助于调试和问题排查。

实现效果
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

RISC-V IDE MRS无感远程协助模块详解

RISC-V IDE MRS无感远程协助模块详解 一、说明 1.1 概述 针对RISC-V/ARM等内核MCU的嵌入式集成开发环境MRS(MounRiver Studio)从V1.90版本开始内置无感远程协助模块&#xff08;Sensorless Remote Assistant Module&#xff0c;以下简称SRA模块&#xff09;。SRA模块是一款支…

Leetcode刷题详解——按摩师

1. 题目链接&#xff1a;面试题 17.16. 按摩师 2. 题目描述&#xff1a; 一个有名的按摩师会收到源源不断的预约请求&#xff0c;每个预约都可以选择接或不接。在每次预约服务之间要有休息时间&#xff0c;因此她不能接受相邻的预约。给定一个预约请求序列&#xff0c;替按摩师…

无线渗透|Wi-Fi渗透思路

对于WPA2 WPA3的一些渗透思路 0x00 进行渗透时需知晓的基础知识 1.WPA2:是WPA的升级版&#xff0c;是针对保护无线网络安全而设计的无线网络保护系统&#xff0c;引入了PSK&#xff08;预共享密钥模式&#xff09;秘钥&#xff0c;加强了WPA的不足之处&#xff0c;但是因为使…

技术栈 业务架构 插件库

大前端 技术栈 业务架构 插件库

yolov5 pt转成nccn_yolov5

一&#xff1a;转换环境准备 python版本为Python 3.8.0&#xff0c;需要安装对应的版本包&#xff0c;torch1.10.0 torchvision0.11.0 torchaudio0.10.0 pip3 install torch1.10.0 torchvision0.11.0 torchaudio0.10.0 -f https://download.pytorch.org/whl/torch_stable.html…

yum 命令

基本语法 yum [选项] [参数] 选项说明 -y 对所有提问都回答“yes” 参数说明 实操 yum list | grep firefox yum -y remove firefox yum -y install firefox

前端打印表格功能+单号生成条形码

第一种打印方法&#xff1a;不需要下载任何插件 浏览器自带打印功能&#xff08;不太推荐&#xff09;&#xff0c;原理是生成新的页面后被打印&#xff0c;当打印完成或者取消打印时&#xff0c;页面需要强制刷新&#xff0c;否则页面无法回显。 //打印功能 print() {var pr…

【EI会议征稿】第三届结构抗震与监测检测国际学术会议(SSRMD 2024)

第三届结构抗震与监测检测国际学术会议&#xff08;SSRMD 2024&#xff09; 2024 3rd International Conference on Structural Seismic Resistance, Monitoring and Detection 随着城市化进程的深入&#xff0c;城市中的建筑越来越多。建筑也逐渐多样化&#xff0c;复杂化。…

项目文章 | CUTTag助力解析水稻白叶枯病菌Sigma因子70 RpoD的致病作用

发表单位&#xff1a;南京农业大学和江苏省农业科学院植物保护研究所 期 刊&#xff1a;Journal of Integrative Agriculture&#xff08;IF:4.8&#xff09; 发表日期&#xff1a;2023年10月18日 2023年南京农业大学和江苏省农业科学院植物保护研究所研究团队在期刊Jo…

postgresql的windows

1. 资源下载&#xff1a; https://www.postgresql.org/download/windows/ 2. 安装 双击&#xff0c;指定D盘目录&#xff0c;接下来默认安装&#xff0c;一直到出现下面的最后一步。一定要去除勾选复选框。 在最后&#xff0c;点击FINISH。 3. 初始化 4. 检查和修改配置 1&am…

倾斜摄影三维模型的顶层合并构建重要性分析

倾斜摄影三维模型的顶层合并构建重要性分析 倾斜摄影超大场景的三维模型的顶层合并对于构建精确、完整且真实的三维模型具有重要的意义和应用价值。本文将从几个方面对其重要性进行浅析。 一、模型完整性与连贯性 倾斜摄影超大场景的三维模型的顶层合并可以将多个倾斜摄影数据…

从0到1之微信小程序快速入门(03)

目录 什么是生命周期函数 WXS脚本 ​编辑 与 JavaScript 不同 纯数据字段 组件生命周期 定义生命周期方法 代码示例 组件所在页面的生命周期 代码示例 插槽 什么是插槽 启用多插槽 ​编辑 定义多插槽 组件通信 组件间通信 监听事件 触发事件 获取组件实例 自…

winodws10系统C盘文件夹目录讲解

背景&#xff1a; 电脑安装系统一段时间后&#xff0c;发现C盘的空间越来越小&#xff0c;于是乎&#xff0c;想了解一下C盘文件目录结构&#xff0c;删除一下非必要的文件&#xff0c;同时增强一些操作系统的知识。 目前我的C盘目录如下&#xff1a; 如果开启显示隐藏文件&…

Ubuntu中使用yum命令出现错误提示:Command ‘yum‘ not found, did you mean:

Ubuntu中使用yum命令出现错误提示:Command ‘yum’ not found, did you mean: command ‘gum’ from snap gum (0.12.0) command ‘num’ from deb quickcal (2.4-1) command ‘yum4’ from deb nextgen-yum4 (4.5.2-6) command ‘uum’ from deb freewnn-jserver (1.1.1~a021…

在CentOS上用yum方式安装MySQL8过程记录

此文参考官方文档一步一步记录安装到正常运行全过程 安装环境&#xff1a;centos7 mysql版本&#xff1a;8.0.35 安装过程主要参考下面两边文章&#xff1a; 1.官方文档 https://dev.mysql.com/doc/refman/8.0/en/linux-installation-yum-repo.html 2.linux yum安装mysql8 安…

Anaconda下载安装以及环境变量的配置

一、下载安装anaconda 可以在官网下载&#xff1a;Anaconda | The World’s Most Popular Data Science Platform 也直接用清华源镜像进行下载&#xff1a;Index of /anaconda/archive/ | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror 按照需要选则自己需要的版本…

如何在十亿级别用户中检查用户名是否存在?

不知道大家有没有留意过&#xff0c;在使用一些app注册的时候&#xff0c;提示你用户名已经被占用了&#xff0c;需要更换一个&#xff0c;这是如何实现的呢&#xff1f;你可能想这不是很简单吗&#xff0c;去数据库里查一下有没有不就行了吗&#xff0c;那么假如用户数量很多&…

损失函数总结(十):TripletMarginLoss、TripletMarginWithDistanceLoss

损失函数总结&#xff08;十&#xff09;&#xff1a;TripletMarginLoss、TripletMarginWithDistanceLoss 1 引言2 损失函数2.1 TripletMarginLoss2.2 TripletMarginWithDistanceLoss 3 总结 1 引言 在前面的文章中已经介绍了介绍了一系列损失函数 (L1Loss、MSELoss、BCELoss、…

SpringBoot集成与应用Neo4j

文章目录 前言集成使用定义实体配置定义Repository查询方法方式一&#xff1a;Query方式二&#xff1a;Cypher语法构建器方式三&#xff1a;Example条件构建器方式四&#xff1a;DSL语法 自定义方法自定义接口继承自定义接口实现自定义接口neo4jTemplateNeo4jClient 自定义抽象…