Android autocomplete Google Places suggestions taking delays too long - android

I implemented in my app google places autocomplete on autocomplete textview.
At first when i was working on that part predictions came up on start of typing but now there is a delay after i start typing. Usually 5 seconds but sometimes over a half of minute !!!
The strange thing is that after i try autocomplete for first time(and wait that delay) and then go back and to autocomplete again the results show WITHOUT THE DELAY !!
I've run trough my code a million times but i just can't see why is that happening.
I've cleaned my project, rebooted my device and did solution on this topic:
How to improve performance of google places autocomplete suggestions?
Here is my code:
onCreate:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.dialog);
actvLocations = (AutocompleteTextViewCustom) findViewById(R.id.actvEnterLocation);
actvLocations.addTextChangedListener(new TextWatcher() {
#Override
public void afterTextChanged(Editable arg0) {
Log.e("dialog location after text changed", "AFTER");
}
#Override
public void beforeTextChanged(CharSequence arg0, int arg1,
int arg2, int arg3) {
// TODO Auto-generated method stub
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
String input = "";
// get input text
try {
input = "input=" + URLEncoder.encode(s.toString(), "utf-8"); // !!! check text coding for different counties !!!
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
/**
* activate error screen
*/
}
// set parameters for parsing
String parameters = input + "&" + "types=geocode" + "&" + "sensor=false";
// start places task for getting results from google
placesTask = new PlacesTask(listenerForAutocompleteCompletedTask, "getPredictions");
placesTask.execute(parameters);
}
});
// populate listview with previously browsed locations
ListView listviewPreviouslyBrowsedLocations = (ListView) findViewById(R.id.lvPreviouslyBrowsedLocations);
final ListViewAdapter adapterListview= new ListViewAdapter(context, listPreviouslyBrowsedLocations);
listviewPreviouslyBrowsedLocations.setAdapter(adapterListview);
listviewPreviouslyBrowsedLocations.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View convertView, int position, long arg3) {
List<HashMap<String, String>> list = new ArrayList<HashMap<String, String>>();
list.add(adapterListview.getParameters(position));
listenerForHeaderLocationChange.onLocationChangeExecuteThisMethod(list, false);
dismiss();
}
});
}
OnTaskCompleted listenerForAutocompleteCompletedTask = new OnTaskCompleted() {
#Override
public void onGetAutocompletePredictionsExecuteThisMethod( final List<HashMap<String, String>> listOfHashmapsForAutocompleteTextview) {
//making simple adapter for autocomplete textview
String[] from = new String[] { "description" };
int[] to = new int[] { android.R.id.text1 };
SimpleAdapter adapter = new SimpleAdapter(context, listOfHashmapsForAutocompleteTextview, android.R.layout.simple_dropdown_item_1line, from, to);
actvLocations.setAdapter(adapter);
/** autocomplete textview drop down items wouldn't show even after threshold set to 0 so .showDropDown() forces drop down items to show*/
actvLocations.showDropDown();
actvLocations.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View convertView, final int position, long arg3) {
dismiss();
final PlacesTask taskForLatLng = new PlacesTask(listenerForAutocompleteCompletedTask, "getPlaceLatLng");
#SuppressWarnings("unchecked")
HashMap<String, String> clickedItem = (HashMap<String, String>) parent.getItemAtPosition(position);
// set name of place for getting result back to header
nameOfSelectedPlace = clickedItem.get("description");
taskForLatLng.execute("placeid=" + clickedItem.get("place_id"));
}
});
}
Here is the async task where the delay happends.
I've marked where the delay happends
public class PlacesTask extends AsyncTask<String, Void, String>{
private OnTaskCompleted listener;
String typeOfResult;
String url = null;
public PlacesTask(OnTaskCompleted callerListener, String type) {
this.listener = callerListener;
this.typeOfResult = type;
switch (type) {
case "getPredictions":
url = "https://maps.googleapis.com/maps/api/place/autocomplete/";
break;
case "getPlaceLatLng":
url = "https://maps.googleapis.com/maps/api/place/details/";
break;
}
// this case is if we+re tying to get place name from latlng
if (type.contains(","))
url = "https://maps.googleapis.com/maps/api/geocode/";
}
#Override
protected String doInBackground(String... place) {
Log.e("places task", "usao je tu");
String data = "";
String APIkey = "key=AIzaSyC5gP63PPD8CQLCXqbkZZf6XvOhZPnoe-s";
/**
//place type to be searched
String types = "types=geocode";
// our app didn't use any sensor to determinate the location
String sensor = "sensor=false";
*/
String parameters, outputFormat;
// building paramters for search
parameters = place[0] + "&" + APIkey;
// output format
outputFormat = "json";
try {
// fetching the data from web service
data = downloadUrl(url + outputFormat + "?" + parameters);
} catch(Exception e) {
/**
* activate error screen
*/
}
return data;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
// create parser task to parse the gotten results
ParserTask parserTask = new ParserTask(listener, typeOfResult);
// start the parsing
parserTask.execute(result);
}
// private method used in the PlacesTask to download the data from the url
private String downloadUrl(String inputUrl) throws IOException{
String data = "";
InputStream is = null;
HttpURLConnection urlConnection = null;
try {
URL url = new URL(inputUrl);
//creating http connection to comunicate eith url
urlConnection = (HttpURLConnection) url.openConnection();
Log.e("places task", "3");
/*
*
* HERE IS WHERE THE DELAY HAPPENDS
*/
**urlConnection.connect();**
// reading from url
is = urlConnection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
StringBuffer sb = new StringBuffer();
String line = "";
while( (line = br.readLine()) != null ) {
sb.append(line);
}
data = sb.toString();
br.close();
} catch (Exception e) {
e.printStackTrace();
/**
* activate error screen
*/
} finally {
is.close();
urlConnection.disconnect();
}
Log.e("places task data", data);
return data;
}
}
i didn't want to post ParserTask and GooglePlacesJSONParser so the question wouldn't be that long but if someone is intereested in those classes just add comment and i will update my question

Please try with this link..
http://wptrafficanalyzer.in/blog/android-autocompletetextview-with-google-places-autocomplete-api/
Onece I did used this Turorial... And Its working properly.

