当前位置: 首页 > news >正文

【Android】模糊搜索与数据处理

【Android】模糊搜索与数据处理

本篇博客主要以根据输入内容动态获取城市为例进行讲解。

获取城市

这一部分主要是根据输入的信息去动态获取城市信息

首先定义了一个名为 NetUtil 的类,主要用于通过 HTTP 请求获取城市信息。

public class NetUtil {private static final String URL_CITY_DAY = "https://geoapi.qweather.com/v2/city/lookup?";private static final String API_KEY = "";public static String doGet(String urlStr) throws IOException {String result = "";try {OkHttpClient client = new OkHttpClient();Request request = new Request.Builder().url(urlStr).build();Response response = client.newCall(request).execute();result = response.body().string();} catch (IOException e) {throw new RuntimeException(e);} finally {return result;}}public static String getCitys(String name) throws IOException {String weatherUrl = URL_CITY_DAY + "location=" + name + "&key=" + API_KEY + "&range=cn";String cityResult = doGet(weatherUrl);return cityResult;}
}

URL 定义

  • URL_WEATHER 是一个常量,定义了用于获取天气信息的 API URL。这个 API 来自“易客天气”平台。
  • URL_CITY_DAY 是另一个常量,定义了查询城市的 API URL。这个 API 来自“和风天气”平台。
  • API_KEY 用于存放和风天气的 API 密钥,但是目前是空的,需要填入实际的 API 密钥才能使用。

doGet 方法

  • 这个方法用于发起 HTTP GET 请求。
  • 使用了 OkHttp 库来发送请求,urlStr 是请求的 URL。
  • 方法首先创建一个 OkHttpClient 对象,然后构建一个 Request,并使用 client.newCall(request).execute() 来执行该请求。
  • 请求的响应 (Response) 通过 response.body().string() 获取响应内容,将其存储到 result 变量中。
  • 如果在请求过程中发生异常,会捕获 IOException 并抛出一个 RuntimeException
  • 最后,无论是否有异常,都会返回 result,即请求的响应结果。

getCitys 方法

  • 这个方法用于根据城市名称查询城市的相关信息。
  • 首先,它将城市名 name 通过 URL 参数形式与 API 密钥和 range=cn 参数一起拼接成完整的 API URL,目的是查询中国范围内的城市。
  • 然后,它调用 doGet 方法来发送请求,并获取请求的响应内容 cityResult
  • 最后,记录获取到的响应数据,并返回查询结果 cityResult

下面我们要在MainActivity中去实现根据输入信息发起网络请求,并通过异步线程获取该输入文字相关的城市数据:

