【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后可以把城市名称传递给下一个活动。


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


已经到底啦!!

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

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

相关文章

C++自动驾驶面试核心问题整理

应用开发 概述&#xff1a;比较基础&#xff0c;没啥壁垒&#xff0c;主要有linux开发经验即可 问题&#xff1a;基础八股&#xff0c;如计算机网络、操作系统、c11等基础三件套&#xff1b;中等难度算法题1-2道。 中间件开发&#xff08;性能优化&#xff09; 概述&am…

快递物流查询-快递查询-快递单号查询-快递物流单号查询-快递物流轨迹查询-快递物流查询接口

快递物流查询接口&#xff08;API&#xff09;是一种允许开发者通过编程方式实时查询快递物流信息的服务。这些接口通常集成了多家快递公司的物流数据&#xff0c;为电商平台、物流管理系统、个人用户等提供便捷的物流查询服务。以下是关于快递物流查询接口的一些详细介绍&…

哪有什么三教九流,物以类聚罢了——kmeans聚类算法

观察人类社会&#xff0c;亦或说车水马龙中的光怪陆离&#xff0c;不难发现《马原》中介绍的人类社会中的个体&#xff0c;总是通过某种方面的“类似”聚在一起&#xff0c;文学上称这种现象叫做物以类聚&#xff0c;人以群分。 一.引言 前文提到&#xff0c;每个数据项&#x…

SpringBoot项目License证书生成与验证(TrueLicense) 【记录】

SpringBoot项目License证书生成与验证(TrueLicense) 【记录】 在非开源产品、商业软件、收费软件等系统的使用上&#xff0c;需要考虑系统的使用版权问题&#xff0c;不能随便一个人拿去在任何环境都能用。应用部署一般分为两种情况&#xff1a; 应用部署在开发者自己的云服务…

Qt笔记(十七)cmake编译Qt项目

Qt笔记&#xff08;十七&#xff09;cmake编译Qt项目 1. 文件内容与文件结构1.1.文件目录1.2. CMakeLists.txt内容1.3. main.cpp文件1.4. mouseevent.h1.5. mouseevent.cpp1.6. 生成Visual Studio项目后编译报错1.7. 界面显示中文乱码问题 1. 文件内容与文件结构 1.1.文件目录…

jdk11特性介绍

JDK 11&#xff08;也称为Java 11&#xff09;是Java平台的一个重要版本&#xff0c;它引入了许多新特性和改进&#xff0c;旨在提高开发者的生产力和Java平台的性能。以下是一些JDK 11的主要特性&#xff1a; 局部变量类型推断&#xff08;Local-Variable Syntax for Lambda P…

2009考研数学真题解析-数二:

第一题&#xff1a; 解析&#xff1a;先找间断点&#xff1a;分母不能等于0&#xff0c;分母是sinΠx&#xff0c; 因此不难看出间断点是x0&#xff0c;-1&#xff0c;-2&#xff0c;-3。。。。。 接着一个一个来算这些点是什么间断点。 &#xff0c;从x趋于2开始&#xff0c;分…

JavaScript是如何来的~~

文章目录 前言一、网络的诞生 ( The birth of the Web )二、Mosaic 浏览器三、Netscape 浏览器四、JavaScript的诞生 ~ 千呼万唤始出来总结 前言 例如&#xff1a;想要了解一门语言的发展历程&#xff0c;首先你得知道它是怎么来的&#xff0c;所以本文开篇介绍了网络的基本发…

智能BI平台项目

1.项目介绍 BI商业智能&#xff1a;数据可视化、报表可视化系统 4&#xff09;发布订阅 Resource 是基于名称进行查找的&#xff0c;而Spring框架中更常用的 Autowired 则是基于类型进行查找的。如果找不到匹配的bean&#xff0c;Autowired 会抛出异常&#xff0c;而 Resource…

EAGLE——探索混合编码器的多模态大型语言模型的设计空间

概述 准确解释复杂视觉信息的能力是多模态大型语言模型 (MLLM) 的关键重点。最近的研究表明&#xff0c;增强的视觉感知可显著减少幻觉并提高分辨率敏感任务&#xff08;例如光学字符识别和文档分析&#xff09;的性能。最近的几种 MLLM 通过利用视觉编码器的混合来实现这一点…

