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

news2024/9/24 1:16:13

【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()) {
        @Override
        public 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 字符串解析为 JsonObject
        JsonObject 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() {
            @Override
            public boolean onQueryTextSubmit(String query) {
                return true;
            }

            @Override
            public 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
    @Override
    public 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);
    }

    @Override
    public 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);
            }
        });
    }

    @Override
    public 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() {
            @Override
            public 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.coloradmin.cn/o/2158966.html

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

相关文章

计算机毕业设计之:微信小程序的校园闲置物品交易平台(源码+文档+讲解)

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

JavaEE: 深入探索TCP网络编程的奇妙世界(六)

文章目录 TCP核心机制TCP核心机制九: 面向字节流TCP核心机制十: 异常处理 小小的补充(URG 和 PSH)~TCP小结TCP/UDP 对比用UDP实现可靠传输(经典面试题) 结尾 TCP核心机制 上一篇文章JavaEE: 深入探索TCP网络编程的奇妙世界(五) 书接上文~ TCP核心机制九: 面向字节流 TCP是面…

开关频率与谐振频率对应的模态图

当fsfr时 当fr2<fs<fr1时 当fs>fr1时 开关频率对应输入电压的频率 谐振频率对应的是谐振电流的频率

JavaSE - 面向对象编程05

01 正则表达式 【1】概念&#xff1a;正则表达式是由一些特定字符组成的&#xff0c;代表的是一个规则。 【2】可以用来做什么&#xff1f; ① 用于校验数据格式的合法性 ② 用于在文本中爬取满足要求的内容 ③ 用于String类的replace方法&#xff0c;split方法的替换和分割 …

动态时间【JavaScript】

这个代码实现了一个动态显示当前日期和时间的功能。具体来说&#xff0c;它会每秒更新一次时间并在页面上显示出来。 实现效果&#xff1a; 代码&#xff1a; <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8"><…

GUI编程之MATLAB入门详解(01)

⛄前言 图形用户界面的设计是MATLAB的核心应用之一。当用户与计算机之间或用户与计算机程序之间进行交互操作时&#xff0c;舒服高效的用户接口功能则会对用户产生极大的吸引力。图形用户界面&#xff08;GUI&#xff09;则通过窗口、图标、按钮、菜单、文本等图形对象构成用户…

美业SaaS收银系统如何收银?博弈美业实操/美业门店管理系统源码

1.打开博弈美业APP 2.工作台上方的【收银台】、【扫码核销】、【密码核销】均可完成收银 3.【收银台】可直接选择商品/服务/课程&#xff0c;再选择客户后提交订单收款 4.【扫码核销】【密码核销】可直接扫描二维码、输入核销码进行收银

大模型日报|7 篇必读的大模型论文

大家好&#xff0c;今日必读的大模型论文来啦&#xff01; 1.中科大团队提出人像视频编辑方法 PortraitGen 中国科学技术大学团队提出了 PortraitGen&#xff0c;这是一种功能强大的人像视频编辑方法&#xff0c;它能通过多模态提示实现一致且富有表现力的风格化。 传统的人…

SLAM面经1(百度)

百度面经 百度共三面,如果面试效果俱佳,会增加一个hr面。前二面主要是技术面,分为在线coding+代码知识+专业知识+工程能力。第三面是主管面,偏向于管理方面,和hr面相似。 一面 1)在线coding 在线coding的考试内容为下面力扣的变种。 2)专业面 (1)VINS-FUSION与ORB…

鲲鹏计算这五年:硬生态基本盘稳住,才能放手进击软生态

文 | 智能相对论 作者 | 叶远风 数智化深入发展、新质生产力成为主旋律的当下&#xff0c;本土计算产业的发展被寄予越来越多的关注和期待。自2019年开启以来&#xff0c;鲲鹏计算产业生态已经整整走过5个年头。 因此&#xff0c;今年华为全联接大会的鲲鹏之夜&#xff0c;在…

