即使ArrayAdapter更新,AutoCompleteTextView也不显示结果

Eri*_*vik 7 android adapter autocompletetextview

我正在尝试使用AutoCompleteTextView(ACTV)来显示我从网络资源中获取的结果.我已将完成阈值设置为2,我可以看到在输入字符时触发了请求.

我得到的结果是正确的.让我说我写"ca",我得到结果"汽车"作为自动完成.我有一个回调函数,它接收来自AsyncTask的结果并将结果放入ArrayAdapter.然后我在ACTV上调用.showDropDown()并显示一个空的下拉列表(正常元素大小的一半).然后,如果我输入最后一个字母"r"并且ACTV显示"car",则显示下拉列表并且结果突然出现在列表中.

如果我输入了两个字符(返回有效结果),则删除最后一个字母也会出现同样的情况.删除该字母后,"car"将显示为自动完成值.

有谁有这个问题?看起来适配器已经填充了结果,但结果直到我做的下一个操作才会显示.我已经尝试在将结果添加到适配器后运行.notifyDataSetChanged(),但是不应该这样做,或者?

Joe*_*Joe 16

如果没有看到您的代码,很难说清楚可能会发生什么.但首先想到的是,您的网络请求发生在不同的线程上,因此您performFiltering()可能会过早地返回空结果集.此时,publishResults()返回空结果,您的下拉列表为空.稍后,您的AsyncTask将返回其结果,并将结果添加到适配器列表中,但由于某种原因,它尚未显示.

我想你可能会错误地认为需要AsyncTask.Filter对象已经在做类似于AsyncTask的事情: performFiltering()在后台线程中完成,并publishResults()在performFiltering()完成后从UI线程调用.这样你就可以直接做你的网络请求performFiltering(),并将结果设定到FilterResults对象,你将不必担心网络请求太慢而导致你的用户界面的问题.

另一种解决方案,稍微复杂一点,但它是我在我的Filter对象中所做的事情(由于现有的架构在后台执行API调用,使用异步回调而不是performFiltering所需的阻塞/同步步骤( )),是使用带有wait()/ notify()的同步对象来进行跨线程监视,因此效果与在performFiltering()中直接执行网络请求相同,但它实际上发生在多个线程中:

// in Filter class..
protected FilterResults performFiltering(CharSequence constraint) {

    APIResult response = synchronizer.waitForAPI(constraint);
    // ...
}

// callback invoked after the API call finishes:
public void onAPIComplete(APIResult results) {
    synchronizer.notifyAPIDone(results);
}

private class Synchronizer {
    APIResult result;

    synchronized APIResult waitForAPI(CharSequence constraint) {
        someAPIObject.startAsyncNetworkRequest(constraint);
        // At this point, control returns here, and the network request is in-progress in a different thread.
        try {
            // wait() is a Java IPC technique that will block execution until another
            // thread calls the same object's notify() method.
            wait();
            // When we get here, we know that someone else has just called notify()
            // on this object, and therefore this.result should be set.
        } catch(InterruptedException e) { }
        return this.result;
    }

    synchronized void notifyAPIDone(APIResult result) {
        this.result = result;
        // API result is received on a different thread, via the API callback.
        // notify() will wake up the other calling thread, allowing it to continue
        // execution in the performFiltering() method, as usual.
        notify();
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,我认为您可能会发现最简单的解决方案是直接在performFiltering()方法中同步执行您的网络请求.上面的代码示例只是一种可能性,如果您已经具有适用于异步/回调驱动的API调用的体系结构,并且您不希望更改该行为以便在performFiltering()中获得同步结果.