Android Studio实现解析HTML获取json,解析json图片URL,将URL存到list,进行瀑布流展示

news2025/1/14 2:29:16

目录

        • 效果
        • build.gradle(app)添加的依赖(用不上的可以不加)
        • AndroidManifest.xml
        • 错误
        • activity_main.xml
        • item_image.xml
        • MainActivity
        • Image适配器
        • ImageModel 接收图片URL

效果

在这里插入图片描述

build.gradle(app)添加的依赖(用不上的可以不加)

dependencies {
    implementation 'com.squareup.picasso:picasso:2.71828'
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.airbnb.android:lottie:3.0.3'
    implementation 'com.facebook.fresco:fresco:0.9.0+'
    implementation 'org.jsoup:jsoup:1.14.1'
    implementation 'com.squareup.okhttp3:okhttp:4.9.1'
    implementation 'com.github.bumptech.glide:glide:4.12.0'
    annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
    implementation 'com.readystatesoftware.sqliteasset:sqliteassethelper:+'
    implementation 'androidx.sqlite:sqlite:2.2.0'
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.google.code.gson:gson:2.8.9'
    implementation 'com.alibaba:fastjson:1.2.67'
    implementation("com.squareup.okhttp3:okhttp:4.10.0")
    }

AndroidManifest.xml

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
 <application
  android:usesCleartextTraffic="true">

错误

如果出现错误:app:checkDebugDuplicateClasses
参考这篇博客尝试解决

activity_main.xml

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

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</RelativeLayout>

item_image.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="5dp">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:scaleType="centerCrop"
        android:adjustViewBounds="true" />

</LinearLayout>

MainActivity

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
import android.os.Bundle;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class MainActivity extends AppCompatActivity {
    private RecyclerView mRecyclerView;
    private ImageAdapter mImageAdapter;
    public String html = "https://2k317b5009.goho.co/images/List?type=breakfast";
    private List<ImageModel> mImageUrlsList = new ArrayList<>();

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

        //使用单线程的线程池来异步执行 callable 对象中的任务,并在任务执行完成后获取结果并显示图片和进行其他操作
        //使用 ExecutorService 来执行一个 Callable 对象,并获取它的返回结果
        //创建一个单线程的线程池,用于执行任务
        ExecutorService executor = Executors.newSingleThreadExecutor();

        //将 callable 对象提交给线程池进行执行,并返回一个 Future 对象,该对象可以用于获取任务的执行结果
        Future<List<ImageModel>> future = executor.submit(callable);

        try {
            //通过调用 future.get() 方法来阻塞主线程,直到任务执行完成并返回结果。在这里,我们将返回的结果赋值给 imageUrls 变量
            List<ImageModel> imageUrls = future.get();

            //将获取到的图片列表传递给 showImages 方法,以显示图片和后续操作
            showImages(imageUrls);
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            executor.shutdown();
        }
    }

    private void showImages(List<ImageModel> imageUrls) {
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        mRecyclerView.setLayoutManager(layoutManager);
        mRecyclerView = findViewById(R.id.recyclerView);

        //通过设置RecyclerView的布局管理器为StaggeredGridLayoutManager,并指定每行或每列的单元格数量和布局方向,就可以实现错乱瀑布流的效果
        //spanCount:指定每行或每列的单元格数量。在这个例子中,设置为2,表示每行有两个单元格。
        //orientation:指定布局的方向,VERTICAL表示垂直
        mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL));

        //自定义的适配器类 将数据绑定到RecyclerView中的每个列表项上
        ImageAdapter adapter = new ImageAdapter(imageUrls, this);

        //调用RecyclerView的setAdapter()方法,将适配器与RecyclerView关联
        mRecyclerView.setAdapter(adapter);
    }

    /**
     * 使用 java.util.concurrent 包来执行并发任务,可以通过创建 ExecutorService 和 Future 对象来实现
     * 在 onCreate() 方法中,我们创建了一个单线程的 ExecutorService,然后通过 submit() 方法将 HtmlParserTask 提交给线程池进行执行。
     * 接着,我们使用 future.get() 来获取并发任务的结果,并调用 showImages() 方法来展示图片
     */
    Callable<List<ImageModel>> callable = new Callable<List<ImageModel>>() {
        @Override
        public List<ImageModel> call() throws Exception {
            List<ImageModel> imageModels = new ArrayList<>();
            // 解析 HTML 获取图片 URL 的逻辑
            Document document = Jsoup.connect(html).get();

            //使用 Jsoup 连接到给定的 HTML 页面,并使用 body().text() 方法获取页面的纯文本内容
            String jsonString = document.body().text();

            //转换成object
            JSONObject jsonObject = new JSONObject(jsonString);

            //从jsonObject里面找一个ImageList的对象
            JSONArray jsonArray = jsonObject.getJSONArray("ImageList");
            String imageUrl = null;
            //开始遍历
            for (int i = 0; i < jsonArray.length(); i++) {
                //遍历ImageList里面的每个对象
                JSONObject item = jsonArray.getJSONObject(i);

                // 检查是否存在 "src" 键
                if (item.has("src")) {
                    imageUrl = item.getString("src");
                    //Log.e(TAG,imageUrl);
                    imageModels.add(new ImageModel(imageUrl));
                }

            }

            return imageModels;
        }

    };
}

