You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AutocompleteTextView调用dismissDropDown()无效问题求助

问题

我用AutocompleteTextView实现远程搜索功能,文本内容变化时发起HTTP请求从远程数据库拉取数据。目前遇到两个矛盾的问题:

  • 点击下拉列表选项时,TextWatcher会把填充文本的操作检测为文本变化,导致下拉框始终无法关闭——哪怕在setOnItemClickListener里调用dismissDropDown()也没用
  • 如果不手动调用showDropdown(),点击选项后下拉框能正常关闭,但搜索结果显示异常,比如明明有8条结果,只显示2条甚至完全不显示
问题根源
  1. TextWatcher被重复触发:点击选项时,AutocompleteTextView会自动填充选中的文本,这会触发TextWatcher的onTextChanged方法,重新发起请求并调用showDropDown(),把刚关掉的下拉框又弹出来
  2. 重复初始化组件:每次文本变化都重新创建Adapter、设置setOnItemClickListener,不仅浪费资源,还会导致组件状态混乱,出现结果显示异常
  3. 手动干扰默认逻辑:强制调用showDropDown()会打乱AutocompleteTextView的默认显示机制,导致结果展示异常
解决方案
  1. 临时禁用TextWatcher:点击选项填充文本时,先移除TextWatcher,避免触发不必要的请求,填充完成后再重新添加
  2. 提前初始化核心组件:把Adapter初始化和setOnItemClickListener移到TextWatcher外面,仅在请求成功后更新Adapter的数据,而非每次都重新创建
  3. 移除手动showDropDown()调用:让AutocompleteTextView自行管理下拉框的显示,只在数据更新时通知Adapter刷新

修改后的Java代码

// 提前声明全局变量
private ArrayAdapter<Deposito> depositoAdapter;
private TextWatcher depositoTextWatcher;
private AutoCompleteTextView autocompleteDeposito;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.your_layout_id); // 替换为你的布局ID

    autocompleteDeposito = findViewById(R.id.autocompleteDeposito);
    
    // 初始化空Adapter,仅执行一次
    depositoAdapter = new ArrayAdapter<>(
            RegistroActivity.this,
            android.R.layout.simple_dropdown_item_1line,
            new ArrayList<>()
    );
    autocompleteDeposito.setThreshold(2);
    autocompleteDeposito.setAdapter(depositoAdapter);

    // 设置Item点击监听,仅初始化一次
    autocompleteDeposito.setOnItemClickListener((parent, view, position, id) -> {
        Deposito depositoSeleccionado = (Deposito) parent.getItemAtPosition(position);
        depositoSeleccionadoId = depositoSeleccionado.getId();
        
        // 临时移除TextWatcher,避免填充文本触发请求
        autocompleteDeposito.removeTextChangedListener(depositoTextWatcher);
        // 手动设置文本(确保选中内容正确填充)
        autocompleteDeposito.setText(depositoSeleccionado.getNombre());
        // 重新添加TextWatcher
        autocompleteDeposito.addTextChangedListener(depositoTextWatcher);
    });

    // 初始化TextWatcher
    depositoTextWatcher = 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 nombreDeposito = charSequence.toString().trim();
            // 文本长度小于阈值时清空结果
            if (nombreDeposito.length() < 2) {
                depositoAdapter.clear();
                return;
            }

            String url = "http://MY_SERVER_IP/buscarDeposito.php";
            StringRequest stringRequest = new StringRequest(Request.Method.POST, url, response -> {
                try {
                    JSONObject jsonObject = new JSONObject(response);
                    boolean success = jsonObject.getBoolean("success");

                    if (success) {
                        JSONArray data = jsonObject.getJSONArray("data");
                        ArrayList<Deposito> depositoList = new ArrayList<>();

                        for (int j = 0; j < data.length(); j++) {
                            JSONObject item = data.getJSONObject(j);
                            String idDeposito = item.getString("id");
                            String nombre = item.getString("nombre");
                            depositoList.add(new Deposito(nombre, idDeposito));
                        }

                        // 更新Adapter数据,而非重建Adapter
                        depositoAdapter.clear();
                        depositoAdapter.addAll(depositoList);
                        depositoAdapter.notifyDataSetChanged();
                    } else {
                        depositoAdapter.clear();
                        Toast.makeText(RegistroActivity.this, "未找到匹配的仓库", Toast.LENGTH_SHORT).show();
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                    Toast.makeText(RegistroActivity.this, "处理响应出错", Toast.LENGTH_LONG).show();
                }
            }, error -> {
                depositoAdapter.clear();
                Toast.makeText(RegistroActivity.this, "请求失败", Toast.LENGTH_SHORT).show();
            }) {
                @Override
                protected Map<String, String> getParams() {
                    Map<String, String> params = new HashMap<>();
                    params.put("nombre_deposito", nombreDeposito);
                    return params;
                }
            };

            RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext());
            requestQueue.add(stringRequest);
        }

        @Override
        public void afterTextChanged(Editable editable) {}
    };

    // 添加TextWatcher到控件
    autocompleteDeposito.addTextChangedListener(depositoTextWatcher);
}

XML代码(无需修改)

<AutoCompleteTextView
    android:id="@+id/autocompleteDeposito"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginStart="44dp"
    android:layout_marginTop="180dp"
    android:layout_marginEnd="44dp"
    android:hint="@string/deposito_autocomplete"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintHorizontal_bias="0.0"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="@+id/toolbar" />

内容的提问来源于stack exchange,提问作者pmpato

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 21:29:56