Weird ListView sort - android

I've got following problem:
As you can see on the picture, the CITROEN group header is not above the all Citroen car models, like e.g DACIA.
The weird thing is that there is around 20 Car Brands like BMW,AUDI...and every group header is above its children items, but not the CITROEN.
This listview is populated from the html file, which has the following structure:
<optgroup label="BMW">
<option value="225" >BMW X3 3.0si</option>
<option value="226" >BMW X5 3.0d A/T</option>
<option value="227" >BMW X5 4.8i A/T</option>
</optgroup>
<optgroup label="CITROËN">
<option value="67" >CITROËN C1 1.0i</option>
<option value="68" >CITROËN C1 1.4 HDi</option>
<option value="69" >CITROËN C2 1.1i</option>
I'm using custom adapter. Here is the source code of the comparing method:
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
progressDialog.dismiss();
adapter = new ModelsAdaper(CarsList.this, generateData());
/*Should sort the ListView alphabetically*/
adapter.sort(new Comparator<Model>() {
#Override
public int compare(Model lhs, Model rhs) {
return lhs.getTitle().compareTo(rhs.getTitle());
}
});
setListAdapter(adapter);
The generateData() method:
private ArrayList<Model> generateData() {
models = new ArrayList<Model>();
/*This loop adds car brands to the listview*/
for(String s: brands){
models.add(new Model(R.drawable.alfa_romeo_icon_52,s));
}
/*This loop inserts car models into the listview*/
int key;
for(int i = 0; i < hashMap.size(); i++) {
key = hashMap.keyAt(i);
models.add(new Model(hashMap.get(key)));
}
return models;
}
And finally, the Model class
public class Model {
private String title;
private boolean isGroupHeader = false;
private int icon;
/**
* This constructor will be used for creating instance od target_item
* #param title is content of the item
*/
public Model(String title){
this.title = title;
}
/**
* This constructor will be used for group headers
* #param icon is icon of the group
* #param title is name of the group
*/
public Model(int icon, String title){
this.icon = icon;
this.title = title;
isGroupHeader = true;
}
EDIT
As requested, here is the HTMLParser class source code. Its constructor is called from CarsList Activity, which extends ListActivity
public class HTMLParser {
private String value;
private InputStream is = null;
private Context context=null;
private org.jsoup.nodes.Document document = null;
SparseArray<String> hashMap = new SparseArray<String>();
private ArrayList<String> modelsList = new ArrayList<String>();
private ArrayList<String> brandsList = new ArrayList<String>();
/**
* Constructor is used to pass instance of CarsList Context to get html asset
* #param context instance of the CarsList activity context
*/
public HTMLParser(Context context) throws IOException {
this.context = context;
is = context.getAssets().open("modely aut.html");
document = Jsoup.parse(is,"UTF-8","http://example.com");
}
/**
* The purpose of this method is to parse car brands from html asset
* #return ArrayList of car brands
*/
public ArrayList<String> parseCarBrands(){
Elements models = document.select("optgroup");
for (Element e: models){
brandsList.add(e.attr("label"));
}
return brandsList;
}
/**
* Method parses all car models from html asset. For IO safety operations, it is recommended to call this method
* after parseCarBrands() method, because parseCarModels() method closes inputStream.
* #return SparseArray consisting of key: carID and value: car model
*/
public SparseArray<String> parseCarModels(){
try {
Elements models = document.select("option");
for (Element e: models){
int res = new Scanner(e.toString()).useDelimiter("\\D+").nextInt();
value = e.html();
modelsList.add(value);
hashMap.put(res,value);
}
} finally {
if(is!=null){
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return hashMap;
}
}
EDIT 2 Possible source of the problem
I have made some tests with the same code, but only in simple java project. It looks like some encoding issue.
when using
Elements models2 = doc.select("option");
for (Element e: models2){
int key = Integer.parseInt(e.attr("value"));
String modelName = e.html();
modelsList.add(value);
}
the output from System.out.println(modelName) looks like this:
CITROËN C4 1.6i 16V EP turbo
but when parsing just a brand names using String s = e.attr("label"); the output is as it should be.
Do you have any idea, where the problem can be? I will post other parts of the code, if it will be necessary.
I would like to thank you for all your time and effort you give to my question

I've made it, but it's such a stupid thing. I've changed few things in the parseCarModels()
First of all, I've changed the return type to LinkedHashMap<Integer,String>. Parsing the html now seems to be faster.
Then I've changed the value variable from String to CharSequence. This allowed me to use Html.fromHtml(e.html), so the final code looks like this:
public LinkedHashMap<Integer,String> parseCarModels(){
Elements models = document.select("option");
int key;
CharSequence value;
for(Element e: models){
key = Integer.parseInt(e.attr("value"));
value = Html.fromHtml(e.html());
hashMap.put(key,value.toString());
}
if(is!=null){
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return hashMap;
}
Thank you for all your help. I really appreciate that. I hope that this code isn't very ineffective

Related

comparing two lists return false (android)

I'm trying to compare two lists. First list has values from switches of class1 and the other list I'm trying to retreive it from a site (class2). I'm trying to compare those two lists but if statement returns no. For example
I'm checking the soy switch and when I scan a barcode the fetched list has soy in it but text returns no. Help me please!
Here is the code that I wrote.
Class1
public ArrayList<String> soy2= new ArrayList<String>();
Switch soy;
.....................
if (soy.isChecked()) {
checked();
}
else {
textView.setText("blahblah");
}
public void checked() {
soy2.add("Soy");
soy2.add("Σόγια");
soy2.add("soja");
soy2.add("Soybeans");
soy2.add("soybeans");
soy2.add("en:soybeans");
//checkedAllergens.add(soy2);
}
public ArrayList<String> getList() {
return soy2;
}
Class2
public Manage checkd;
String fetchedAllergens=new String();
List<String> fetchedAllergensList = new ArrayList<String>();
.......................
public void test() {
checkd = new Manage();
ArrayList<String> list = checkd.getList();
System.out.println(list);
System.out.println(fetchedAllergensList);
if(fetchedAllergensList.contains(list))
{
testtxt.setText("yes");
}
else
{
testtxt.setText("no");
}
//Test method is calling by a click listener and i get the list from class 2 with the code below
protected String doInBackground(String... strings) {
final String barcode = strings[0];
#Nullable
String allergens = null;
try {
final String jsonStr = Jsoup.connect(
"https://world.openfoodfacts.org/api/v0/product/" + barcode + ".json")
.ignoreContentType(true)
.execute()
.body();
final JSONObject jsonObj = new JSONObject(jsonStr);
if (jsonObj.has("product")) {
JSONObject productNode = jsonObj.getJSONObject("product");
allergens = productNode.getString("allergens");
}
} catch (IOException | JSONException e) {
e.printStackTrace();
}
fetchedAllergens=allergens;
fetchedAllergensList = Arrays.asList(fetchedAllergens.split(","));
System.out.print(fetchedAllergensList);
return allergens;
}
Here if(fetchedAllergensList.contains(list))
.contains() is expecting an element of your list not an arraylist
ex.
fetchedAllergensList.contains("Soy")
If you want to compare two list, try this
listA.containsAll(listB) && listB.containsAll(listA)
compare lists if equal
To check if list2 contains element that is also present in list1
public boolean elementExist(ArrayList<String> list1, ArrayList<String> list2) {
for (int i= 0; i < list2.length() i++) {
if (list1.contains(list2[i])) {
// element list2[i] exist in list1
return true;
}
}
return false;
}
This method will return true if list2 has element that is also in list1

How can I manage to arrange an ArrayList of a custom Object in alphabetical order, which contains two different strings?

Now in detail. I am writing an App for a dictionary. For that I have created a custom Object called Word. This Word contains the term and its' corresponding translation:
public class Word implements Serializable {
private int _id;
private int wordType;
private String engWordSi;
private String okyWordPl;
private String engWordPl;
private String okyWordSi;
private String engEx;
private String okyEx;
/** Creates a custom class, which allows save a term, it's translation, as well as the plural and example in both
* languages
* #param _id saves the Id of the Word in the Database
* #param engWordSi saves the English translation of the word
* #param okyWordSi saves the Oshikwanyama translation of the word
* #param wordType saves the type of word in form of a number:
* 0 = phrase; 1 = noun; 2 = verb; 3 = adjective; 4 = pronoun; 5 = other
*/
public Word(int _id, int wordType, String engWordSi, String okyWordSi){
this._id = _id;
this.wordType = wordType;
this.engWordSi = engWordSi;
this.okyWordSi = okyWordSi;
}public int get_id(){
return _id;
}
public void set_id(int i){
_id = i;
}
public int getWordType(){
return wordType;
}
public void setWordType(int i){
if(i < 0 || i > 6){
return;
}
wordType = i;
}
public String getEngWordSi(){
return engWordSi;
}
public void setEngWordSi(String word){
engWordSi = word;
}
public String getOkyWordSi(){
return okyWordSi;
}
public void setOkyWordSi(String word){
okyWordSi = word;
}
public String getEngWordPl(){
return engWordPl;
}
public void setEngWordPl(String word){
engWordPl = word;
}
public String getOkyWordPl(){
return okyWordPl;
}
public void setOkyWordPl(String word){
okyWordPl = word;
}
public String getEngEx(){
return engEx;
}
public void setEngEx(String word){
engEx = word;
}
public String getOkyEx(){
return okyEx;
}
public void setOkyEx(String word){
okyEx = word;
}
The data is loaded via a php file connected to the database. The ORDER BY statement only allows me to choose one language to order the results by. But what I need is, that the search term, which might be found in words of both languages, defines if the English word or the Oshikwanyama word is the word which is being arranged in the order. I have check which translation to use in each case. My guess would be to do it in onPostExecute(). The data is returned by the PHP file in the JSON format. From there I put them into an ArrayList.
private class Query extends AsyncTask<Void, Void, Void>{
#Override
protected void onPostExecute(Void aVoid) {
try{
JSONArray jsonArray = new JSONArray(result);
for (int i = 0; i < jsonArray.length(); i++){
JSONObject jsonObject = jsonArray.getJSONObject(i);
Word word = new Word(jsonObject.getInt("_id"), jsonObject.getInt("type"), jsonObject.getString("eng"), jsonObject.getString("oky") );
arrayList.add(word);
Log.d("JSON", word.toString());
}
}catch (JSONException e){
e.printStackTrace();
}
ProgressBar bar = (ProgressBar) findViewById(R.id.bar);
bar.setVisibility(View.GONE);
Button button = (Button) findViewById(R.id.SearchButton);
button.setVisibility(View.VISIBLE);
super.onPostExecute(aVoid);
if (arrayList.isEmpty()){
Toast.makeText(SearchActivity.this, "Unfortunately there were no results, the missing word was sent to our developers.", Toast.LENGTH_LONG).show();
return;
}
Intent intent = new Intent(SearchActivity.this, ResultActivity.class);
ItemDetailsWrapper wrapper = new ItemDetailsWrapper(arrayList);
intent.putExtra("results", wrapper);
intent.putExtra("term", searchTerm);
startActivity(intent);
}
InputStream inputStream = null;
String result = "";
#Override
protected void onPreExecute() {
if (arrayList != null){
arrayList.clear();}
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... voids) {
try{
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(uri.toString());
//httpPost.setEntity(new UrlEncodedFormEntity(null));
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
inputStream = httpEntity.getContent();
}
catch (UnsupportedEncodingException e1){
e1.printStackTrace();
} catch (ClientProtocolException e2){
e2.printStackTrace();
}catch (IllegalStateException e3){
e3.printStackTrace();
}catch (IOException e4){
e4.printStackTrace();
}try{
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder stringBuilder = new StringBuilder();
String line = null;
while ((line = bufferedReader.readLine()) != null){
stringBuilder.append(line + "\n");
}
inputStream.close();
result = stringBuilder.toString();
}catch (IOException e){
e.printStackTrace();
}
return null;
}
}}
I already have a place to check whether the term searched for is contained in the English or Oshikwanyama word. There I use it to define the flag used in the layout.
public class WordAdapter extends ArrayAdapter<Word> {
private Context mContext;
private List<Word> wordList = new ArrayList<>();
private int srcCode;
private String term;
/** uses words and puts them into a list
*
* #param context stores the context of the calling activity
* #param list stores the ArrayList that was passed into the constructor, and which contains the
* content
* #param searchTerm stores the term that was searched for in SearchActivity to later compare it
* to the contents of the Word and to arrange the correct flag for the source
* language
*/
public WordAdapter(#NonNull Context context, ArrayList<Word> list, String searchTerm) {
super(context, 0 , list);
mContext = context;
wordList = list;
term = searchTerm;
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
View listItem = convertView;
if(listItem == null){
listItem = LayoutInflater.from(mContext).inflate(R.layout.list_item,parent,false);}
final Word currentWord = wordList.get(position);
//Add Images for the flags of the countries and the flag
final TextView sourceTerm = (TextView) listItem.findViewById(R.id.searchTerm);
final TextView translationTerm = (TextView) listItem.findViewById(R.id.translationTerm);
ImageView flag = (ImageView) listItem.findViewById(R.id.src_flag);
ImageButton button = (ImageButton) listItem.findViewById(R.id.flag);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(getContext(), EditorActivity.class);
intent.putExtra("mode", "report");
intent.putExtra("id", currentWord.get_id());
intent.putExtra("source", sourceTerm.getText());
intent.putExtra("trans", translationTerm.getText());
getContext().startActivity(intent);
}
});
if (currentWord.getOkyWordPl() == null){
currentWord.setOkyWordPl("");
}
if (currentWord.getEngWordPl() == null){
currentWord.setEngWordPl("");
}
if (currentWord.getEngWordSi().contains(term) || currentWord.getEngWordPl().contains(term)){
srcCode = 0;
}
if (currentWord.getOkyWordSi().contains(term) || currentWord.getOkyWordPl().contains(term)){
srcCode = 1;
}
if (srcCode == 0){
sourceTerm.setText(currentWord.getEngWordSi());
translationTerm.setText(currentWord.getOkyWordSi());
flag.setImageResource(R.drawable.britain);
}
if (srcCode == 1){
sourceTerm.setText(currentWord.getOkyWordSi());
translationTerm.setText(currentWord.getEngWordSi());
flag.setImageResource(R.drawable.namibia);
}
return listItem;
}}
Thank you in advance. :)
EDIT:
Adding example Words:
1.
EngWordSi: good
OkyWordSi: nawa
wordType: 2
2.
EngWordSi: good morning
OkyWordSi: wa lele po?
wordType: 0
3.
EngWordSi: morning
OkyWordSi: ongula
WordType: 1
what you can do is, sort your object property like below in your adapter,
public WordAdapter(#NonNull Context context, ArrayList<Word> list, String searchTerm) {
super(context, 0 , list);
mContext = context;
wordList = list;
term = searchTerm;
Collections.sort(list, new Comparator<Word>() {
#Override
public int compare(Word word1, word2) {
return word1.getEngWordSi().compareToIgnoreCase(word2.getEngWordSi());
}
});
}
this is helpful to you.
Here is my demo code
public class Main {
static class Word{
String prority1;
#Override
public String toString() {
return "Word{" +
"prority1='" + prority1 + '\'' +
'}';
}
}
public static void main(String[] args) {
ArrayList<Word> words = new ArrayList<>();
Word word;
for (int i = 0; i < 5; i++) {
word =new Word();
word.prority1 = "aaaa"+(5-i);
words.add(word);
System.out.println("wrod "+i+" is "+word);
}
Collections.sort(words, new Comparator<Word>() {
#Override
public int compare(Word o1, Word o2) {
int ret = o1.prority1.compareTo(o2.prority1);
if (ret > 0) {
return 1;
} else if (ret < 0) {
return -1;
}
return 0;
}
});
System.out.println("after sort check words");
for (Word w : words) {
System.out.println("check word:"+w);
}
}
}
and following is console's output:
wrod 0 is Word{prority1='aaaa5'}
wrod 1 is Word{prority1='aaaa4'}
wrod 2 is Word{prority1='aaaa3'}
wrod 3 is Word{prority1='aaaa2'}
wrod 4 is Word{prority1='aaaa1'}
after sort check words
check word:Word{prority1='aaaa1'}
check word:Word{prority1='aaaa2'}
check word:Word{prority1='aaaa3'}
check word:Word{prority1='aaaa4'}
check word:Word{prority1='aaaa5'}
Hope that can help you.

Performance comparison custom class versus arrays

Is it more performant to create a class
public class test {
private Circle c;
private String mac;
private Short abstand;
private Location ort;
public test (String mac, Circle c, Short abstand, Location ort){
this.c = c;
this.mac = mac;
this.abstand = abstand;
this.ort = ort;
}
public String erhalteMac()
{
return mac;
}
//etc.
}
Create an array list by using
ArrayList<test> karte = new ArrayList<test>();
and adding
test t = new test();
t.mac = "...";
karte.add(t);
etc.
to then see if there is an object that has a certain property
public static boolean hM(ArrayList<object> list, String mac) {
for (object object2 : list) {
if (object2.erhalteMac().equals(mac))
{
//work with object2 here.
return true;
}
}
return false;
}
versus simply creating four arrays for each type and iterating through only the mac array in my case and use the index of the matching mac string in each other array to make changes?
The Array method would be a tiny bit faster than the simple List, but
a HashMap would be a lot faster when there are more than a few object instances.

AutoCompleteTextView with Google Places shown in ListView just like Uber

I need to make screen similar to this. I think it has autocompletetextview and listview to display returned results. Google Place API is used here to auto suggest places and listview adapter is updated accordingly.
Please any kind of help is appreciated.
Thanks in advance.
Checked android sample project on AutoComplete for places too. But it is not having any listview to display results. Instead it shows results in autocompletetextview spinner. Any modification we can do with that project
Link to google sample project
You can achieve this exactly by using EditText and ListView, and not AutoCompleteTextView. Characters are entered in the EditText on the basis of which the results in the ListView are filtered by calling the GooglePlacesAutomplete webservice. The following is the code:
This is your layoout file ( EditText with ListView )
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff"
tools:context="com.example.siddarthshikhar.liftsharesample.EnterLocationActivity">
<EditText
android:paddingLeft="#dimen/activity_horizontal_margin"
android:layout_width="250dp"
android:layout_height="35dp"
android:textColorHint="#ffffff"
android:id="#+id/edEnterLocation"
android:textColor="#ffffff"
android:textSize="#dimen/abc_text_size_medium_material"
android:layout_alignParentLeft="true"
android:backgroundTint="#00000000"
android:gravity="start|center">
<requestFocus />
</EditText>
<ListView android:id="#+id/listView1" android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/filterLayout"/>
</RelativeLayout>
In your corresponding Activity, access this EditText and apply Filterable. You have to use GooglePlacesAutompleteAdapter for this.
The following is the GooglePlacesAutompleteAdapter :
public class GooglePlacesAutocompleteAdapter extends ArrayAdapter implements Filterable {
private static final String LOG_TAG = "Google Places Autocomplete";
private static final String PLACES_API_BASE = "https://maps.googleapis.com/maps/api/place";
private static final String TYPE_AUTOCOMPLETE = "/autocomplete";
private static final String OUT_JSON = "/json";
private static final String API_KEY = "your_api_key";
private ArrayList<String> resultList;
private Context context = null;
public GooglePlacesAutocompleteAdapter(Context context, int textViewResourceId) {
super(context, textViewResourceId);
this.context = context;
}
#Override
public int getCount() {
if(resultList != null)
return resultList.size();
else
return 0;
}
#Override
public String getItem(int index) {
return resultList.get(index);
}
public ArrayList<String> autocomplete(String input) {
ArrayList<String> resultList = null;
ArrayList<String> descriptionList = null;
HttpURLConnection conn = null;
StringBuilder jsonResults = new StringBuilder();
try {
StringBuilder sb = new StringBuilder(PLACES_API_BASE + TYPE_AUTOCOMPLETE + OUT_JSON);
sb.append("?key=" + API_KEY);
sb.append("&components=country:in");
sb.append("&input=" + URLEncoder.encode(input, "utf8"));
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 resultList;
} catch (IOException e) {
Log.e(LOG_TAG, "Error connecting to Places API", e);
return resultList;
} finally {
if (conn != null) {
conn.disconnect();
}
}
try {
// Create a JSON object hierarchy from the results
Log.d("yo",jsonResults.toString());
JSONObject jsonObj = new JSONObject(jsonResults.toString());
JSONArray predsJsonArray = jsonObj.getJSONArray("predictions");
// Extract the Place descriptions from the results
resultList = new ArrayList(predsJsonArray.length());
descriptionList = new ArrayList(predsJsonArray.length());
for (int i = 0; i < predsJsonArray.length(); i++) {
resultList.add(predsJsonArray.getJSONObject(i).toString());
descriptionList.add(predsJsonArray.getJSONObject(i).getString("description"));
}
saveArray(resultList.toArray(new String[resultList.size()]), "predictionsArray", getContext());
} catch (JSONException e) {
Log.e(LOG_TAG, "Cannot process JSON results", e);
}
return descriptionList;
}
#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.
resultList = autocomplete(constraint.toString());
// Assign the data to the FilterResults
filterResults.values = resultList;
filterResults.count = resultList.size();
}
return filterResults;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
if (results != null && results.count > 0) {
setImageVisibility();
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
};
return filter;
}
}
Access the adapter and apply getFilter() to the EditText in the corresponding Activity. The following is to be added in your Activity corresponding to your layout created earlier:
dataAdapter = new GooglePlacesAutocompleteAdapter(EnterLocationActivity.this, R.layout.adapter_google_places_autocomplete){
listView = (ListView) findViewById(R.id.listView1);
// Assign adapter to ListView
listView.setAdapter(dataAdapter);
//enables filtering for the contents of the given ListView
listView.setTextFilterEnabled(true);
etEnterLocation.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
dataAdapter.getFilter().filter(s.toString());
}
});
This should get you going. You can modify your layout as you want. This basically loads the autocomplete data in a ListView.
Here is an example of how to do just that.
You have the bonus of getting any of the AutocompletePrediction from the adapter. Just call getItem(int position) from the AutoCompleteTextView's AdapterView.OnItemClickListener for example and use any data from the prediction clicked as you wish.
Links relevant code:
/**
* Adapter that handles Autocomplete requests from the Places Geo Data API.
* {#link AutocompletePrediction} results from the API are frozen and stored directly in this
* adapter. (See {#link AutocompletePrediction#freeze()}.)
* <p>
* Note that this adapter requires a valid {#link com.google.android.gms.common.api.GoogleApiClient}.
* The API client must be maintained in the encapsulating Activity, including all lifecycle and
* connection states. The API client must be connected with the {#link Places#GEO_DATA_API} API.
*/
public class PlaceAutocompleteAdapter
extends ArrayAdapter<AutocompletePrediction> implements Filterable {
private static final String TAG = "PlaceAutocompleteAdapter";
private static final CharacterStyle STYLE_BOLD = new StyleSpan(Typeface.BOLD);
/**
* Current results returned by this adapter.
*/
private ArrayList<AutocompletePrediction> mResultList;
/**
* Handles autocomplete requests.
*/
private GoogleApiClient mGoogleApiClient;
/**
* The bounds used for Places Geo Data autocomplete API requests.
*/
private LatLngBounds mBounds;
/**
* The autocomplete filter used to restrict queries to a specific set of place types.
*/
private AutocompleteFilter mPlaceFilter;
/**
* Initializes with a resource for text rows and autocomplete query bounds.
*
* #see android.widget.ArrayAdapter#ArrayAdapter(android.content.Context, int)
*/
public PlaceAutocompleteAdapter(Context context, GoogleApiClient googleApiClient,
LatLngBounds bounds, AutocompleteFilter filter) {
//change the layout nex for your own if you'd like
super(context, android.R.layout.simple_expandable_list_item_2, android.R.id.text1);
mGoogleApiClient = googleApiClient;
mBounds = bounds;
mPlaceFilter = filter;
}
/**
* Sets the bounds for all subsequent queries.
*/
public void setBounds(LatLngBounds bounds) {
mBounds = bounds;
}
/**
* Returns the number of results received in the last autocomplete query.
*/
#Override
public int getCount() {
return mResultList.size();
}
/**
* Returns an item from the last autocomplete query.
*/
#Override
public AutocompletePrediction getItem(int position) {
return mResultList.get(position);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = super.getView(position, convertView, parent);
// Sets the primary and secondary text for a row.
// Note that getPrimaryText() and getSecondaryText() return a CharSequence that may contain
// styling based on the given CharacterStyle.
AutocompletePrediction item = getItem(position);
TextView textView1 = (TextView) row.findViewById(android.R.id.text1);
TextView textView2 = (TextView) row.findViewById(android.R.id.text2);
textView1.setText(item.getPrimaryText(STYLE_BOLD));
textView2.setText(item.getSecondaryText(STYLE_BOLD));
return row;
}
/**
* Returns the filter for the current set of autocomplete results.
*/
#Override
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
// We need a separate list to store the results, since
// this is run asynchronously.
ArrayList<AutocompletePrediction> filterData = new ArrayList<>();
// Skip the autocomplete query if no constraints are given.
if (constraint != null) {
// Query the autocomplete API for the (constraint) search string.
filterData = getAutocomplete(constraint);
}
results.values = filterData;
if (filterData != null) {
results.count = filterData.size();
} else {
results.count = 0;
}
return results;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
if (results != null && results.count > 0) {
// The API returned at least one result, update the data.
mResultList = (ArrayList<AutocompletePrediction>) results.values;
notifyDataSetChanged();
} else {
// The API did not return any results, invalidate the data set.
notifyDataSetInvalidated();
}
}
#Override
public CharSequence convertResultToString(Object resultValue) {
// Override this method to display a readable result in the AutocompleteTextView
// when clicked.
if (resultValue instanceof AutocompletePrediction) {
return ((AutocompletePrediction) resultValue).getFullText(null);
} else {
return super.convertResultToString(resultValue);
}
}
};
}
/**
* Submits an autocomplete query to the Places Geo Data Autocomplete API.
* Results are returned as frozen AutocompletePrediction objects, ready to be cached.
* objects to store the Place ID and description that the API returns.
* Returns an empty list if no results were found.
* Returns null if the API client is not available or the query did not complete
* successfully.
* This method MUST be called off the main UI thread, as it will block until data is returned
* from the API, which may include a network request.
*
* #param constraint Autocomplete query string
* #return Results from the autocomplete API or null if the query was not successful.
* #see Places#GEO_DATA_API#getAutocomplete(CharSequence)
* #see AutocompletePrediction#freeze()
*/
private ArrayList<AutocompletePrediction> getAutocomplete(CharSequence constraint) {
if (mGoogleApiClient.isConnected()) {
Log.i(TAG, "Starting autocomplete query for: " + constraint);
// Submit the query to the autocomplete API and retrieve a PendingResult that will
// contain the results when the query completes.
PendingResult<AutocompletePredictionBuffer> results =
Places.GeoDataApi
.getAutocompletePredictions(mGoogleApiClient, constraint.toString(),
mBounds, mPlaceFilter);
// This method should have been called off the main UI thread. Block and wait for at most 60s
// for a result from the API.
AutocompletePredictionBuffer autocompletePredictions = results
.await(60, TimeUnit.SECONDS);
// Confirm that the query completed successfully, otherwise return null
final Status status = autocompletePredictions.getStatus();
if (!status.isSuccess()) {
Toast.makeText(getContext(), "Error contacting API: " + status.toString(),
Toast.LENGTH_SHORT).show();
Log.e(TAG, "Error getting autocomplete prediction API call: " + status.toString());
autocompletePredictions.release();
return null;
}
Log.i(TAG, "Query completed. Received " + autocompletePredictions.getCount()
+ " predictions.");
// Freeze the results immutable representation that can be stored safely.
return DataBufferUtils.freezeAndClose(autocompletePredictions);
}
Log.e(TAG, "Google API client is not connected for autocomplete query.");
return null;
}
}
You can achieve automcomplete textview in a simpler way by adding the below code to your layout
<fragment
android:id="#+id/place_autocomplete_fragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:name="com.google.android.gms.location.places.ui.PlaceAutocompleteFragment"
/>
For using the above code you need to configure few settings for your application in Google develepor console .Please refer Android Places autocomplete example for complete example