I'm not sure why you are experiencing a delay, possibly it is a network issue or something in the other classes. But if you would like to try a library that provides a GooglePlaceAutoComplete widget, you could take a look at Sprockets (I'm the developer).
After the library is configured with your Google API key, you can add a GooglePlaceAutoComplete element to your layout. For example:
<net.sf.sprockets.widget.GooglePlaceAutoComplete
android:id="#+id/place"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
And then you can get the Place that a user selects by setting an OnPlaceClickListener.
public void onPlaceClick(AdapterView<?> parent, Prediction place, int position) {
/* do something with the Place */
}

Related

android sunshine app live data is not loaded on list when i press refresh button

hi i have been following android sunshine Udacity course but i got stuck at loading live data from internet i log and i see data but it is not loaded on listView thanks in advance.
package com.example.ali.ican;
public class MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new ForcastFragment())
.commit();
}
}
}
ForcastFragment
/**
* A placeholder fragment containing a simple view.
*/
public class ForcastFragment extends android.support.v4.app.Fragment {
private static ArrayAdapter<String> ForcastIncoming;
public ForcastFragment() {
}
//---------------------------------------------------------
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
new FetchWeatherTask().execute("London");
}
#Override
public void onCreateOptionsMenu(Menu menu,MenuInflater inflater) {
// Inflate the menu; this adds items to the action bar if it is present.
inflater.inflate(R.menu.forcastfragment, menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_refresh) {
FetchWeatherTask fetchWeatherTask = new FetchWeatherTask();
fetchWeatherTask.execute("119505");
Log.v("Action_refresh","works");
return true;
}
return super.onOptionsItemSelected(item);
}
//---------------------------------------------------------
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
// api.openweathermap.org/data/2.5/forecast?q=Qazvin,Iran&mode=Json
// api.openweathermap.org/data/2.5/forecast/daily?q=Qazvin,Iran&mode=Json&units=metric&cnt=7
String [] wheather ={
"Today - sunny 88/66",
"Tommorow - foggy 65/66",
"Sunday - windy 55/63",
"Monday - cloudy 89/66"
};
List<String> WeekForecast =new ArrayList<String>(
Arrays.asList(wheather)
);
ForcastIncoming =
new ArrayAdapter<String>
(getActivity()
,R.layout.list_item_forcast,
R.id._list_item_forecast_textView,
WeekForecast);
ListView firstlist =(ListView) rootView.findViewById(R.id.list_view_foreccast);
firstlist.setAdapter(ForcastIncoming);
return rootView;
}
public class FetchWeatherTask extends AsyncTask<String ,Void, String[]>{
private final String LOG_TAG =FetchWeatherTask.class.getCanonicalName();
#Override
protected String[] doInBackground(String... params) {
Log.v("CityID",""+params);
// These two need to be declared outside the try/catch
// so that they can be closed in the finally block.
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
int numDays =7;
// Will contain the raw JSON response as a string.
String forecastJsonStr = null;
try {
// Construct the URL for the OpenWeatherMap query
// Possible parameters are avaiable at OWM's forecast API page, at
// http://openweathermap.org/API#forecast
// final String FORCAST_BASE_URL ="http://api.openweathermap.org/data/2.5/forecast?id=119505&APPID=2a1ca9cdf8fa6bece6558112664c02ab";
final String FORCAST_BASE_URL ="http://api.openweathermap.org/data/2.5/forecast?id=119505&APPID=2a1ca9cdf8fa6bece6558112664c02ab";
final String QUERY_PARAM ="id";
final String QUERY_AAPID = "APPID";
final String APPID = "2a1ca9cdf8fa6bece6558112664c02ab";
final String QUERY_CNT = "cnt";
Uri uriBuilder = Uri.parse(FORCAST_BASE_URL).buildUpon()
.appendQueryParameter(QUERY_PARAM,params[0])
.appendQueryParameter(QUERY_AAPID,APPID)
.appendQueryParameter(QUERY_CNT,Integer.toString(numDays))
.build();
// URL url = new URL("http://api.openweathermap.org/data/2.5/forecast?id=119505&APPID=2a1ca9cdf8fa6bece6558112664c02ab");
URL url = new URL(uriBuilder.toString());
Log.v("Uri_builder",""+uriBuilder);
// Create the request to OpenWeatherMap, and open the connection
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
// urlConnection.setRequestProperty("User-Agent","Mozilla/5.0 ( compatible ) ");
// urlConnection.setRequestProperty("Accept","*/*");
// urlConnection.setRequestProperty("API_KEY", "2a1ca9cdf8fa6bece6558112664c02ab");
// urlConnection.setDoInput(true);
// urlConnection.setDoOutput(false);
urlConnection.connect();
// Read the input stream into a String
InputStream inputStream = urlConnection.getInputStream();
StringBuffer buffer = new StringBuffer();
if (inputStream == null) {
// Nothing to do.
Log.e("inputstreamshouting","yesssssssssnullllllllll");
return null;
}
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
// Since it's JSON, adding a newline isn't necessary (it won't affect parsing)
// But it does make debugging a *lot* easier if you print out the completed
// buffer for debugging.
buffer.append(line + "\n");
}
if (buffer.length() == 0) {
// Stream was empty. No point in parsing.
return null;
}
forecastJsonStr = buffer.toString();
Log.v("MAhdi","forcastJsonStr:" +forecastJsonStr);
} catch (IOException e) {
Log.e("PlaceholderFragment", "Error ", e);
// If the code didn't successfully get the weather data, there's no point in attemping
// to parse it.
return null;
} finally{
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e("PlaceholderFragment", "Error closing stream", e);
}
}
}
try {
return getWeatherDataFromJson(forecastJsonStr,numDays);
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String[] res) {
super.onPostExecute(res);
Log.v("From_onPost",""+res);
if (res !=null)
{
ForcastIncoming.clear();
for(String dayForcastTR :res){
ForcastIncoming.add(dayForcastTR);
}
}
ForcastIncoming.notifyDataSetChanged();
}
/* The date/time conversion code is going to be moved outside the asynctask later,
* so for convenience we're breaking it out into its own method now.
*/
private String getReadableDateString(long time){
// Because the API returns a unix timestamp (measured in seconds),
// it must be converted to milliseconds in order to be converted to valid date.
Date date = new Date(time * 1000);
SimpleDateFormat format = new SimpleDateFormat("E, MMM d");
return format.format(date).toString();
}
/**
* Prepare the weather high/lows for presentation.
*/
private String formatHighLows(double high, double low) {
// For presentation, assume the user doesn't care about tenths of a degree.
long roundedHigh = Math.round(high);
long roundedLow = Math.round(low);
String highLowStr = roundedHigh + "/" + roundedLow;
return highLowStr;
}
/**
* Take the String representing the complete forecast in JSON Format and
* pull out the data we need to construct the Strings needed for the wireframes.
*
* Fortunately parsing is easy: constructor takes the JSON string and converts it
* into an Object hierarchy for us.
*/
private String[] getWeatherDataFromJson(String forecastJsonStr, int numDays)
throws JSONException {
Log.v("Testing_arg","this is the ::"+ forecastJsonStr);
// These are the names of the JSON objects that need to be extracted.
final String OWM_LIST = "list";
final String OWM_WEATHER = "weather";
final String OWM_TEMPERATURE = "temp";
final String OWM_MAX = "temp_max";
final String OWM_MIN = "temp_min";
final String OWM_DATETIME = "dt";
final String OWM_DESCRIPTION = "main";
JSONObject forecastJson = new JSONObject(forecastJsonStr);
JSONArray weatherArray = forecastJson.getJSONArray(OWM_LIST);
String[] resultStrs = new String[numDays];
Log.v("here_weatherArray","works ::"+ weatherArray);
for(int i = 0; i < weatherArray.length(); i++) {
// For now, using the format "Day, description, hi/low"
String day;
String description;
String highAndLow;
// Get the JSON object representing the day
JSONObject dayForecast = weatherArray.getJSONObject(i);
Log.v("here_dayForecast","works ::"+dayForecast);
// The date/time is returned as a long. We need to convert that
// into something human-readable, since most people won't read "1400356800" as
// "this saturday".
long dateTime = dayForecast.getLong(OWM_DATETIME);
day = getReadableDateString(dateTime);
// description is in a child array called "weather", which is 1 element long.
JSONObject weatherObject = dayForecast.getJSONArray(OWM_WEATHER).getJSONObject(0);
description = weatherObject.getString(OWM_DESCRIPTION);
Log.v("herewat","worksk ::" + weatherObject);
// Temperatures are in a child object called "temp". Try not to name variables
// "temp" when working with temperature. It confuses everybody.
JSONObject temperatureObject = dayForecast.getJSONObject(OWM_DESCRIPTION);
double high = temperatureObject.getDouble(OWM_MAX);
double low = temperatureObject.getDouble(OWM_MIN);
Log.v("high","temperatureObject ::"+high);
highAndLow = formatHighLows(high, low);
resultStrs[i] = day + " - " + description + " - " + highAndLow;
Log.v("_resultStrs","works ::"+resultStrs);
// Log.v("resultStrs[i]","this is the ::"+ resultStrs[i]);
// for(int ii=0;ii<resultStrs.length;i++){
//
// Log.v("_Parsing", "Forcast entry: " + resultStrs[ii]);
//
//
// }
return resultStrs;
}
return resultStrs;
}
}
}
i hope someone can help me again thanks in advance
Layout Structor
Make your List<String> WeekForecast as global and add new items in onPostExecute to it as in
#Override
protected void onPostExecute(String[] res) {
super.onPostExecute(res);
Log.v("From_onPost",""+res);
if (res !=null)
{
WeekForecast.clear();
WeekForecast.addAll(Arrays.asList(res));
ForcastIncoming.notifyDataSetChanged();
}
}

