autocompleteTextViewArrayAdapterが更新された場合でも結果が表示されません

StackOverflow https://stackoverflow.com/questions/2671404

質問

AutoCompleTeTextView(ACTV)を取得して、ネットワークリソースから得ている結果を表示しようとしています。私は完了トレシードを2に設定しましたが、キャラクターに入るとリクエストが起動されることがわかります。

私が得ている結果は正しいものです。 「CA」と書いて、結果「車」が自動認定として取得されるとしましょう。 Asynctaskから結果を受信し、結果をArrayAdapterに入れるコールバック関数があります。次に、ACTVで.ShowDropDown()を呼び出し、空のドロップダウンが表示されます(通常の要素の半分のサイズ)。次に、最後の文字「R」を入力し、ACTVが「車」を表示すると、ドロップダウンが表示され、結果が突然リストに表示されます。

私が2人の文字を入力した場合(有効な結果を返します)、最後の文字を削除した場合も同じことが起こります。文字が削除されると、「車」が自動補完値として表示されます。

誰かがこの問題を抱えていましたか?アダプターは結果で満たされているように見えますが、結果は次のアクションまで表示されません。また、アダプターに結果を追加した後、.notifydatasetchanged()を実行しようとしましたが、それは必要ありませんか?

役に立ちましたか?

解決

あなたのコードを見ることなく、何が起こっているのかを伝えるのは難しいです。しかし、最初に思い浮かぶのは、あなたのネットワーク要求が別のスレッドで起こっていること、したがってあなたの performFiltering() 空の結果を時期尚早に返す可能性があります。その時点で、 publishResults() 空の結果を返していますが、ドロップダウンは空です。その後、Asynctaskは結果を取り戻し、結果をアダプターのリストに追加しますが、何らかの理由でまだ表示されていません。

しかし、あなたはasynctaskの必要性について間違っているかもしれないと思います。フィルターオブジェクトはすでにasynctaskに似たことをしています: performFiltering() 背景スレッドで行われます publishResults() PerformFiltering()が終了した後、UIスレッドから呼び出されます。したがって、ネットワークリクエストをパフォーマンスフィルタリング()で直接実行し、結果をFilterResultsオブジェクトに設定できます。ネットワークリクエストが遅すぎてUIの問題を引き起こすことを心配する必要はありません。

少し複雑な代替ソリューションですが、それは私がフィルターオブジェクトで行っていることです(パフォーマンスフィルタリングに必要なブロッキング/同期ステップの代わりに非同期コールバックを使用して、背景にAPI呼び出しを行う既存のアーキテクチャのために(既存のアーキテクチャによる) )、クロススレッドモニタリングを実行するためにwait()/notify()を使用して同期オブジェクトを使用することです。そのため、効果はパフォーマンスフィルタリング()でネットワーク要求を直接実行するのと同じですが、実際には複数のスレッドで発生しています。

// 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呼び出しのアーキテクチャが既に整っており、パフォーマンスフィルタリング()で同期結果を取得するためにその動作を変更したくない場合、1つの可能性にすぎません。

他のヒント

ジョーの答えは行く方法だと思います。ただし、使用する必要があると思います CountDownLatch 待機/通知の代わりに。

その理由は、wait/notifyを使用すると、 "wait()"を開始する前にAPIが実際に非常に高速に戻ると、レース条件の危険があります...この場合、Notifyは効果がなく、Wait()は無期限に待機します。 。ラッチを使用すると、コードは次のようになります(ジョーからコピーされ、変更された):

// 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();
  }
}

最後に、コメントを投稿するのに十分なクレジットがありません。そうでなければ...

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top