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

目录

效果

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

java 复制代码
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

java 复制代码
<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" />
java 复制代码
 <application
  android:usesCleartextTraffic="true">

错误

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

activity_main.xml

java 复制代码
<?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

java 复制代码
<?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

java 复制代码
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适配器

java 复制代码
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

java 复制代码
//接收图片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;
    }
}
相关推荐
爱上好庆祝5 小时前
学习js的第五天
前端·css·学习·html·css3·js
前端老石人6 小时前
前端开发中的 URL 完全指南
开发语言·前端·javascript·css·html
jingqingdai38 小时前
别用正则格式化 HTML!我用 DOM 遍历实现零风险本地格式化,老项目重构效率直接拉满
前端·重构·html
a1117769 小时前
“像风之翼“无人机巡检平台仪表盘
前端·javascript·开源·html·无人机
a11177610 小时前
QQ 宠物(怀旧 开源)前端electron项目
前端·开源·html
ZC跨境爬虫10 小时前
跟着 MDN 学 HTML day_8:(高级文本语义标签+适配核心功底)
前端·css·笔记·ui·html
Dxy123931021610 小时前
HTML中的伪类详解:从基础到高级应用的全面指南
前端·html
Dxy123931021610 小时前
HTML中如何设置元素样式:从基础到进阶的完整指南
前端·html
DFT计算杂谈1 天前
VASP官方教程 TRIQS DFT+DMFT计算教程
运维·css·自动化·html·css3
We་ct1 天前
React 性能优化精讲
前端·javascript·react.js·性能优化·前端框架·html·浏览器