1

J'ai un AutocompleteTextView qui fonctionne avec un ArrayAdapter. L'adaptateur est mis à jour à partir d'un service Web lorsque le texte change. Cette mise à jour est faite dans un AsyncTask, ce qui est censé être une bonne pratique. Cela fonctionne plus ou moins, car les suggestions après chaque touche sont basées sur les chaînes récupérées dans la touche précédente. Il y a quelques problèmes liés à cette page, mais aucune des réponses ne fonctionne pour moi. De toute façon, j'avais une solution, mais elle est inefficace et je ne sais pas pourquoi la "solution officielle" échoue.ArrayAdapter est mis à jour en fin de Webservice dans AutoCompleteTextAdapter

Je pense que la clé est dans la fonction qui utilise de ArrayAdapter en arrière-plan. Il en ce que je fais dans l'appel asynchrone aux webservices:

private class DoAutoCompleteSearch extends AsyncTask<String, Void, Map<String, String>> { 

    @Override 
    protected Map<String, String> doInBackground(String... params) { 

     // Ask the webservice for data 
     Map<String, String> autoComplete = GetResource.dataList(params[0]); 
     return autoComplete; 
    } 

    @Override 
    protected void onPostExecute(Map<String, String> result) { 

     //mAutoCompleteAdapter.clear(); * This should work but does not * 

/* If it is set a new adapter in the AutoCompleteTextView, the whole thing works properly */ 

    mAutoCompleteAdapter = new ArrayAdapter<String>(mAutoCompleteAdapter.getContext(), android.R.layout.simple_dropdown_item_1line); 
    mACTV.setAdapter(mAutoCompleteAdapter); 

     for (Map.Entry<String, String> entry : result.entrySet()) { 
      mAutoCompleteAdapter.add(entry.getKey()); 
     } 
    } 
} 

J'ai essayé avec mAutoCompleteAdapter.clear() et la mise en mAutoCompleteAdapter.notifyDataSetChanged() partout, mais il est inutile.

Répondre

2

J'ai également essayé beaucoup d'obtenir cette approche fonctionnante, mais n'ai pas réussi mieux que vous-même. Mais j'ai trouvé un autre moyen d'accomplir ce que tu veux; étendre ArrayAdapter et implémenter Filterable. Cette classe va faire le chargement proprement dit de la base de données, lorsqu'il est appelé par le AutoCompleteTextView dans un thread de travail:

public class MyAutoCompleteAdapter extends ArrayAdapter<String> implements Filterable { 

    private List<String> mData = new ArrayList<String>(); 
    private Server mServer; 

    public MyAutoCompleteAdapter(Server server, Context context, int textViewResourceId) { 
     super(context, textViewResourceId); 
     mServer = server; 
    } 

    @Override 
    public int getCount() { 
     return mData.size(); 
    } 

    @Override 
    public String getItem(int index) { 
     return mData.get(index); 
    } 

    @Override 
    public Filter getFilter() { 
     Filter myFilter = new Filter() { 
      @Override 
      protected FilterResults performFiltering(CharSequence constraint) { 
       // This method is called in a worker thread 

       FilterResults filterResults = new FilterResults(); 
       if(constraint != null) { 
        try { 
         // Here is the method (synchronous) that fetches the data 
         // from the server 
         List<String> results = mServer.searchForItems(constraint.toString()); 
         filterResults.values = results; 
         filterResults.count = results.size(); 
        } 
        catch(Exception e) {} 

       } 
       return filterResults; 
      } 

      @Override 
      protected void publishResults(CharSequence contraint, FilterResults results) { 
       if(results != null && results.count > 0) { 
        mData = (List<String>)results.values; 
        notifyDataSetChanged(); 
       } 
       else { 
        notifyDataSetInvalidated(); 
       } 
      } 
     }; 
     return myFilter; 
    } 
} 

EDIT: J'ai amélioré le code ci-dessus depuis que je suis parfois l'exception java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Pour résoudre ce problème, j'ai déplacé la mise à jour de mData à publishResults().

0

Cet extrait de code a fonctionné pour moi dans mon application. Mettez dans votre activité qui contient le ListView:

@Override 
public void onActivityResumed() // 
{ 
    if (favoritesHaveChanged(activity, productString)) // 
    { 
     m_adapter.clear(); 
     performAsyncTaskWithCallBack(activity); 
    } 
} 

Le rappel sera un écouteur d'événement qui est déclenché. Typiquement avec AsyncTasks vous pouvez utiliser onPostExecute() dans votre AsyncTask.

Questions connexes