populate GridView using custom ArrayAdapter won't load the first time(asynktask)

The problem is i can't figure out why the grid won't filled with the images, the first time i run the app. If i do refresh or change to landscape mode the images load and the app works fine. I assume it has to be the List that i gave to the Adapter, somehow i lost his reference the first time and when the onCreateView calls again(refresh/landscape) it gets fixed. i tried to change the places where i define the adaptor, the list, etc and some methods too like setGridData but it doesn't work. Maybe you can help me
This is the code of the Fragment and the asynkTask(by the way it works fine).
public class MovieFragment extends Fragment {
private GridViewAdapter mGridViewAdapter;
private ArrayList<Movie> mMovieList = new ArrayList<Movie>();
public MovieFragment() {
}
#Override
public void onStart() {
super.onStart();
FetchMoviesTask movieTask = new FetchMoviesTask();
movieTask.execute("popular");
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Add this line in order for this fragment to handle menu events.
setHasOptionsMenu(true);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.moviefragment, menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_refresh) {
FetchMoviesTask movieTask = new FetchMoviesTask();
movieTask.execute("popular");
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.moviefragment, container, false);
mGridViewAdapter = new GridViewAdapter(getActivity(),R.layout.movie_list_item, mMovieList);
GridView movieGrid= (GridView) rootView.findViewById(R.id.gridview_movie);
movieGrid.setAdapter(mGridViewAdapter);
return rootView;
}
public class FetchMoviesTask extends AsyncTask<String, Void, Movie[]> {
private final String LOG_TAG = FetchMoviesTask.class.getSimpleName();
private Movie[] getMoviesDataFromJson(String moviesJsonStr) throws JSONException{
final String OMDB_RESULTS="results";
final String OMBD_POSTER_PATH="poster_path";
final String OMBD_RELEASE_DATE="release_date";
final String OMBD_OVERVIEW="overview";
final String OMBD_ORIGINAL_TITLE="original_title";
final String OMBD_VOTE_AVERAGE="vote_average";
final String url= "http://image.tmdb.org/t/p/";
final String imageSize="w185";
JSONObject moviesJson = new JSONObject(moviesJsonStr);
JSONArray moviesArray = moviesJson.getJSONArray(OMDB_RESULTS);
Movie[] results = new Movie[moviesArray.length()];
//CUIDADO ACA NO SE SI SE PASA POR UNO
for (int i=0; i<moviesArray.length();i++){
JSONObject movie=moviesArray.getJSONObject(i);
Movie index=new Movie();
index.setPoster_path(url+imageSize+movie.getString(OMBD_POSTER_PATH));
index.setOriginalTitle(movie.getString(OMBD_ORIGINAL_TITLE));
index.setOverview(movie.getString(OMBD_OVERVIEW));
index.setReleaseDate(movie.getString(OMBD_RELEASE_DATE));
index.setVoteAverage(movie.getDouble(OMBD_VOTE_AVERAGE));
results[i]=index;
}
return results;
}
#Override
protected Movie[] doInBackground(String... params) {
Movie[] imageMovies;
// If there's no zip code, there's nothing to look up. Verify size of params.
if (params.length == 0) {
return null;
}
// These two need to be declared outside the try/catch
// so that they can be closed in the finally block.
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
// Will contain the raw JSON response as a string.
String moviesJsonStr = null;
try {
// Construct the URL for the OpenWeatherMap query
// Possible parameters are avaiable at OWM's forecast API page, at
// http://openweathermap.org/API#forecast
final String MOVIE_BASE_URL =
"https://api.themoviedb.org/3/movie/"+params[0];
final String APPID_PARAM = "api_key";
Uri builtUri = Uri.parse(MOVIE_BASE_URL).buildUpon()
.appendQueryParameter(APPID_PARAM, BuildConfig.OPEN_MOVIEDB_API_KEY)
.build();
URL url = new URL(builtUri.toString());
//Log.v(LOG_TAG, "Built URI " + builtUri.toString());
// Create the request to OpenWeatherMap, and open the connection
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
// Read the input stream into a String
InputStream inputStream = urlConnection.getInputStream();
StringBuffer buffer = new StringBuffer();
if (inputStream == null) {
// Nothing to do.
return null;
}
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
// Since it's JSON, adding a newline isn't necessary (it won't affect parsing)
// But it does make debugging a *lot* easier if you print out the completed
// buffer for debugging.
buffer.append(line + "\n");
}
if (buffer.length() == 0) {
// Stream was empty. No point in parsing.
return null;
}
moviesJsonStr = buffer.toString();
imageMovies = getMoviesDataFromJson(moviesJsonStr);
} catch (IOException e) {
Log.e(LOG_TAG, "Error ", e);
// If the code didn't successfully get the weather data, there's no point in attemping
// to parse it.
return null;
} catch (JSONException e) {
Log.e(LOG_TAG, "Error ", e);
// If the code didn't successfully get the weather data, there's no point in attemping
// to parse it.
return null;
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e(LOG_TAG, "Error closing stream", e);
}
}
}
return imageMovies;
}
#Override
protected void onPostExecute(Movie[] movies) {
if(movies!=null){
mGridViewAdapter.setGridData(Arrays.asList(movies));
}
}
}
}
And this is the code of the Adapter:
public class GridViewAdapter extends ArrayAdapter {
private static final String LOG_TAG = GridViewAdapter.class.getSimpleName();
private Context mContext;
private int mLayoutResourceId;
private ArrayList<Movie> mGridData;
/**
* This is our own custom constructor (it doesn't mirror a superclass constructor).
* The context is used to inflate the layout file, and the List is the data we want
* to populate into the lists
*
* #param context The current context. Used to inflate the layout file.
* #param movieList A List of AndroidFlavor objects to display in a list
*/
public GridViewAdapter(Activity context, int layoutResourceId, ArrayList<Movie> movieList) {
// Here, we initialize the ArrayAdapter's internal storage for the context and the list.
// the second argument is used when the ArrayAdapter is populating a single TextView.
// Because this is a custom adapter for two TextViews and an ImageView, the adapter is not
// going to use this second argument, so it can be any value. Here, we used 0.
super(context, layoutResourceId, movieList);
mContext=context;
mLayoutResourceId=layoutResourceId;
mGridData=movieList;
}
/**
* Updates grid data and refresh grid items.
*/
public void setGridData(List<Movie> movies) {
mGridData.clear();
mGridData.addAll(movies);
notifyDataSetChanged();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
ImageView imageView;
if (row == null) {
LayoutInflater inflater = ((Activity) mContext).getLayoutInflater();
row = inflater.inflate(mLayoutResourceId, parent, false);
imageView = (ImageView) row.findViewById(R.id.list_item_movie_imageview);
row.setTag(imageView);
} else {
imageView = (ImageView) row.getTag();
}
Movie movie = mGridData.get(position);
Picasso.with(mContext).load(movie.getPoster_path()).into(imageView);
Log.d(LOG_TAG,movie.getOriginalTitle());
return row;
}
}
The movie class is a simple class with the data. The log in the getView() method pop up only once in the first run, but it has to be 20 times.
I had a similar issue with this project as well. Try the following:
mGridViewAdapter.notifyDataSetChanged()
Currently. you're not calling it on any object. If that doesn't work, try this method instead:
mGridViewAdapter.notifyDataSetInvalidated()
Further reading: How to refresh Android listview?