private void fetchCitys(String city) {if (city == null || city.trim().isEmpty()) {return;  // 如果输入为空,不进行网络请求}new Thread(() -> {try {String weatherOfCity = NetUtil.getCitys(city);if (weatherOfCity != null) {Message message = Message.obtain();message.what = 0;message.obj = weatherOfCity;mHandler.sendMessage(message);  // 将获取到的城市数据通过Handler发送到主线程} else {runOnUiThread(() -> Toast.makeText(SearchForCitysActivity.this, "未能获取到城市数据", Toast.LENGTH_SHORT).show());}} catch (IOException e) {e.printStackTrace();runOnUiThread(() -> Toast.makeText(SearchForCitysActivity.this, "网络请求失败:" + e.getMessage(), Toast.LENGTH_SHORT).show());}}).start();
}
private Handler mHandler = new Handler(Looper.getMainLooper()) {@Overridepublic void handleMessage(@NonNull Message msg) {if (msg.what == 0) {String city = (String) msg.obj;if (city == null) {Toast.makeText(SearchForCitysActivity.this, "网络请求失败!!", Toast.LENGTH_SHORT).show();return;}parseToCityString(city);cityItemRecyclerView.getAdapter().notifyDataSetChanged();}}};

获取到了 JSON 格式的城市数据,下面我们定义了一个名为 parseToCityString 的方法,负责解析从 API 返回的城市信息 JSON 数据,并将其转换为一个城市信息列表:

private void parseToCityString(String cityJson) {List<String> cityList = new ArrayList<>();// 将 JSON 字符串解析为 JsonObjectJsonObject jsonObject = JsonParser.parseString(cityJson).getAsJsonObject();// 获取 "location" 数组JsonArray jsonArray = jsonObject.getAsJsonArray("location");if (jsonArray == null) {Log.e(TAG, "Location array is null");runOnUiThread(() -> Toast.makeText(SearchForCitysActivity.this, "未能获取到城市信息", Toast.LENGTH_SHORT).show());return;}// 遍历数组中的每个元素for (JsonElement jsonElement : jsonArray) {JsonObject cityObject = jsonElement.getAsJsonObject();// 获取城市名称和行政区信息String name = cityObject.get("name").getAsString();String adm1 = cityObject.get("adm1").getAsString();String adm2 = cityObject.get("adm2").getAsString();// 组合为所需的格式String cityInfo = name + "——" + adm1 + "——" + adm2;cityList.add(cityInfo);}citys = cityList;runOnUiThread(() -> {SearchCityItemsAdapter adapter = (SearchCityItemsAdapter) cityItemRecyclerView.getAdapter();if (adapter != null) {adapter.updateCityList(citys);}});}

初始化城市列表

  • 创建一个空的 cityList,用于存储解析出来的城市信息字符串。

解析 JSON 字符串

  • 使用 JsonParser.parseString 方法将传入的 cityJson 字符串转换为 JsonObject。这个对象包含从服务器获取的城市数据。

获取 “location” 数组

  • JsonObject 中提取名为 "location" 的数组,它包含多个城市的信息。每个元素代表一个城市的数据。

检测数据有效性

  • 检查 "location" 数组是否为 null。如果是 null,表示服务器没有返回有效的城市数据。此时通过记录日志和在主线程显示 Toast 提示用户,通知未能获取到城市信息,并结束方法的执行。

解析每个城市的信息

  • 遍历 "location" 数组中的每个元素。每个元素都是一个包含城市信息的 JsonObject
  • 从每个城市的 JsonObject 中提取城市名称(name)、省级行政区(adm1)和地级行政区(adm2)。
  • 将提取的信息组合成一个字符串,格式为 城市名——省级行政区——地级行政区,并将其添加到 cityList 中。

保存解析结果

  • 将生成的 cityList 赋值给类的成员变量 citys,这使得其他部分可以访问到最新的城市数据。

更新 UI

  • 使用 runOnUiThread 将解析后的城市信息更新到 UI 中。因为 UI 操作只能在主线程上进行,所以通过这个方法确保在主线程执行更新操作。
  • 获取 RecyclerView 的适配器 SearchCityItemsAdapter,并调用适配器的 updateCityList(citys) 方法,传入最新的城市列表,更新 RecyclerView 中的城市列表显示。

现在我们就把根据输入的信息去搜索相应的城市就实现了,下面我们就要开始进行数据处理了。

数据处理与信息传递

SearchView

下面大致说一下SearchView用法:

SearchView 的主要功能是为用户提供一个搜索输入框,通常用于在应用中实现搜索功能。以下是其核心功能:

  1. 搜索输入:允许用户输入搜索关键词。
  2. 实时建议:支持根据用户输入的关键词动态提供搜索建议。
  3. 语音搜索:可以配置成支持语音输入功能(需要设备支持)。
  4. 图标化显示:可以在初始状态下以搜索图标的形式显示,用户点击图标时展开为输入框。
  5. 提交搜索请求:当用户输入完查询后,可以点击提交按钮或键盘上的回车键触发搜索请求。
  6. 显示占位提示:可以设置 queryHint 来显示输入提示,引导用户输入。

我们在使用的时候,主要使用的是监控输入的信息。

在创建searchView并获取实例后,可以设置监听事件:

searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {@Overridepublic boolean onQueryTextSubmit(String query) {return true;}@Overridepublic boolean onQueryTextChange(String newText) {fetchCitys(newText);  // 调用获取城市的方法return true;}});

onQueryTextSubmit(String query) 这个方法在用户提交搜索请求时触发,即用户输入完关键词并按下“提交”键(通常是键盘上的回车键)在这个方法中,你可以处理用户的完整搜索请求,比如开始执行搜索或查询操作。

onQueryTextChange(String newText) 这个方法在用户每次修改搜索框内容时触发,比如用户键入或删除字符时。通常用于实现实时搜索或提供动态建议。

我们在进行模糊搜索的时候就要使用的是onQueryTextChange()这个方法,这里我们调用了上面的fetchCitys()去获取相关的城市。

RecyclerView绑定

我们获取了输入信息所对应的城市之后,就需要把相应的信息显示在搜索框下面,我们这里就需要使用到RecyclerView。

当然,我们并不能仅仅只创建一个简单的RecyclerView,因为我们会对想要查询的城市进行点击,所以要设置点击事件,并且还需要把选中的城市返回到Activity方便进行其他操作。

先创建Adapter:

public class SearchCityItemsAdapter extends RecyclerView.Adapter<SearchCityItemsAdapter.SearchCityItemsViewHolder> {List<String> citys;private OnItemClickListener onItemClickListener;// 定义点击事件接口public interface OnItemClickListener {void onItemClick(String cityInfo);}// 构造函数中传入点击监听器public SearchCityItemsAdapter(List<String> citys, OnItemClickListener listener) {this.citys = citys;this.onItemClickListener = listener;}@NonNull@Overridepublic SearchCityItemsAdapter.SearchCityItemsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.city_recyclerview_item, parent, false);return new SearchCityItemsViewHolder(view);}@Overridepublic void onBindViewHolder(@NonNull SearchCityItemsAdapter.SearchCityItemsViewHolder holder, int position) {String cityInfo = citys.get(position);holder.cityItem.setText(cityInfo);// 设置点击事件holder.itemView.setOnClickListener(v -> {if (onItemClickListener != null) {onItemClickListener.onItemClick(cityInfo);}});}@Overridepublic int getItemCount() {return citys == null ? 0 : citys.size();}public class SearchCityItemsViewHolder extends RecyclerView.ViewHolder {TextView cityItem;public SearchCityItemsViewHolder(@NonNull View itemView) {super(itemView);cityItem = itemView.findViewById(R.id.cityName_item);}}public void updateCityList(List<String> newCityList) {this.citys = newCityList;notifyDataSetChanged();}
}

我们自定义了一个点击事件监听器接口 OnItemClickListener,并在 RecyclerView.Adapter 中传递了这个监听器。

上面代码我们可以实现点击RecyclerView中的item后,通过 onItemClickListener.onItemClick(cityInfo);,我们就可以在Activity中获取点击的城市名称。

Activity中实现如下:

	    cityItemRecyclerView = findViewById(R.id.search_recyclerview);LinearLayoutManager layoutManager1 = new LinearLayoutManager(this);cityItemRecyclerView.setLayoutManager(layoutManager1);// 创建适配器并传入点击事件监听器SearchCityItemsAdapter adapter = new SearchCityItemsAdapter(citys, new SearchCityItemsAdapter.OnItemClickListener() {@Overridepublic void onItemClick(String cityInfo) {Intent intent1 = new Intent(SearchForCitysActivity.this, AddCityActivity.class);intent1.putExtra("CityName", cityInfo);intent1.putStringArrayListExtra("CityNames", (ArrayList<String>) cityNames);startActivity(intent1);}});cityItemRecyclerView.setAdapter(adapter);

我们在创建RecyclerView的Adapter的时候就创建了点击事件监听器,重写了onItemClick(String cityInfo)方法,使我们在点击item后可以把城市名称传递给下一个活动。


这样我们就完整实现了模糊搜索与数据处理。


已经到底啦!!

相关文章:

【Android】模糊搜索与数据处理

【Android】模糊搜索与数据处理 本篇博客主要以根据输入内容动态获取城市为例进行讲解。 获取城市 这一部分主要是根据输入的信息去动态获取城市信息 首先定义了一个名为 NetUtil 的类&#xff0c;主要用于通过 HTTP 请求获取城市信息。 public class NetUtil {private stat…...

机器学习-KNN

KNN&#xff1a;K最邻近算法&#xff08;K-Nearest Neighbor,KNN&#xff09; 用特征空间中距离待分类对象的最近的K个样例点的类别来预测。 投票法&#xff1a;K 个样例的对数类别。 k1:最近邻分类 k 通常是奇数&#xff08;因为我们根据这个K数据判断类别&#xff0c;如果…...

python 安装包 site-packages

1. site-packages 文件夹的位置 当我们通过 pip 或其他方式安装一个 Python 包时&#xff0c;这些包的文件就会被复制到 site-packages 文件夹下。 site-packages 文件夹通常位于 Python 的安装目录下的 Lib 文件夹内。具体的路径会根据你使用的操作系统和 Python 版本的不同而…...

大数据-151 Apache Druid 集群模式 配置启动【上篇】 超详细!

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…...

CentOS8.5.2111(3)实验之DHCP服务器架设

一、实验目标 1&#xff0e;掌握DHCP服务器的主配置文件各项申明参数及操作及其含义 2. 具备DHCP 服务器、中继服务器的配置能力 3. 具备测试客户端正常获取服务器分配地址的能力 4. 具备DHCP服务器故障排除能力 二、实训原理/流程 &#xff08;一&#xff09;项目背景 …...

机器学习(4):机器学习项目步骤(一)——定义问题

1. 机器学习项目的五大步骤 定义问题 收集数据和预处理 选择算法和确定模型 训练拟合模型 评估优化模型性能 2. 定义问题的主要任务 刨析业务场景&#xff0c;设定清晰目标&#xff0c;同时还要确定当前问题属于哪一种机器学习类型。 3. “易速鲜花”项目案例 项目任务&a…...

C#中Socket通信常用的方法

创建Socket 在C#中创建一个Socket对象的基本步骤如下&#xff1a; 引入命名空间&#xff1a; 首先&#xff0c;确保你的文件顶部包含了以下命名空间的引用&#xff1a; using System.Net; using System.Net.Sockets; 创建Socket实例&#xff1a; 你可以创建一个Socket实例&am…...

【JavaEE】——单例模式引起的多线程安全问题:“饿汉/懒汉”模式,及解决思路和方法(面试高频)

阿华代码&#xff0c;不是逆风&#xff0c;就是我疯&#xff0c;你们的点赞收藏是我前进最大的动力&#xff01;&#xff01;希望本文内容能够帮助到你&#xff01; 目录 一&#xff1a;单例模式&#xff08;singleton&#xff09; 1&#xff1a;概念 二&#xff1a;“饿汉模…...

huggingface实现中文文本分类

目录 1 自定义数据集 2 分词 2.1 重写collate_fn方法 3 用BertModel加载预训练模型 4 模型试算 5 定义下游任务 6 训练 7 测试 #导包 import torch from datasets import load_from_disk #用于加载本地磁盘的datasets文件 1 自定义数据集 #自定义数据集 #…...

基于python+控制台+txt文档实现学生成绩管理系统(含课程实训报告)

目录 第一章 需求分析 第二章 系统设计 2.1 系统功能结构 2.1.1 学生信息管理系统的七大模块 2.1.2 系统业务流程 2.2 系统开发必备环境 第三章 主函数设计 3.1 主函数界面运行效果图 3.2 主函数的业务流程 3.3 函数设计 第四章 详细设计及实现 4.1 学生信息录入模块的设计与实…...

Spring Boot 整合MyBatis-Plus 实现多层次树结构的异步加载功能

文章目录 1&#xff0c;前言2&#xff0c;什么是多层次树结构&#xff1f;3&#xff0c;异步加载的意义4&#xff0c;技术选型与实现思路5&#xff0c;具体案例5.1&#xff0c;项目结构5.2&#xff0c;项目配置&#xff08;pom.xml&#xff09;5.3&#xff0c;配置文件&#xf…...

网络工程师指南:防火墙配置与管理命令大全,零基础入门到精通,收藏这一篇就够了

本指南详细介绍了防火墙的配置与管理命令&#xff0c;涵盖了防火墙的工作原理、常见配置命令、安全策略与访问控制、日志管理与故障排查&#xff0c;并通过实战案例展示了如何有效防御网络攻击。通过学习本指南&#xff0c;网络工程师能够系统掌握防火墙的配置与管理技能&#…...

英特尔终于找到了Raptor Lake处理器崩溃与不稳定问题的根源

技术背景 在过去的几个月里&#xff0c;一些用户报告称他们的第13代和第14代Intel Core“Raptor Lake”处理器遇到了系统崩溃和不稳定的情况。这些问题最初在2024年7月底被英特尔识别出来&#xff0c;并且初步的诊断显示&#xff0c;这些问题与微码有关&#xff0c;该微码使CP…...

Shp2pb:Shapefile转Protocol Buffers的高效工具

Shp2pb是一个实用工具&#xff0c;专门用于将Shapefile&#xff08;shp&#xff09;格式转换为Protocol Buffers&#xff08;protobuf&#xff09;文件。这对于以更高效、更紧凑的方式处理地理数据特别有用。以下是关于如何安装和使用Shp2pb工具的详细说明&#xff0c;以及一个…...

Elasticsearch使用Easy-Es + RestHighLevelClient实现深度分页跳页

注意&#xff01;&#xff01;&#xff01;博主只在测试环境试了一下&#xff0c;没有发到生产环境跑。因为代码还没写完客户说不用弄了( •̩̩̩̩&#xff3f;•̩̩̩̩ ) 也好&#xff0c;少个功能少点BUG 使用from size的时候发现存在max_result_window10000的限制&…...

基于ASRPRO的语音应答

做这个的起因是为了送女朋友,而且这东西本身很简单,所以在闲暇之余尝试了一下。 这个工程很简单,只通过对ASRPRO进行编程即可。 先看效果。(没有展示所有效果,后续会列出来所有对话触发) 语音助手示例1 语音助手示例2 代码部分使用天文Block编辑,找了一圈好像只…...

3D看车汽车案例,车模一键换皮肤,开关车门,轴距,电池功能

3D 汽车案例 网址&#xff1a; http://car.douchuanwei.com/...

数据结构-4.栈与队列

本篇博客给大家带来的是栈和队列的知识点, 其中包括两道面试OJ题 用队列实现栈 和 用栈实现队列. 文章专栏: Java-数据结构 若有问题 评论区见 欢迎大家点赞 评论 收藏 分享 如果你不知道分享给谁,那就分享给薯条, 如果分享不成功, 那我就会回你一下,那样你就分享成功啦. 你们的…...

芝士AI写作有什么特色? 大模型支撑,智能改写续写,让写作更轻松

又到了一年的毕业季&#xff0c;大学四年眨眼间匆匆就过去了&#xff0c;毕业&#xff0c;求职&#xff0c;考研&#xff0c;工作&#xff0c;升学&#xff0c;但是在这之前&#xff0c;我们必须要完成论文的写作&#xff0c;这也是每一位大学生都必须要面对~ 芝士AI官网&…...

【计网】从零开始学习http协议 --- http的请求与应答

如果你不能飞&#xff0c;那就跑&#xff1b; 如果跑不动&#xff0c;那就走&#xff1b; 实在走不了&#xff0c;那就爬。 无论做什么&#xff0c;你都要勇往直前。 --- 马丁路德金 --- 从零开始学习http协议 1 什么是http协议2 认识URL3 http的请求和应答3.1 服务端设计…...

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周&#xff0c;有很多同学在写期末Java web作业时&#xff0c;运行tomcat出现乱码问题&#xff0c;经过多次解决与研究&#xff0c;我做了如下整理&#xff1a; 原因&#xff1a; IDEA本身编码与tomcat的编码与Windows编码不同导致&#xff0c;Windows 系统控制台…...

uniapp 对接腾讯云IM群组成员管理(增删改查)

UniApp 实战&#xff1a;腾讯云IM群组成员管理&#xff08;增删改查&#xff09; 一、前言 在社交类App开发中&#xff0c;群组成员管理是核心功能之一。本文将基于UniApp框架&#xff0c;结合腾讯云IM SDK&#xff0c;详细讲解如何实现群组成员的增删改查全流程。 权限校验…...

web vue 项目 Docker化部署

Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段&#xff1a; 构建阶段&#xff08;Build Stage&#xff09;&#xff1a…...

ubuntu搭建nfs服务centos挂载访问

在Ubuntu上设置NFS服务器 在Ubuntu上&#xff0c;你可以使用apt包管理器来安装NFS服务器。打开终端并运行&#xff1a; sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享&#xff0c;例如/shared&#xff1a; sudo mkdir /shared sud…...

Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!

一、引言 在数据驱动的背景下&#xff0c;知识图谱凭借其高效的信息组织能力&#xff0c;正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合&#xff0c;探讨知识图谱开发的实现细节&#xff0c;帮助读者掌握该技术栈在实际项目中的落地方法。 …...

MySQL用户和授权

开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务&#xff1a; test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...

智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制

在数字化浪潮席卷全球的今天&#xff0c;数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具&#xff0c;在大规模数据获取中发挥着关键作用。然而&#xff0c;传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时&#xff0c;常出现数据质…...

CSS设置元素的宽度根据其内容自动调整

width: fit-content 是 CSS 中的一个属性值&#xff0c;用于设置元素的宽度根据其内容自动调整&#xff0c;确保宽度刚好容纳内容而不会超出。 效果对比 默认情况&#xff08;width: auto&#xff09;&#xff1a; 块级元素&#xff08;如 <div>&#xff09;会占满父容器…...

【笔记】WSL 中 Rust 安装与测试完整记录

#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统&#xff1a;Ubuntu 24.04 LTS (WSL2)架构&#xff1a;x86_64 (GNU/Linux)Rust 版本&#xff1a;rustc 1.87.0 (2025-05-09)Cargo 版本&#xff1a;cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...

并发编程 - go版

1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程&#xff0c;系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...