网络层协议 —— IP协议

目录 0.前言 1.IP协议的格式 2.IP地址 2.1IP地址的划分 国际间IP地址的划分 公有IP 私有IP 特殊的IP地址 国内IP地址的划分 2.2IP地址不足问题 2.3IP地址的功能 2.4如何使用IP地址 2.5IP地址的构成 3.网段划分 以前的方案 现在的方案 4.认识宏观网络 5.路由 …

SpringCloud config native 配置

SpringCloud config native 配置 1.概述 最近项目使用springCloud 框架&#xff0c;使用config搭建git作为配置中心。 在私有化部署中&#xff0c;出现很多比较麻烦的和鸡肋的设计。 每次部署都需要安装gitlab 有些环境安装完gitlab&#xff0c;外面不能访问&#xff0c;不给开…

QT实现升级进度条页面

一.功能说明 在Qt中实现固件升级的进度条显示窗口&#xff0c;你可以通过创建一个自定义的对话框&#xff08;Dialog&#xff09;来完成。这个对话框可以包含一个进度条&#xff08;QProgressBar&#xff09;、一些文本标签&#xff08;QLabel&#xff09;用于显示状态信息&am…

SSL 最长签发时间是多久?

在当今数字化的时代&#xff0c;网络安全变得至关重要。为了确保数据在网络传输中的安全性&#xff0c;SSL&#xff08;Secure Sockets Layer&#xff0c;安全套接层&#xff09;证书被广泛应用。那么&#xff0c;SSL最长签发时间是多久呢&#xff1f; SSL证书是一种数字证书&…

差分数组介绍

差分数组 差分数组介绍定义性质性质1: 计算数列第i项的值性质2: 计算数列第i项的前缀和应用场景差分数组具体示例【leetcode】370.区间加法题目描述题解【leetcode】1109. 航班预订统计题目描述题解【leetcode】2848.与车相交的点题目描述题解差分数组介绍 定义 对于已知有n个…

C#如何把写好的类编译成dll文件

1 新建一个类库项目 2 直接改写这个Class1.cs文件 3 记得要添加Windows.Forms引用 4 我直接把在别的项目中做好的cs文件搞到这里来&#xff0c;连文件名也改了&#xff08;FilesDirectory.cs&#xff09;&#xff0c;这里using System.Windows.Forms不会报错&#xff0c;因为前…

制造解法 Manufactured Solutions 相关的论文的阅读笔记

Verification of Euler/Navier–Stokes codes using the method of manufactured solutions https://doi.org/10.1002/fld.660 粘性项与扩散项之间的平衡 For the Navier–Stokes simulations presented herein, the absolute viscosity is chosen to be a large constant va…

【Java】掌握Java:基础概念与核心技能

文章目录 前言&#xff1a;1. 注释2. 字面量3. 变量详解3.1 变量的定义3.2 变量里的数据存储原理3.3 数据类型3.4 关键字、标识符 4. 方法4.1 方法是啥&#xff1f;4.2 方法的完整定义格式4.3 方法如何使用&#xff1a;4.4 方法的其他形式4.5 方法的其他注意事项4.5.1 方法是可…

如何充分使用芝士AI呢?一文讲清楚助力论文完成无忧

为了解决各位学弟学妹们的论文烦恼&#xff0c;助力大家毕业无忧&#xff0c;芝士AI由985硕博团队的学长学姐们潜心研发出来的一款集齐论文选题、开题报告、论文初稿、论文查重、论文降重、论文降AIGC率、论文答辩稿、论文答辩PPT&#xff0c;一站式解决困扰大家已久的论文问题…

如何创建标准操作规程(SOP)[+模板]

创建、分发和管理流程文档和逐步说明的能力是确定企业成功的关键因素。许多组织依赖标准操作规程&#xff08;SOP&#xff09;作为基本形式的文档&#xff0c;指导他们的工作流程操作。 然而&#xff0c;SOP不仅仅是操作路线图&#xff1b;它们就像高性能车辆中的先进GPS系统一…