Nothing happens on pressing Menu Item

I am trying to build an app following a tutorial. I have a "Refresh" button that's supposed to populate a ListView (through and ArrayAdaptor)with an array of data from an API call but when I press the "Refresh" button. The button is supposed to run updateWeather() method to load the ListView with some weather data that looks like this (This data appears in my Log actually):
Can someone please help with this. Can't seem to get my head around it.
05-10 23:23:23.921: V/FetchWeatherTask(2037): Forecast entry: Sun May 10 - Clouds - 10/8
05-10 23:23:23.921: V/FetchWeatherTask(2037): Forecast entry: Mon May 11 - Clear - 17/5
05-10 23:23:23.921: V/FetchWeatherTask(2037): Forecast entry: Tue May 12 - Rain - 21/8
05-10 23:23:23.921: V/FetchWeatherTask(2037): Forecast entry: Wed May 13 - Rain - 15/10
05-10 23:23:23.921: V/FetchWeatherTask(2037): Forecast entry: Thu May 14 - Rain - 20/15
05-10 23:23:23.922: V/FetchWeatherTask(2037): Forecast entry: Fri May 15 - Rain - 13/11
05-10 23:23:23.922: V/FetchWeatherTask(2037): Forecast entry: Sat May 16 - Rain - 13/8
ForecastFragment.java
package com.example.siaw.sunshine;
import ...
public class ForecastFragment extends Fragment {
private ArrayAdapter<String> forecastAdaptor;
public ForecastFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_refresh){
updateWeather();
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
forecastAdaptor = new ArrayAdapter<String>(getActivity(),R.layout.list_item_forecast,
R.id.list_item_forecast_textview, new ArrayList<String>());
ListView listView = (ListView) rootView.findViewById(R.id.listview_forecast);
listView.setAdapter(forecastAdaptor);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String forecast = forecastAdaptor.getItem(position);
Intent intent = new Intent(getActivity(), DetailActivity.class)
.putExtra(Intent.EXTRA_TEXT, forecast);
startActivity(intent);
}
});
return rootView;
}
private void updateWeather() {
FetchWeatherTask weatherTask = new FetchWeatherTask();
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
String location = prefs.getString(getString(R.string.pref_location_key),
getString(R.string.pref_location_default));
weatherTask.execute(location);
}
#Override
public void onStart() {
super.onStart();
updateWeather();
}
public class FetchWeatherTask extends AsyncTask<String, Void, String[]> {
private final String LOG_TAG = FetchWeatherTask.class.getSimpleName();
/* The date/time conversion code is going to be moved outside the asynctask later,
* so for convenience we're breaking it out into its own method now.
*/
private String getReadableDateString(long time){
// Because the API returns a unix timestamp (measured in seconds),
// it must be converted to milliseconds in order to be converted to valid date.
SimpleDateFormat shortenedDateFormat = new SimpleDateFormat("EEE MMM dd");
return shortenedDateFormat.format(time);
}
/**
* Prepare the weather high/lows for presentation.
*/
private String formatHighLows(double high, double low) {
// For presentation, assume the user doesn't care about tenths of a degree.
long roundedHigh = Math.round(high);
long roundedLow = Math.round(low);
String highLowStr = roundedHigh + "/" + roundedLow;
return highLowStr;
}
/**
* Take the String representing the complete forecast in JSON Format and
* pull out the data we need to construct the Strings needed for the wireframes.
*
* Fortunately parsing is easy: constructor takes the JSON string and converts it
* into an Object hierarchy for us.
*/
private String[] getWeatherDataFromJson(String forecastJsonStr, int numDays)
throws JSONException {
// These are the names of the JSON objects that need to be extracted.
final String OWM_LIST = "list";
final String OWM_WEATHER = "weather";
final String OWM_TEMPERATURE = "temp";
final String OWM_MAX = "max";
final String OWM_MIN = "min";
final String OWM_DESCRIPTION = "main";
JSONObject forecastJson = new JSONObject(forecastJsonStr);
JSONArray weatherArray = forecastJson.getJSONArray(OWM_LIST);
// OWM returns daily forecasts based upon the local time of the city that is being
// asked for, which means that we need to know the GMT offset to translate this data
// properly.
// Since this data is also sent in-order and the first day is always the
// current day, we're going to take advantage of that to get a nice
// normalized UTC date for all of our weather.
Time dayTime = new Time();
dayTime.setToNow();
// we start at the day returned by local time. Otherwise this is a mess.
int julianStartDay = Time.getJulianDay(System.currentTimeMillis(), dayTime.gmtoff);
// now we work exclusively in UTC
dayTime = new Time();
String[] resultStrs = new String[numDays];
for(int i = 0; i < weatherArray.length(); i++) {
// For now, using the format "Day, description, hi/low"
String day;
String description;
String highAndLow;
// Get the JSON object representing the day
JSONObject dayForecast = weatherArray.getJSONObject(i);
// The date/time is returned as a long. We need to convert that
// into something human-readable, since most people won't read "1400356800" as
// "this saturday".
long dateTime;
// Cheating to convert this to UTC time, which is what we want anyhow
dateTime = dayTime.setJulianDay(julianStartDay+i);
day = getReadableDateString(dateTime);
// description is in a child array called "weather", which is 1 element long.
JSONObject weatherObject = dayForecast.getJSONArray(OWM_WEATHER).getJSONObject(0);
description = weatherObject.getString(OWM_DESCRIPTION);
// Temperatures are in a child object called "temp". Try not to name variables
// "temp" when working with temperature. It confuses everybody.
JSONObject temperatureObject = dayForecast.getJSONObject(OWM_TEMPERATURE);
double high = temperatureObject.getDouble(OWM_MAX);
double low = temperatureObject.getDouble(OWM_MIN);
highAndLow = formatHighLows(high, low);
resultStrs[i] = day + " - " + description + " - " + highAndLow;
}
for (String s : resultStrs) {
Log.v(LOG_TAG, "Forecast entry: " + s);
}
return resultStrs;
}
#Override
protected String[] doInBackground(String... params){
// These two need to be declared outside the try/catch
// so that they can be closed in the finally block.
if (params.length == 0){
return null;
}
HttpURLConnection urlConnection = null;
//TODO: track and remove.
BufferedReader reader = null;
// Will contain the raw JSON response as a string.
String forecastJsonStr = null;
String format = "json";
String units = "metric";
int numDays = 7;
try {
final String FORECAST_BASE_URL = "http://api.openweathermap.org/data/2.5/forecast/daily?";
final String QUERY_PARAM = "q";
final String FORMAT_PARAM = "mode";
final String UNITS_PARAM = "units";
final String DAYS_PARAM = "cnt";
Uri builtUri = Uri.parse(FORECAST_BASE_URL).buildUpon()
.appendQueryParameter(QUERY_PARAM, params[0])
.appendQueryParameter(FORMAT_PARAM, format)
.appendQueryParameter(UNITS_PARAM, units)
.appendQueryParameter(DAYS_PARAM, Integer.toString(numDays))
.build();
URL url = new URL(builtUri.toString());
Log.v(LOG_TAG, "Built URI " + builtUri.toString());
// Create the request to OpenWeatherMap, and open the connection
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
// Read the input stream into a String
InputStream inputStream = urlConnection.getInputStream();
StringBuilder buffer = new StringBuilder();
if (inputStream == null) {
// Nothing to do.
return null;
}
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
// Since it's JSON, adding a newline isn't necessary (it won't affect parsing)
// But it does make debugging a *lot* easier if you print out the completed
// buffer for debugging.
buffer.append(line + "\n");
}
if (buffer.length() == 0) {
// Stream was empty. No point in parsing.
return null;
}
forecastJsonStr = buffer.toString();
Log.v(LOG_TAG, "Forecast String: " + forecastJsonStr);
} catch (IOException e) {
Log.e("ForecastFragment", "Error", e);
// If the code didn't successfully get the weather data, there's no point in attempting
// to parse it.
return null;
} finally{
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e("ForecastFragment", "Error closing stream", e);
}
}
}
try {
return getWeatherDataFromJson(forecastJsonStr, numDays);
} catch (JSONException e) {
Log.e(LOG_TAG, e.getMessage(), e);
e.printStackTrace();
}
//This will only happen if there was an error getting/parsing the forecast.
return null;
}
#Override
protected void onPostExecute(String[] result) {
if (result != null) {
forecastAdaptor.clear();
for (String dayForecastStr : result) {
forecastAdaptor.add(dayForecastStr);
}
// New data is back from the server. Hooray!
}
}
}
}
The data in this ListView is actually not from the API call, the funny thing is I deleted the static String array that's holding THIS data but after cleaning and rebuilding, the static data still appears. I am not sure why this is happening. In the code this data has been removed!
I want to populate this fake data with the data from the API call with the kind of data that shows in LogCat.
It looks like the main issue is that you are not calling notifyDataSetChanged() after modifying the data set in onPostExecute(). This should be all you need to get it working:
#Override
protected void onPostExecute(String[] result) {
if (result != null) {
forecastAdaptor.clear();
for (String dayForecastStr : result) {
forecastAdaptor.add(dayForecastStr);
}
// New data is back from the server. Hooray!
forecastAdapter.notifyDataSetChanged(); //added
}
}
As an alternative, I usually prefer to do all data manipulation on the underlying ArrayList instead of using the methods of ArrayAdapter, see below for details:
Create a ArrayList<String> as a member variable, which will be your data source for the ListView:
public class ForecastFragment extends Fragment {
private ArrayAdapter<String> forecastAdaptor;
private ArrayList<String> data; //added
//.........
Initialize in onCreate():
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
data = new ArrayList<String>(); //added
}
Then, pass in the data source when calling setAdapter():
forecastAdaptor = new ArrayAdapter<String>(getActivity(),R.layout.list_item_forecast,
R.id.list_item_forecast_textview, data);
Then, in onPostExecute() of your AsyncTask, update the data source, then call notifyDataSetChanged():
#Override
protected void onPostExecute(String[] result) {
if (result != null) {
//forecastAdaptor.clear(); //no need for this
data.clear(); //clear the data source
for (String dayForecastStr : result) {
//forecastAdaptor.add(dayForecastStr);
data.add(dayForecastStr); //update data source
}
// New data is back from the server. Hooray!
forecastAdapter.notifyDataSetChanged(); //added
}
}
See documentation for notifyDataSetChanged()