【网络安全】依赖混淆漏洞实现RCE

未经许可&#xff0c;不得转载。 文章目录 正文 依赖混淆是一种供应链攻击漏洞&#xff0c;发生在企业的内部依赖包错误地从公共库&#xff08;如npm&#xff09;下载&#xff0c;而不是从其私有注册表下载。攻击者可以在公共注册表中上传一个与公司内部包同名的恶意包&#xf…

java基础(2)方法的使用

目录 1.前言 2.正文 2.1方法的定义 2.2方法的调用过程 2.3方法的实参与形参 2.3.1形参 2.3.2实参 2.3.3参数传递 2.4方法的重载 3.小结 1.前言 哈喽大家好啊&#xff0c;今天博主继续带领大家学习java的基本语法&#xff0c;java的基础语法部分打算用六到七篇博文完…

关于uniapp wifi调用走过的坑

1. uniapp老脚手架与uni-wif带来的兼容性问题 且几乎找不到解决方法 2. uni-wif需要插件市场安装 3.还有一种可以使用导入安卓类的方式&#xff0c;可以正常获取到已经连接ssid&#xff08;wifi名称&#xff09;&#xff0c;也可以获取到wifi列表 &#xff0c; 但ScanResul…

p18 docker镜像原理之联合文件系统,p19 docker镜像分层的理解

镜像是什么 镜像其实就是一种轻量级的&#xff0c;可执行的一种软件包&#xff0c;用来打包基于环境开发的软件&#xff0c;里面可以包括代码&#xff0c;环境&#xff0c;数据库&#xff0c;配置文件等信息 如何得到镜像&#xff1f; 可以从镜像仓库下载比方说dockerhub 比…

道路车辆功能安全 ISO 26262标准(2)—功能安全管理

写在前面 本系列文章主要讲解道路车辆功能安全ISO26262标准的相关知识&#xff0c;希望能帮助更多的同学认识和了解功能安全标准。 若有相关问题&#xff0c;欢迎评论沟通&#xff0c;共同进步。(*^▽^*) 1. 道路车辆功能安全ISO 26262标准 2. ISO 26262-2 功能安全管理 IS…

基于SpringBoot+Vue的旅游攻略平台管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码 精品专栏&#xff1a;Java精选实战项目…

论文不会写快来看!分享4款ai改写论文软件

在当今学术研究和写作领域&#xff0c;AI论文改写工具已经成为不可或缺的助手。这些工具不仅能够帮助研究人员提高写作效率&#xff0c;还能确保论文的质量和原创性。以下是四款值得推荐的AI改写论文软件&#xff0c;其中特别推荐千笔-AIPassPaper。 千笔-AIPassPaper 传送门&…

设计模式之命令模式:从原理到实战,深入解析及源码应用

命令模式 什么是命令模式&#xff1f; 命令模式&#xff08;Command Pattern&#xff09;是一种行为设计模式&#xff0c;它将一个请求封装为一个对象&#xff0c;从而允许使用不同的请求、队列或者日志来参数化对象&#xff0c;并支持可撤销的操作。命令模式的核心思想是将命令…

STM32在Keil5中利用Jansson库处理和组装JSON数据【详细版】

在Keil5中利用Jansson库处理和组装JSON数据 下载Keil.Jansson.1.0.0.pack https://keilpack.azureedge.net/pack/Keil.Jansson.1.0.0.packhttps://keilpack.azureedge.net/pack/Keil.Jansson.1.0.0.pack 下载完成后直接安装到keil5中即可 选择Jansson库的理由&#xff1a;轻量…

医学数据分析实训 项目三 关联规则分析预备项目---购物车分析

文章目录 1 预备项目关联规则分析实践———购物车分析1 产生频繁集2 产生关联规则 1 预备项目 关联规则分析实践———购物车分析 import warnings import numpy as np import pandas as pd from mlxtend.frequent_patterns import apriori from mlxtend.frequent_patterns …