2016-11-22 50 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