Google places autocomplete api is not working

I have tried most probably every tutorial regarding this. But still am not able to get a proper working autocomplete textview. What i want is ,when a user starts typing the textview should suggest proper places with every character being typed.
Here's my code :
public class Directions extends FragmentActivity {
AutoCompleteTextView from,to;
Button direction;
private static final int GPS_ERRORDIALOG_REQUEST = 9001;
GoogleMap mMap;
public ParserTask parserTask;
protected PlacesTask placesTask;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(servicesOk())
{
setContentView(R.layout.activity_directions);
if(initMap())
{
from = (AutoCompleteTextView) findViewById(R.id.atv_from);
//from.setAdapter(new PlacesAutoCompleteAdapter(this, R.layout.list_item));
from.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
placesTask = new PlacesTask();
placesTask.execute(s.toString());
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
#Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
}
});
from.setOnTouchListener(new OnTouchListener(){
#Override
public boolean onTouch(View arg0, MotionEvent arg1) {
from.showDropDown();
return false;
}
});
to = (AutoCompleteTextView) findViewById(R.id.atv_to);
//to.setAdapter(new PlacesAutoCompleteAdapter(this, R.layout.list_item));
to.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
placesTask = new PlacesTask();
placesTask.execute(s.toString());
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
#Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
}
});
to.setOnTouchListener(new OnTouchListener(){
#Override
public boolean onTouch(View arg0, MotionEvent arg1) {
from.showDropDown();
return false;
}
});
direction = (Button) findViewById(R.id.direction);
}
else
{
Toast.makeText(getApplicationContext(), "map not available", Toast.LENGTH_LONG).show();
}
}
else
{
setContentView(R.layout.activity_main);
}
}
/** A method to download json data from url */
private String downloadUrl(String strUrl) throws IOException{
String data = "";
InputStream iStream = null;
HttpURLConnection urlConnection = null;
try{
URL url = new URL(strUrl);
// Creating an http connection to communicate with url
urlConnection = (HttpURLConnection) url.openConnection();
// Connecting to url
urlConnection.connect();
// Reading data from url
iStream = urlConnection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(iStream));
StringBuffer sb = new StringBuffer();
String line = "";
while( ( line = br.readLine()) != null){
sb.append(line);
}
data = sb.toString();
br.close();
}catch(Exception e){
Log.d("Exception while downloading url", e.toString());
}finally{
iStream.close();
urlConnection.disconnect();
}
return data;
}
// Fetches all places from GooglePlaces AutoComplete Web Service
private class PlacesTask extends AsyncTask<String, Void, String>{
#Override
protected String doInBackground(String... place) {
// For storing data from web service
String data = "";
// Obtain browser key from https://code.google.com/apis/console
String key = "key=Api_key";
String input="";
try {
input = "input=" + URLEncoder.encode(place[0], "utf-8");
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
}
// place type to be searched
String types = "types=geocode";
// Sensor enabled
String sensor = "sensor=false";
// Building the parameters to the web service
String parameters = input+"&"+types+"&"+sensor+"&"+key;
// Output format
String output = "json";
// Building the url to the web service
String url = "https://maps.googleapis.com/maps/api/place/autocomplete/"+output+"?"+parameters;
try{
// Fetching the data from we service
data = downloadUrl(url);
}catch(Exception e){
Log.d("Background Task",e.toString());
}
return data;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
// Creating ParserTask
parserTask = new ParserTask();
// Starting Parsing the JSON string returned by Web Service
parserTask.execute(result);
}
}
/** A class to parse the Google Places in JSON format */
private class ParserTask extends AsyncTask<String, Integer, List<HashMap<String,String>>>{
JSONObject jObject;
#Override
protected List<HashMap<String, String>> doInBackground(String... jsonData) {
List<HashMap<String, String>> places = null;
PlaceJSONParser placeJsonParser = new PlaceJSONParser();
try{
jObject = new JSONObject(jsonData[0]);
// Getting the parsed data as a List construct
places = placeJsonParser.parse(jObject);
}catch(Exception e){
Log.d("Exception",e.toString());
}
return places;
}
#Override
protected void onPostExecute(List<HashMap<String, String>> result) {
String[] frm = new String[] { "description"};
int[] t = new int[] { android.R.id.text1 };
// Creating a SimpleAdapter for the AutoCompleteTextView
SimpleAdapter adapter = new SimpleAdapter(getBaseContext(), result, android.R.layout.simple_list_item_1, frm, t);
// Setting the adapter
from.setAdapter(adapter);
to.setAdapter(adapter);
}
}
}
You can use a AutoCompletetextView for showing the place names. I did the same below.
class GetPlaces extends AsyncTask<String, Void, ArrayList<String>> {
#Override
// three dots is java for an array of strings
protected ArrayList<String> doInBackground(String... args) {
ArrayList<String> predictionsArr = new ArrayList<String>();
try {
URL googlePlaces = new URL(
// URLEncoder.encode(url,"UTF-8");
"https://maps.googleapis.com/maps/api/place/autocomplete/json?input="
+ URLEncoder.encode(args[0].toString(), "UTF-8")
+ "&types=geocode&language=en&sensor=true&key="+Constant.GOOGLE_API_KEY);
URLConnection tc = googlePlaces.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(
tc.getInputStream()));
String line;
StringBuffer sb = new StringBuffer();
// take Google's legible JSON and turn it into one big string.
while ((line = in.readLine()) != null) {
sb.append(line);
}
// turn that string into a JSON object
JSONObject predictions = new JSONObject(sb.toString());
// now get the JSON array that's inside that object
JSONArray ja = new JSONArray(
predictions.getString("predictions"));
for (int i = 0; i < ja.length(); i++) {
JSONObject jo = (JSONObject) ja.get(i);
// add each entry to our array
predictionsArr.add(jo.getString("description"));
}
} catch (IOException e) {
Log.e("YourApp", "GetPlaces : doInBackground", e);
} catch (JSONException e) {
Log.e("YourApp", "GetPlaces : doInBackground", e);
}
return predictionsArr;
}
#Override
protected void onPostExecute(ArrayList<String> result) {
// update the adapter
adapter = new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_list_item_1);
adapter.setNotifyOnChange(true);
// attach the adapter to auto complete textview
et_destination.setAdapter(adapter);
}
}
I have created a GooglePlaceAutoComplete (source) (Javadoc) widget in the Sprockets library. You can see how I implemented it and/or set up the library in your project and use the widget.
<net.sf.sprockets.widget.GooglePlaceAutoComplete
android:id="#+id/place"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
To get the Place that a user selects, add an OnPlaceClickListener to it.
public void onPlaceClick(AdapterView<?> parent, Prediction place, int position) {
/* do something with the Place */
}

