2016-11-22 85 views
0

我正在嘗試使用Geocoder API構建地址搜索器,其中用戶鍵入位置名稱,並且所有相關地址都顯示在列表視圖中。Android:外部ListView更改的適配器問題

我在運行搜索時,出現此錯誤:

java.lang.IllegalStateException:適配器的內容 改變,但ListView控件沒有收到通知。確保您的適配器的 內容不是從後臺線程修改的,而是僅從修改的UI線程。

確保您的適配器在其內容更改時調用 notifyDataSetChanged()。

這是我實現:

SimpleStringAdapter adapter; 
ArrayList<String> items = new ArrayList<>(); 
ListView addressList; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_search_address); 

    addressList = (ListView) findViewById(R.id.addressList); 
    addressBox = (EditText) findViewById(R.id.addressBox); 

    //Search for locations when the user types in 
    addressBox.addTextChangedListener(new TextWatcher() { 
      @Override 
      public void onTextChanged(final CharSequence s, int start, int before, int count) { 
       //Search the typed location 
       SearchAddresses(searchText); 
      } 

      @Override 
      public void beforeTextChanged(CharSequence s, int start, int count, 
              int after) { 

      } 

      @Override 
      public void afterTextChanged(Editable s) { 

      } 
    }); 
} 

private void SearchAddresses(String searchText) { 
    Geocoder geoCoder = new Geocoder(this, Locale.getDefault()); 
    try { 
     List<Address> addresses = geoCoder.getFromLocationName(searchText, 5); 
     addressList.setAdapter(null); 

     if (addresses.size() != 0) { 
      //Add the Address line to the list 
      items.add(addresses.get(0).getAddressLine(0)); 
      //Populate the listview 
      adapter = new SimpleStringAdapter(this, items); 
      addressList.setAdapter(adapter); 
     } 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

而且ListView控件適配器只是簡單地設置文本到一個TextView。如果您需要查看,請告訴我。

我在做什麼錯?

+1

將notifydatasetchanged應用於您的適配器。 – LoveAndroid

+0

請告訴我在哪裏添加,關於代碼示例@LoveAndroid – Dinuka

+0

我見過幾個答案,說同樣的事情,但沒有一個說明我應該添加它和任何解釋:) – Dinuka

回答

1

不要onTextChanged()方法來初始化適配器每次。使用notifyDataSetChanged()。這裏是你的代碼的例子。

只需用您的代碼替換即可。而已。

SimpleStringAdapter adapter; 
ArrayList<String> items = new ArrayList<>(); 
ListView addressList; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_search_address); 

    addressList = (ListView) findViewById(R.id.addressList); 
    addressBox = (EditText) findViewById(R.id.addressBox); 

    adapter = new SimpleStringAdapter(this, items); 
    addressList.setAdapter(adapter); 

    //Search for locations when the user types in 
    addressBox.addTextChangedListener(new TextWatcher() { 
      @Override 
      public void onTextChanged(final CharSequence s, int start, int before, int count) { 
       //Search the typed location 
       SearchAddresses(searchText); 
      } 

      @Override 
      public void beforeTextChanged(CharSequence s, int start, int count, 
             int after) { 

      } 

      @Override 
      public void afterTextChanged(Editable s) { 

      } 
    }); 
} 

private void SearchAddresses(String searchText) { 
    Geocoder geoCoder = new Geocoder(this, Locale.getDefault()); 
    try { 
     List<Address> addresses =  geoCoder.getFromLocationName(searchText, 5); 
     addressList.setAdapter(null); 

     if (addresses.size() != 0) { 
      //Add the Address line to the list 
      items.add(addresses.get(0).getAddressLine(0)); 
      //Populate the listview 
      adapter.notifyDataSetChanged(); 

     } 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 
+0

這不會在列表視圖中顯示任何結果。這是對的嗎? – Dinuka

+0

是的,這是絕對正確的。它應該工作。 好的,我遇到了問題。 從SearchAddresses中刪除此行:addressList.setAdapter(null); 現在試試。 –

+0

這似乎工作,但我有一個小問題。打字時有輕微的明顯滯後。是否因爲多個請求被髮送到SearchAddresses方法? – Dinuka

1

試試這個添加notifyDataSetChanged到適配器: -

private void SearchAddresses(String searchText) { 
    Geocoder geoCoder = new Geocoder(this, Locale.getDefault()); 
    try { 
     List<Address> addresses = geoCoder.getFromLocationName(searchText, 5); 
     addressList.setAdapter(null); 

     if (addresses.size() != 0) { 
      //Add the Address line to the list 
      items.add(addresses.get(0).getAddressLine(0)); 
      //Populate the listview 
      adapter = new SimpleStringAdapter(this, items); 
      addressList.setAdapter(adapter); 
      adapter.notifyDataSetChanged(); 
     } 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 
+0

這可以工作,但我看到稍微滯後。我認爲這部分是因爲每次文本更改時都會初始化適配器 – Dinuka

+0

@DinukaJayasuriya Yup!你是對的 。它正在發生,因爲每次文本更改時都會初始化適配器。 – LoveAndroid