1

ArrayAdapterで動作するAutocompleteTextViewがあります。テキストが変更されると、アダプタはWebサービスから更新されます。この更新は、AsyncTaskで行われます。これは、良い方法であるはずです。これは、押されたすべてのキーの後の提案が、以前押されたキーで取得された文字列に基づいているため、多かれ少なかれ動作しています。 このページはいくつか問題がありますが、私の答えはありません。とにかく、私は解決策を持っていましたが、効率が悪く、「公式の解決策」がなぜ失敗するのか分かりません。ArrayAdapterは、AutoCompleteTextAdapterのWebserviceから遅く更新されます。

キーは、ArrayAdapterをバックグラウンドで更新する機能にあると思います。これは、私がWebサービスへの非同期呼び出しに何をすべきか:

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

私は(mAutoCompleteAdapter.clearで試してみました)とmAutoCompleteAdapter.notifyDataSetChangedを設定()どこでも、それは無意味ですしています。

答えて

2

私はまた、このアプローチを働かせるために多くの努力をしましたが、自分よりもうまくいくことはありませんでした。しかし、私はあなたが望むものを達成する別の方法を見つけました。 ArrayAdapterを拡張し、Filterableを実装します。このクラスは、ワーカースレッドでAutoCompleteTextViewによって呼び出されたデータベースから、実際のフェッチをやってます。

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:私は時々例外java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notificationを得たので、私は上記のコードを改善しています。これを修正するため、mDataの更新をpublishResults()に移動しました。

0

このコードスニペットは、私のアプリケーションで私のために働いていました。 ListViewが含まれているあなたの活動にこれを入れて:

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

コールバックがトリガーされるイベントリスナーになります。通常AsyncTasksAsyncTaskonPostExecute()を使用することができます。

関連する問題