Image适配器

import static android.content.ContentValues.TAG;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.squareup.picasso.Picasso;
import java.util.List;
import java.util.Random;

//适配器类
public class ImageAdapter extends RecyclerView.Adapter<ImageAdapter.ImageViewHolder> {
    private List<ImageModel> imageList;
    private Context context;

    //有参构造
    public ImageAdapter(List<ImageModel> imageList, Context context) {

        Log.e(TAG, "ImageAdapter thread id= "+ Thread.currentThread().getId() + " name="+Thread.currentThread().getName());

        this.imageList = imageList;
        this.context = context;
    }

    //onCreateViewHolder() 方法用于创建RecyclerView的每个列表项的视图
    @NonNull
    @Override
    public ImageViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(context).inflate(R.layout.item_image, parent, false);
        return new ImageViewHolder(view);
    }


    //onBindViewHolder() 方法用于将数据绑定到ViewHolder中的视图
    @Override
    public void onBindViewHolder(@NonNull ImageViewHolder holder, int position) {
        ImageModel imageModel = imageList.get(position);//获取特定位置的图像模型(ImageModel)对象,并从中获取图像URL
        String imageUrl = imageModel.getImageUrl();

        //使用Picasso库加载图像URL并显示在ViewHolder的ImageView
        Picasso.get()
                .load(imageUrl)
                .fit()
                .centerCrop()
                .into(holder.imageView);

        // 设置图片的高度为随机高度,以实现错乱瀑布流效果
        ViewGroup.LayoutParams layoutParams = holder.imageView.getLayoutParams();
        layoutParams.height = getRandomHeight();//随机高度
        holder.imageView.setLayoutParams(layoutParams);
    }

    // 获取随机高度
    private int getRandomHeight() {
        Random random = new Random();
        return random.nextInt(400) + 300; // 设置图片高度范围为300-700之间的随机值
    }

    //返回图像列表的大小,即列表中包含的图像数量
    @Override
    public int getItemCount() {
        return imageList.size();
    }

    //设置适配器的图像列表
    public void setImageList(List<ImageModel> imageList) {
        this.imageList = imageList;
    }

    public class ImageViewHolder extends RecyclerView.ViewHolder {
        ImageView imageView;

        //持有每个列表项的视图组件,这里是一个ImageView
        public ImageViewHolder(@NonNull View itemView) {
            super(itemView);
            imageView = itemView.findViewById(R.id.imageView);
        }
    }
}

ImageModel 接收图片URL

//接收图片url
public class ImageModel {
    private String imageUrl;

    public ImageModel(String imageUrl) {
        this.imageUrl = imageUrl;
    }

    public void setImageUrl(String imageUrl) {
        this.imageUrl = imageUrl;
    }

    public String getImageUrl() {
        return imageUrl;
    }
}


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

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

相关文章

STM32 printf函数

printf函数输出流程 用户调用printf()函数到C标准库调用printf函数相关部分&#xff0c;printf函数由编译器提供的stdio.h解析。包含在usart.h文件中。fputc()最终实现输出。用户需要根据最终输出的硬件重新定义该函数&#xff0c;此过程为&#xff1a;printf重定向。 printf的…

用它来画文档插图简直太方便了

支持常用的12864接口&#xff0c;图像可保存&#xff0c;鼠标左键可delete键删除选区&#xff0c;鼠标右键抓取坐标。 支持快捷撤销操作CtrlZ、回退操作CtrlY&#xff0c;可点击此处下载软件。

Educational Codeforces Round 153 (Rated for Div. 2)ABC

Educational Codeforces Round 153 (Rated for Div. 2) 目录 A. Not a Substring题目大意思路核心代码 B. Fancy Coins题目大意思想核心代码 C. Game on Permutation题目大意思想核心代码 A. Not a Substring 题目大意 给定一个只包含“&#xff08;”和“&#xff09;”这两…

EV PV AC SPI CPI TCPI

SPI EV / PV CPI EV / ACCPI 1.25 SPI 0.8 PV 10 000 BAC 100 000EV PV * SPI 10 000 * 0.8 8000 AC EV / CPI 8000 / 1.25 6400TCPI (BAC - EV) / (BAC -AC) (100 000 - 8 000) / (100 000 - 6 400) 92 000 / 93 600 0.98290598

Python土力学与基础工程计算.PDF-钻探泥浆制备

Python 求解代码如下&#xff1a; 1. rho1 2.5 # 黏土密度&#xff0c;单位&#xff1a;t/m 2. rho2 1.0 # 泥浆密度&#xff0c;单位&#xff1a;t/m 3. rho3 1.0 # 水的密度&#xff0c;单位&#xff1a;t/m 4. V 1.0 # 泥浆容积&#xff0c;单位&#xff1a;…

画质提升+带宽优化,小红书音视频团队端云结合超分落地实践

