个人网站界面设计图片,书城网站开发,中英网站搭建报价表,三只松鼠的网站建设的意义【Android】模糊搜索与数据处理
本篇博客主要以根据输入内容动态获取城市为例进行讲解。
获取城市 这一部分主要是根据输入的信息去动态获取城市信息 首先定义了一个名为 NetUtil 的类#xff0c;主要用于通过 HTTP 请求获取城市信息。
public class NetUtil {private stat…【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 rangecn;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 密钥和 rangecn 参数一起拼接成完整的 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) {ListString 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 的主要功能是为用户提供一个搜索输入框通常用于在应用中实现搜索功能。以下是其核心功能
搜索输入允许用户输入搜索关键词。实时建议支持根据用户输入的关键词动态提供搜索建议。语音搜索可以配置成支持语音输入功能需要设备支持。图标化显示可以在初始状态下以搜索图标的形式显示用户点击图标时展开为输入框。提交搜索请求当用户输入完查询后可以点击提交按钮或键盘上的回车键触发搜索请求。显示占位提示可以设置 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.AdapterSearchCityItemsAdapter.SearchCityItemsViewHolder {ListString citys;private OnItemClickListener onItemClickListener;// 定义点击事件接口public interface OnItemClickListener {void onItemClick(String cityInfo);}// 构造函数中传入点击监听器public SearchCityItemsAdapter(ListString citys, OnItemClickListener listener) {this.citys citys;this.onItemClickListener listener;}NonNullOverridepublic 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(ListString 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, (ArrayListString) cityNames);startActivity(intent1);}});cityItemRecyclerView.setAdapter(adapter);我们在创建RecyclerView的Adapter的时候就创建了点击事件监听器重写了onItemClick(String cityInfo)方法使我们在点击item后可以把城市名称传递给下一个活动。 这样我们就完整实现了模糊搜索与数据处理。 已经到底啦