When passing 2 identical Parcable Classes, 1 is null

i have a weird issue.
I'm trying to pass 2 parcable classesfrom one activity to another.
I define both of them the exact same way, but of them is null.
The parcable class :
class Friends implements Parcelable {
private ArrayList<Integer> ids = new ArrayList<Integer>();
private ArrayList<String> names = new ArrayList<String>();
private ArrayList<Bitmap> images = new ArrayList<Bitmap>();
public void addId(Integer id)
{
ids.add(id);
}
public void addName(String name){
names.add(name);
}
public void addImage(Bitmap img){
images.add(img);
}
public ArrayList<Integer> getIds() {
return ids;
}
public ArrayList<String> getNames() {
return names;
}
public ArrayList<Bitmap> getImages() {
return images;
}
#Override
public int describeContents() {
// TODO Auto-generated method stub
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeList(ids);
dest.writeList(names);
dest.writeList(images);
}
public static final Parcelable.Creator<Friends> CREATOR = new Parcelable.Creator<Friends>() {
public Friends createFromParcel(Parcel in) {
return new Friends(in);
}
public Friends[] newArray(int size) {
return new Friends[size];
}
};
public Friends(Parcel in){
in.readList(ids, null);
in.readList(names, null);
in.readList(images, null);
}
public Friends(Integer id, String name, Bitmap img) {
ids.add(id);
names.add(name);
images.add(img);
}
public Friends(){
}
The Sending part :
for(Integer position : selectedIds)
{
String name = a.getItem(position).getFriendName();
int id = a.getItem(position).getFriendId();
Bitmap img = a.getItem(position).getFriendImage();
Log.e("ID",String.valueOf(id));
selectedFriends.addId(new Integer(id));
selectedFriends.addName(name);
selectedFriends.addImage(img);
}
for(int position=0;position<list.getCount(); position++)
{
String name = a.getItem(position).getFriendName();
int id = a.getItem(position).getFriendId();
Bitmap img = a.getItem(position).getFriendImage();
Log.e("All IDs",String.valueOf(id));
allFriends.addId(new Integer(id));
allFriends.addName(name);
allFriends.addImage(img);
}
b.putParcelable("selecet_friends", selectedFriends);
b.putParcelable("all_friends", allFriends);
data.putExtras(b);
Both of the loops are being runned ( i can see the logs), all variables you don't see are being initialized correctly, everything is fine.
The Reciving part :
i define both as null :
private Friends selectedFriends = null;
private Friends allFriends = null;
And handle the onResult like this :
Log.e("Result","yessss");
Friends all_friends = (Friends)data.getParcelableExtra("all_friends");
Friends selected_friends = (Friends)data.getParcelableExtra("selected_friends");
allFriends = all_friends;
selectedFriends = selected_friends;
if(selectedFriends != null){
Log.e("is null","No");
}
if(allFriends != null){
Log.e("is all null","No");
}
Does anyone know how come the selectedFriends is null when allFriends is not?
EDIT:
Just a thought, but maybe it's because i put 2 parcables on a Bundle?
just i just add 2 bundles?
In the sending method you have a typo in this line:
b.putParcelable("selecet_friends", selectedFriends);
try this instead:
b.putParcelable("selected_friends", selectedFriends);
Also, you should use more specific names for the keys. The documentation for putExtras() says:
Add a set of extended data to the intent. The keys must include a
package prefix, for example the app com.android.contacts would use
names like "com.android.contacts.ShowAll

Categories

Resources