随着视频业务和短视频播放规模不断增长&#xff0c;小红书一直致力于研究&#xff1a;如何在保证提升用户体验质量的同时降低视频带宽成本&#xff1f; 在近日结束的音视频技术大会「LiveVideoStackCon 2023」上海站中&#xff0c;小红书音视频架构视频图像处理算法负责人剑寒向…

OpenAI 选择这家成立2年的8人团队做什么?

当地时间 8 月 16 日&#xff0c;OpenAI 发布公告称收购了 Global Illumination 的团队&#xff0c;此笔交易更成为 OpenAI 自 2015 年成立以来首次对外收购&#xff0c;但并未公开交易涉及金额。据悉&#xff0c;该团队将参与 OpenAI 核心产品产品的研发&#xff0c;包括 Chat…

第八章:联邦学习在金融保险领域的应用案例

8.1 概述 联邦学习作为一种保障数据安全的建模方法&#xff0c;在保险、金融等行业中的应用前景十分广泛&#xff0c;因为这类行业昔谝受到更为严格的监管和隐私保护法律法规的约束&#xff0c;跨部门或者跨枧构之间的数据&#xff0c;无法被直接共卓进行机器学习模型训练。因…

Go download

https://go.dev/dl/https://golang.google.cn/dl/

贝锐蒲公英助力电子公交站牌联网远程运维,打造智慧出行新趋势

在现代城市公共交通系统中&#xff0c;我们随处可见电子公交站牌的身影。作为公共交通服务的核心之一&#xff0c;电子公交站牌的稳定运行至关重要&#xff0c;公交站台的实时公交状况、公共广告信息&#xff0c;是市民候车时关注的焦点。 某交通科技公司在承接某市智能电子站牌…

Fluent-MyBatis

Fluent-MyBatis Fluent-MyBatis 简介 何为 Fluent Mybatis&#xff1f; Fluent Mybatis, 是一款 Mybatis 语法增强框架, 综合了 Mybatis Plus, Dynamic SQL, JPA 等框架特性和优点 Fluent-MyBatis 开源地址 Fluent-MyBatis 原理 Fluent-MyBatis 原理是利用 annotation pro…

商城-学习整理-高级-商城业务-商品上架es(十)

目录 一、商品上架1、sku在ES中存储模型分析2、nested数据类型场景3、构造基本数据&#xff08;商品上架&#xff09; 二、首页1、项目介绍2、整合thymeleaf&#xff08;spring-boot下模板引擎&#xff09;渲染页面3、页面修改不重启服务器实时更新4、渲染二级三级数据 三、搭建…

HCIP---路由策略

文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 前言 前文我们初步了解了重发布技术的技术的工作流程及配置方法&#xff0c;在解决路由回馈问题的同时&#xff0c;路由回馈&#xff0c;选路不佳问题仍然没有得到有效解决&#xff0c;接下来通…

HCIA---ARP协议

文章目录 目录 前言 一.ARP协议简介 二.ARP协议工作原理 交换机转发原理&#xff1a; 泛洪&#xff1a; 总结 前言 我们知道在OSI七层参考模型中&#xff0c;TCP/UDP协议作用于传输层可以用来在设备之间建立连接&#xff0c;而在连接建立的过程中&#xff0c;设备之间是如何…

基于CNN卷积神经网络的口罩检测识别系统matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 ............................................................ % 循环处理每张输入图像 for…

【实现Element表单区间输入框】

思路&#xff1a;两个输入框组合而成的&#xff0c;绑定的是数组的第一项和第二项、搭配自定义正则从而实现的区间输入框 效果 核心代码 页面部分传递给组件的数据上部分核心之外还需给组件一个默认值dataform: {interval: [],}, interval数组的第一项绑定的第一个区间&#…

selenium中处理验证码问题

验证码 基本作用&#xff1a;可以实现当前访问页面的数据安全性、还可以减少用户的并发数&#xff1b; 类型&#xff1a;1、纯数字、纯字母&#xff1b;2、汉字组合&#xff1b;3、数学运算题&#xff1b;4、滑动&#xff1b;5、图片&#xff08;选不同的、选相同、成语顺序&…

SpringBoot + Vue 前后端分离项目 微人事(九)

职位管理后端接口设计 在controller包里面新建system包&#xff0c;再在system包里面新建basic包&#xff0c;再在basic包里面创建PositionController类&#xff0c;在定义PositionController类的接口的时候&#xff0c;一定要与数据库的menu中的url地址到一致&#xff0c;不然…

剑指 Offer 40. 最小的k个数(C+实现)

剑指 Offer 40. 最小的k个数https://leetcode.cn/problems/zui-xiao-de-kge-shu-lcof/ 法1&#xff1a;二叉堆 通过最小堆&#xff0c;直接筛选出最小的k个数 vector<int> getLeastNumbers(vector<int>& arr, int k) {priority_queue<int, vector<int>…

深信服 SG上网优化管理系统 catjs.php 任意文件读取漏洞[2023-HW]

深信服 SG上网优化管理系统 catjs.php 任意文件读取漏洞 一、漏洞描述二、漏洞影响三、网络测绘四、漏洞复现小龙POC检测: 五、 修复建议 免责声明&#xff1a;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间…