How to improve performance of google places autocomplete suggestions?

I am using google places autocomplete suggestions in my application. It is working fine but i want to improve its performance. When user types a place, it is giving a suggestions after a long delay or sometimes after deleting the last characters. How do i improve it's performance?
Please help me.
Thanks in advance
Here is my code
public class invoice extends Activity
{
AutoCompleteTextView edit_destination;
DownloadTask placesDownloadTask;
DownloadTask placeDetailsDownloadTask;
ParserTask placesParserTask;
ParserTask placeDetailsParserTask;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.create_invoice_activity);
edit_destination=(AutoCompleteTextView) findViewById(R.id.destination);
edit_destination.setThreshold(1);
edit_destination.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// Creating a DownloadTask to download Google Places matching "s"
placesDownloadTask = new DownloadTask(PLACES);
// Getting url to the Google Places Autocomplete api
String url = getAutoCompleteUrl(s.toString());
// Start downloading Google Places
// This causes to execute doInBackground() of DownloadTask class
placesDownloadTask.execute(url);
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
#Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
}
});
edit_destination.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int index,
long id) {
ListView lv = (ListView) arg0;
SimpleAdapter adapter = (SimpleAdapter) arg0.getAdapter();
HashMap<String, String> hm = (HashMap<String, String>) adapter.getItem(index);
selected_place=hm.get("description");
// Creating a DownloadTask to download Places details of the selected place
placeDetailsDownloadTask = new DownloadTask(PLACES_DETAILS);
// Getting url to the Google Places details api
String url = getPlaceDetailsUrl(hm.get("reference"));
// Start downloading Google Place Details
// This causes to execute doInBackground() of DownloadTask class
placeDetailsDownloadTask.execute(url);
}
});
}
private String getAutoCompleteUrl(String place){
// Obtain browser key from https://code.google.com/apis/console
String key = "YOUR KEY";
// place to be be searched
String input = "input="+place;
// place type to be searched
String types = "types=geocode";
// Sensor enabled
String sensor = "sensor=false";
// Building the parameters to the web service
String parameters = input+"&"+types+"&"+sensor+"&"+key;
// Output format
String output = "json";
// Building the url to the web service
String url = "https://maps.googleapis.com/maps/api/place/autocomplete/"+output+"?"+parameters;
return url;
}
private String getPlaceDetailsUrl(String ref){
// Obtain browser key from https://code.google.com/apis/console
String key = "YOUR KEY";
// reference of place
String reference = "reference="+ref;
// Sensor enabled
String sensor = "sensor=false";
// Building the parameters to the web service
String parameters = reference+"&"+sensor+"&"+key;
// Output format
String output = "json";
// Building the url to the web service
String url = "https://maps.googleapis.com/maps/api/place/details/"+output+"?"+parameters;
return url;
}
/** A method to download json data from url */
private String downloadUrl(String strUrl) throws IOException{
String data = "";
InputStream iStream = null;
HttpURLConnection urlConnection = null;
try{
URL url = new URL(strUrl);
// Creating an http connection to communicate with url
urlConnection = (HttpURLConnection) url.openConnection();
// Connecting to url
urlConnection.connect();
// Reading data from url
iStream = urlConnection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(iStream));
StringBuffer sb = new StringBuffer();
String line = "";
while( ( line = br.readLine()) != null){
sb.append(line);
}
data = sb.toString();
br.close();
}catch(Exception e){
Log.d("Exception while downloading url", e.toString());
}finally{
iStream.close();
urlConnection.disconnect();
}
return data;
}
// Fetches data from url passed
private class DownloadTask extends AsyncTask<String, Void, String>{
private int downloadType=0;
// Constructor
public DownloadTask(int type){
this.downloadType = type;
}
#Override
protected String doInBackground(String... url) {
// For storing data from web service
String data = "";
try{
// Fetching the data from web service
data = downloadUrl(url[0]);
}catch(Exception e){
Log.d("Background Task",e.toString());
}
return data;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
switch(downloadType){
case PLACES:
// Creating ParserTask for parsing Google Places
placesParserTask = new ParserTask(PLACES);
// Start parsing google places json data
// This causes to execute doInBackground() of ParserTask class
System.out.println(result);
placesParserTask.execute(result);
break;
case PLACES_DETAILS :
// Creating ParserTask for parsing Google Places
placeDetailsParserTask = new ParserTask(PLACES_DETAILS);
// Starting Parsing the JSON string
// This causes to execute doInBackground() of ParserTask class
placeDetailsParserTask.execute(result);
}
}
}
/** A class to parse the Google Places in JSON format */
private class ParserTask extends AsyncTask<String, Integer, List<HashMap<String,String>>>{
int parserType = 0;
public ParserTask(int type){
this.parserType = type;
}
#Override
protected List<HashMap<String, String>> doInBackground(String... jsonData) {
JSONObject jObject;
List<HashMap<String, String>> list = null;
try{
jObject = new JSONObject(jsonData[0]);
switch(parserType){
case PLACES :
PlaceJSONParser placeJsonParser = new PlaceJSONParser();
// Getting the parsed data as a List construct
list = placeJsonParser.parse(jObject);
break;
case PLACES_DETAILS :
PlaceDetailsJSONParser placeDetailsJsonParser = new PlaceDetailsJSONParser();
// Getting the parsed data as a List construct
list = placeDetailsJsonParser.parse(jObject);
}
}catch(Exception e){
Log.d("Exception",e.toString());
}
return list;
}
#Override
protected void onPostExecute(List<HashMap<String, String>> result) {
switch(parserType){
case PLACES :
String[] from = new String[] { "description"};
int[] to = new int[] { android.R.id.text1 };
// Creating a SimpleAdapter for the AutoCompleteTextView
SimpleAdapter adapter = new SimpleAdapter(getBaseContext(), result, android.R.layout.simple_list_item_1, from, to);
// Setting the adapter
edit_destination.setAdapter(adapter);
break;
case PLACES_DETAILS :
HashMap<String, String> hm = result.get(0);
// Getting latitude from the parsed data
latitude = Double.parseDouble(hm.get("lat"));
System.out.println(latitude);
// Getting longitude from the parsed data
longitude = Double.parseDouble(hm.get("lng"));
System.out.println(longitude);
Toast.makeText(invoice.this, latitude+","+longitude , Toast.LENGTH_LONG).show();
SharedPreferences pref=getSharedPreferences("LOC", 0);
String S_lat,S_long;
S_lat=pref.getString("LAT", "");
S_long= pref.getString("LONG","");
source_lat=Double.parseDouble(S_lat);
source_long=Double.parseDouble(S_long);
break;
}
}
}
Replace your "addTextChangedListener" method of autocompleteTextView with following code...
edit_destination.setOnKeyListener(new OnKeyListener() {
public boolean onKey(View arg0, int arg1, KeyEvent arg2) {
return false;
}
});
edit_destination.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// Creating a DownloadTask to download Google Places matching "s"
if(placesDownloadTask!=null)
{
Log.i("--placesDownloadTask--","progress_status : "+placesDownloadTask.getStatus());
placesDownloadTask.cancel(true);
}
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
#Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
String chterm;
chterm=edit_destination.getText().toString();
Log.i("---final selected text---", ""+chterm);
placesDownloadTask = new DownloadTask(PLACES);
// Getting url to the Google Places Autocomplete api
String url = getAutoCompleteUrl(s.toString());
// Start downloading Google Places
// This causes to execute doInBackground() of DownloadTask class
placesDownloadTask.execute(url);
}
});
Instead of giving call from onTextChanged, give call from afterTextChanged it reduces the number of calls after each character and hence reduces the delays.
Try it out, It may help you lot.
There is another method, as above one didn't work for me.
Replace your 'addTextChangedListener' with this one.
This will create a new timer every time it executes the onTextChanged() method and cancels the earlier assigned timertask.
edit_destination.addTextChangedListener(new TextWatcher() {
Timer timer = new Timer();
int DELAY = 3000;
String chterm;
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// Cancel the timer if already running.
timer.cancel();
chterm = s.toString();
// (Optional) Check if length of query is greater than 3
if(s.length() >= 3) {
// Start a new timer and assign a TimerTask to it.
timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
Log.i("---final selected text---", "" + chterm);
// Getting url to the Google Places Autocomplete api
String url = getAutoCompleteUrl(chterm);
// Creating a DownloadTask to download Google Places matching "s"
placesDownloadTask = new DownloadTask(PLACES);
// Start downloading Google Places
// This causes to execute doInBackground() of DownloadTask class
placesDownloadTask.execute(url);
}
}, DELAY);
}
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
#Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
}
});

Categories

Resources