Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/198.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android AutoCompleteTextView即使在更新ArrayAdapter时也不显示结果_Android_Adapter_Autocompletetextview - Fatal编程技术网

Android AutoCompleteTextView即使在更新ArrayAdapter时也不显示结果

Android AutoCompleteTextView即使在更新ArrayAdapter时也不显示结果,android,adapter,autocompletetextview,Android,Adapter,Autocompletetextview,我正在尝试获取一个AutoCompleteTextView(ACTV)来显示我从网络资源获取的结果。我已经将completion treshold设置为2,我可以看到当我输入字符时,请求被触发 我得到的结果是正确的。假设我写了“ca”,结果是“car”作为一个自动补全。我有一个回调函数,它从AsyncTask接收结果并将结果放入ArrayAdapter。然后我在ACTV上调用.showDropDown(),并显示一个空下拉列表(普通元素大小的一半)。然后,如果我输入最后一个字母“r”,ACTV显

我正在尝试获取一个AutoCompleteTextView(ACTV)来显示我从网络资源获取的结果。我已经将completion treshold设置为2,我可以看到当我输入字符时,请求被触发

我得到的结果是正确的。假设我写了“ca”,结果是“car”作为一个自动补全。我有一个回调函数,它从AsyncTask接收结果并将结果放入ArrayAdapter。然后我在ACTV上调用.showDropDown(),并显示一个空下拉列表(普通元素大小的一半)。然后,如果我输入最后一个字母“r”,ACTV显示“car”,则会显示下拉列表,结果会突然出现在列表中

如果我输入了两个字符(返回有效结果),并且删除了最后一个字母,也会发生同样的情况。删除字母后,“car”将显示为自动完成值


有人有这个问题吗?看起来适配器中充满了结果,但直到我执行下一个操作时,结果才显示出来。我还尝试在将结果添加到适配器后运行.notifyDataSetChanged(),但这不需要,或者?

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

我想你可能误解了异步任务的必要性。筛选器对象已在执行类似于AsyncTask的操作:
performFiltering()
在后台线程中完成,并且在performFiltering()完成后从UI线程调用
publishResults()
。因此,您可以直接在performFiltering()中执行网络请求,并将结果设置到FilterResults对象中,这样您就不必担心网络请求速度太慢并导致UI出现问题

另一个稍微复杂一点的解决方案是在我的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();
    }
}

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

我认为Joe的答案是可行的。但是,我认为您应该使用,而不是等待/通知

原因是,使用wait/notify时,如果您的API在开始“wait()”之前返回速度过快,那么您就有可能遇到竞争条件。。。在这种情况下,notify将不起作用,而wait()将无限期地等待。 使用闩锁时,代码将如下所示(从Joe复制并修改):


最后,我没有足够的信用来发表评论,否则我会

如果你添加代码可能会有所帮助。乔,干得好!我认为你说的异步任务在peform过滤完成后返回数据是正确的,因此存在竞争条件!感谢您指出performFiltering()是在后台线程中运行的。这似乎太复杂了。我的问题是这些建议是从Firebase中提取的。因此,为了避免Firebase DB listeners之外的另一个aysnc,我在确定适配器获取了数据后再次调用了settext。只需在最后再次触发整个watcher==>performFilter循环。我验证了额外的调用没有破坏任何东西(视图足够聪明,在第一个过滤器已经正常的情况下不会注意到任何变化)。也许它会帮助某人。。。
// 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;
  CountDownLatch latch;

  synchronized APIResult waitForAPI(CharSequence constraint) {
      latch = new CountDownLatch(1);
      someAPIObject.startAsyncNetworkRequest(constraint);
      // At this point, control returns here, and the network request is in-progress in a different thread.
      try {
        // Will wait till the count is 0...
        // If the count is already 0, it'll return immediately. 
        latch.await();
        // 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.
    // countDown() will wake up the other calling thread, allowing it to continue
    // execution in the performFiltering() method, as usual.
    latch.countDown();
  }
}