Android实现SearchView自动补全时解析JSON数据应用崩溃问题求助
崩溃原因
- 核心错误为
NetworkOnMainThreadException,Android系统禁止在UI主线程执行网络操作,你的代码中调用OkHttp的execute()方法发起同步网络请求,而该逻辑写在onTextChanged回调中(该回调运行在主线程),直接触发系统拦截导致崩溃。 - 辅助问题:你通过字符串替换、拼接的方式处理接口返回的JSON结构,可靠性极低,无法正确提取建议列表,后续即使解决崩溃问题也无法正常展示自动补全内容。
修复实现方案
全局变量声明(在Activity类内定义)
// 自动补全适配器、建议列表全局复用,避免每次输入重复创建 private ArrayAdapter<String> autoCompleteAdapter; private List<String> suggestList = new ArrayList<>(); // 全局复用OkHttpClient实例,提升性能 private final OkHttpClient okHttpClient = new OkHttpClient();
核心逻辑代码(写在onCreate方法中)
AutoCompleteTextView autoCompleteTextView = findViewById(R.id.actv); // 初始化适配器 autoCompleteAdapter = new ArrayAdapter<>(MainActivity3.this, R.layout.custom_list_tem, R.id.text_view_list_item, suggestList); autoCompleteTextView.setAdapter(autoCompleteAdapter); autoCompleteTextView.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { } @Override public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { String keyword = charSequence.toString().trim(); // 输入为空时清空建议列表 if (keyword.isEmpty()) { suggestList.clear(); autoCompleteAdapter.notifyDataSetChanged(); return; } // 取消之前未完成的请求,避免冗余请求占用资源 okHttpClient.dispatcher().cancelAll(); try { // 关键词编码,避免特殊字符、中文导致请求失败 String encodedKey = URLEncoder.encode(keyword, StandardCharsets.UTF_8.name()); String url = "http://suggestqueries.google.com/complete/search?hl=en&ds=yt&q=" + encodedKey + "&client=firefox"; Request request = new Request.Builder().url(url).build(); // 发起异步请求,不会阻塞主线程 okHttpClient.newCall(request).enqueue(new Callback() { @Override public void onFailure(@NonNull Call call, @NonNull IOException e) { e.printStackTrace(); } @Override public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException { if (!response.isSuccessful() || response.body() == null) return; String responseStr = response.body().string(); List<String> newSuggests = new ArrayList<>(); try { // 标准JSON解析,直接提取建议列表 JSONArray rootArr = new JSONArray(responseStr); JSONArray suggestArr = rootArr.getJSONArray(1); for (int j = 0; j < suggestArr.length(); j++) { newSuggests.add(suggestArr.getString(j)); } } catch (JSONException e) { e.printStackTrace(); } // 更新UI必须切回主线程 runOnUiThread(() -> { suggestList.clear(); suggestList.addAll(newSuggests); autoCompleteAdapter.notifyDataSetChanged(); }); } }); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } @Override public void afterTextChanged(Editable editable) { } });
必要配置补充(在AndroidManifest.xml中添加)
<!-- 添加网络权限 --> <uses-permission android:name="android.permission.INTERNET" /> <application ... <!-- 允许http明文请求,适配你调用的http接口 --> android:usesCleartextTraffic="true"> ... </application>
内容的提问来源于stack exchange,提问作者Sara Angelou
相关产品推荐
相关产品推荐

