1

我使用谷歌的地方自動完成,我收到以下錯誤: (並不總是發生只有一些次)適配器的內容發生了變化,但ListView控件沒有收到通知,谷歌Android地方

java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread. Make sure your adapter calls notifyDataSetChanged() when its content changes. [in ListView(-1, class android.widget.ListPopupWindow$DropDownListView) with Adapter(class locationplacesautocomplete.GooglePlacesAutocompleteAdapter)] 

at android.widget.ListView.layoutChildren(ListView.java:1582) 
      at android.widget.AbsListView.onLayout(AbsListView.java:2627) 
      at android.view.View.layout(View.java:16821) 
      at android.view.ViewGroup.layout(ViewGroup.java:5328) 
      at android.widget.FrameLayout.layoutChildren(FrameLayout.java:573) 
      at android.widget.FrameLayout.onLayout(FrameLayout.java:508) 
      at android.view.View.layout(View.java:16821) 
      at android.view.ViewGroup.layout(ViewGroup.java:5328) 

閱讀以下消息後,我用runOnUiThread()爲notifyDataSetChanged(),但仍然無法正常工作。

我將添加適配器類:

package locationplacesautocomplete; 

import android.app.Activity; 
import android.content.Context; 
import android.widget.ArrayAdapter; 
import android.widget.Filter; 
import android.widget.Filterable; 
import java.util.ArrayList; 
import java.util.HashMap; 

import datatypes.AutoCompleteData; 

/** 
* This class implements the adapter for google places auto complete 
* Created by edenbensimon on 07/06/15. 
*/ 
public class GooglePlacesAutocompleteAdapter extends ArrayAdapter implements Filterable { 

    // Holds an array list with the results 
    private Object[] resultList; 
    private HashMap<String, String> result; 
    private Activity _activity; 

    // Default ctor 
    public GooglePlacesAutocompleteAdapter(Context context, int textViewResourceId, Activity activity) { 
     super(context, textViewResourceId); 
     _activity = activity; 
    } 

    @Override 
    public int getCount() { 
     return resultList.length; 
    } 

    @Override 
    public String getItem(int index) { 
     return resultList[index].toString(); 
    } 

    @Override 
    public Filter getFilter() { 
     Filter filter = new Filter() { 
      @Override 
      protected FilterResults performFiltering(CharSequence constraint) { 
       FilterResults filterResults = new FilterResults(); 
       if (constraint != null) { 
        // Retrieve the autocomplete results. 
        result = AutoCompleteLogic.autocomplete(constraint.toString()); 
        resultList = result.keySet().toArray(); 

        // Assign the data to the FilterResults 
        filterResults.values = resultList; 
        filterResults.count = resultList.length; 
       } 
       return filterResults; 
      } 
      @Override 
      protected void publishResults(CharSequence constraint, final FilterResults results) { 
       _activity.runOnUiThread(new Runnable() { 
        @Override 
        public void run() { 
         if (results != null && results.count > 0) { 
          notifyDataSetChanged(); 
         } else { 
          notifyDataSetInvalidated(); 
         } 
        } 
       }); 
      } 
     }; 
     return filter; 
    } 

    /** 
    * Returns an array list with only description about the place 
    */ 
    private ArrayList getDescOnly(ArrayList values) { 
     ArrayList returnValue = new ArrayList<String>(); 
     for (int i = 0; i < values.size(); i++) { 
      returnValue.add(((AutoCompleteData)values.get(i)).getDescription()); 
     } 

     return returnValue; 
    } 

    public HashMap<String, String> getResult() { 
     return result; 
    } 

    public void setResult(HashMap<String, String> result) { 
     this.result = result; 
    } 

    public Object[] getResultList() { 
     return resultList; 
    } 

    public void setResultList(Object[] resultList) { 
     this.resultList = resultList; 
    } 
} 

這是我的計算邏輯

/** 
* This method gets the current input and returns list with all suitable cities 
* @return 
*/ 
public static HashMap autocomplete(String input) { 

    // Initialize the variable 
    HashMap<String, String> result = null; 

    // The url connection will be used 
    HttpURLConnection conn = null; 

    // String builder for the json results 
    StringBuilder jsonResults = new StringBuilder(); 
    try { 
     // Build the string for the url 
     StringBuilder sb = new StringBuilder(PLACES_API_BASE + TYPE_AUTOCOMPLETE + OUT_JSON); 
     sb.append("?key=" + API_KEY); 

     // This parameter is used for choosing specific country, not must. 
     sb.append("&input=" + URLEncoder.encode(input, "utf8")); 


    // Create the url 
    URL url = new URL(sb.toString()); 
    conn = (HttpURLConnection) url.openConnection(); 
    InputStreamReader in = new InputStreamReader(conn.getInputStream()); 

    // Load the results into a StringBuilder 
    int read; 
    char[] buff = new char[1024]; 
    while ((read = in.read(buff)) != -1) { 
     jsonResults.append(buff, 0, read); 
    } 
} catch (MalformedURLException e) { 
    Log.e(LOG_TAG, "Error processing Places API URL", e); 
    return result; 
} catch (IOException e) { 
    Log.e(LOG_TAG, "Error connecting to Places API", e); 
    return result; 
} finally { 
    if (conn != null) { 
     conn.disconnect(); 
    } 
} 

try { 
    // Create a JSON object hierarchy from the results 
    JSONObject jsonObj = new JSONObject(jsonResults.toString()); 
    JSONArray predsJsonArray = jsonObj.getJSONArray("predictions"); 

    // Extract the Place descriptions from the results 
    result = new HashMap<>(predsJsonArray.length()); 
    for (int i = 0; i < predsJsonArray.length(); i++) { 
     result.put(predsJsonArray.getJSONObject(i).getString("description"), 
        predsJsonArray.getJSONObject(i).getString("place_id")); 
    } 
} catch (JSONException e) { 
    Log.e(LOG_TAG, "Cannot process JSON results", e); 
} 

return result; 

}

有沒有人有一個想法,什麼是錯?拿什麼卡?

非常感謝提前, 伊甸園

+0

做一些調試;它何時發生?這個'if(results!= null && results.count> 0)'可能是罪魁禍首。 – natario

+0

我目前正在嘗試調試,但問題是它在很多時候發生過一次..很難趕上它。感謝與該點,如果,我現在再次檢查它 – user3900146

+0

@ mvai到目前爲止它似乎並不相關 – user3900146

回答

0

嘗試調用適配器notifyDataSetChanged每個數據更改後/套。

+0

你能解釋在哪裏,爲什麼? – user3900146

+1

由於您使用setter方法更新數據,但小部件不會知道此更新。所以小部件和適配器不同步。 'notifyDataSetChanged'將通知小部件與適配器同步。 – spgodara

+0

感謝您的好解釋。你的意思是在執行過濾後設置它? – user3900146

相關問題