I am having trouble with an method I am moving to an AsyncTask. I have the doInBackground complete but I need to move the rest of the method into onPostExecute...I Just don't know how to.
Here is my original Method.
private void ShowFuelStopAndRoute(String location) throws IOException {
Geocoder geocoder = new Geocoder(this, Locale.getDefault());
List<Address> addresses;
addresses = geocoder.getFromLocationName(location, 1);
if(addresses.size() > 0) {
BitmapDescriptor subwayBitmapDescriptor = BitmapDescriptorFactory.fromResource(R.drawable.fillingstation);
currentFuelLat= addresses.get(0).getLatitude();
currentFuellong= addresses.get(0).getLongitude();
LatLng toPostion = new LatLng(currentFuelLat, currentFuellong);
GMapV2Direction md = new GMapV2Direction();
AsyncDoc asyncDoc = new AsyncDoc(MapViewActivity.this, currentLocation, toPostion, GMapV2Direction.MODE_DRIVING);
ArrayList<LatLng> directionPoint = md.getDirection(doc);
PolylineOptions rectLine = new PolylineOptions().width(5).color(Color.BLUE);
for(int i = 0 ; i < directionPoint.size() ; i++) {
rectLine.add(directionPoint.get(i));
}
map.addPolyline(rectLine);
Marker fuelMarker = map.addMarker(new MarkerOptions().position(toPostion).icon(subwayBitmapDescriptor).title("Fueling Station, " + location));
}
}
I move the following line into a different class and a Async Class
Document doc = md.getDocument(currentLocation, toPostion, GMapV2Direction.MODE_DRIVING);
And this has been replaced with :
return DALController.sharedInstance().getDocument(startLoc, endLoc, mode);
I have this much of the AsyncTask Complete as shown below:
private class AsyncDoc extends AsyncTask<Void, Void, Document > {
public String mode;
public LatLng startLoc;
public LatLng endLoc;
public AsyncDoc (Activity activity, LatLng startLoc, LatLng endLoc, String mode){
this.startLoc = startLoc;
this.endLoc = endLoc;
this.mode = mode;
dialog = new ProgressDialog(activity);
}
private Activity activity;
private ProgressDialog dialog;
protected void onPreExecute() {
this.dialog.setMessage("Progress start");
if (! (activity).isFinishing()) {
this.dialog.show();
}
}
#Override
protected Document doInBackground(Void... params) {
return DALController.sharedInstance().getDocument(startLoc, endLoc, mode);
}
#Override
protected void onPostExecute(Document result) {
if (dialog.isShowing()) {
dialog.dismiss();
}
}
}
But I need to make sure the rest of the code doesn't run until the doInBackground is complete:
ArrayList<LatLng> directionPoint = md.getDirection(doc);
PolylineOptions rectLine = new PolylineOptions().width(5).color(Color.BLUE);
for(int i = 0 ; i < directionPoint.size() ; i++) {
rectLine.add(directionPoint.get(i));
}
map.addPolyline(rectLine);
Marker fuelMarker = map.addMarker(new MarkerOptions().position(toPostion).icon(subwayBitmapDescriptor).title("Fueling Station, " + location));
How can I ensure the doInBackground completes before the rest of my showfuelstopandroute method completes?
How can I ensure the doInBackground completes before the rest of my
showfuelstopandroute method completes?
you should need to move all code inside onPostExecute which you want to execute after doInBackground execution complete. as:
#Override
protected void onPostExecute(Document result) {
if (dialog.isShowing()) {
dialog.dismiss();
}
// do your work here after doInBackground execution
ArrayList<LatLng> directionPoint = md.getDirection(result);
....
}
In an AsyncTask, the method onPostExecute() runs only after doInBackground() has completed. What is the issue you are facing?
As mentioned by others you can move the whole code which should be executed after the task in its postExecute-method.
Another method would be to let your activity have a Method for hat which the task can call in its onPostExecute()
Related
When my device Network Connect, execute AsyncTask.
this AsyncTask is get Public Ip.
asyncTask in MainActivity (inner)
I want asyncTask result (result value is public Ip) value from another class.
How to get public ip from another class?
My source
public class MainActivity extends Activity {
static getAsyncPubIp async = new getAsyncPubIp();
public static final class getAsyncPubIp extends AsyncTask<Void, Void, String> {
String result;
TextView pubView;
#Override
public void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(Void... params) {
try {
URL pub = new URL("get public ip domain");
BufferedReader in = new BufferedReader(new InputStreamReader(
pub.openStream()));
String strPub = in.readLine();
result = strPub;
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
pubView = (TextView) activity.findViewById(R.id.ip);
pubView.setText(result);
async = null;
pubView = null;
}
}
usually, call this asynctask on another class
MainActivity.getAsyncPubIp asyncPub = new MainActivity.getAsyncPubIp();
asyncPub.execute();
but I want only asyncTask result value from another class
How to get this ?
Create a static variable in second activity's java class named SecondClass.java:
public static String public_ip;
Then in your MainActivity:
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
//Add this
SecondClass.public_ip = result;
pubView = (TextView) activity.findViewById(R.id.ip);
pubView.setText(result);
async = null;
pubView = null;
}
I am fairly new to Android development and am creating an application which uses a Google map fragment. I am querying the Google Directions Api and retrieving JSON data using an AsyncTask method. I then decode the polyline and in turn gain a string array of LatLon pairs. I now would now like to use this string array back in my MainActivity. I have tried many ways to do this, however every single way has made the string array null.
Method tried = 1) using a static field 2) using Intent objects to transfer data 3) creating an interface.
Could someone please tell me as to how I should go around this and why it keeps becoming null in my MainActivity? Snippets of my code are below, thanks.
public class GetDirectionsData extends AsyncTask<Object, String,
String>
{
private GoogleMap mMap;
private Context context;
private String url , googleDirectionsData;
private String distance,duration;
private LatLng destinationLatLng;
private String[] directionsList;
public GetDirectionsData(Context context)
{
this.context = context;
}
#Override
protected String doInBackground(Object... objects)
{
mMap = (GoogleMap)objects[0];
url = (String)objects[1];
destinationLatLng = (LatLng)objects[2];
DownloadUrl downloadURL = new DownloadUrl();
try
{
googleDirectionsData = downloadURL.readUrl(url);
}
catch (IOException e)
{
e.printStackTrace();
}
return googleDirectionsData;
}
#Override
protected void onPostExecute(String s)
{
// uses other class DataParser to extract relevant JSONdata and
// displays polyline
DataParser directionParser = new DataParser();
directionsList = directionParser.parseDirections(s);
displayDirection(directionsList);
}
public void displayDirection(String[] directionsList)
{
int count = directionsList.length;
for(int i = 0; i < count; i++)
{
PolylineOptions options = new PolylineOptions();
options.color(Color.BLUE);
options.width(10);
options.addAll(PolyUtil.decode(directionsList[i])); // decode polylines
mMap.addPolyline(options);
}
}
I now want to pass directionsList string array back to MapsActivity Below
public class MapsActivity extends FragmentActivity
{
public void onClick(View v)
{
Object directionDataTransfer[];
// DIRECTIONS BUTTON
switch(v.getId())
{
case R.id.IB_search:
directionDataTransfer = new Object[3];
GetDirectionsData getDirectionsData = new GetDirectionsData(this);
String directionsUrl = getDirectionsUrl();
directionDataTransfer[0] = mMap;
directionDataTransfer[1] = directionsUrl;
directionDataTransfer[2] = new LatLng(//destination LatLon)
getDirectionsData.execute(directionDataTransfer);
Toast.makeText(MapsActivity.this, "Fetching directions", Toast.LENGTH_LONG).show();
}
}
private String getDirectionsUrl()
{
StringBuilder googleDirectionsUrl = new StringBuilder("https://maps.googleapis.com/maps/api/directions/json?");
googleDirectionsUrl.append("origin=" + originLat + "," + originLon);
googleDirectionsUrl.append("&destination=" + destinationLat + "," + destinationLon);
googleDirectionsUrl.append("&mode=" + modeOfTransport);
googleDirectionsUrl.append("&waypoints=via:" + waypointsLat + "," + waypointsLon);
googleDirectionsUrl.append("&key=" + googleApiKey);
return( googleDirectionsUrl.toString() );
}
}
Here is one of the example using Interface - hope this helps.
DummyAsyncTask.java
import android.os.AsyncTask;
public class DummyAsyncTask extends AsyncTask<Void, Void, String> {
private DummyInterface mListener = null;
DummyAsyncTask(DummyInterface listener) {
mListener = listener;
}
#Override
protected String doInBackground(Void... voids) {
return s; // return your string from doInBackground(it will be available as a parameter in onPostExecute())
}
#Override
protected void onPostExecute(String s) {
if(mListener != null) {
mListener.onCallback(s); // sending string s back to activity which registered for callback
}
}
}
DummyInterface.java
public interface DummyInterface {
void onCallback(String s); // callback API
}
DummyActivity.java
import android.app.Activity;
import android.os.Bundle;
public class DummyActivity extends Activity implements DummyInterface{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
new DummyAsyncTask(this).execute();
}
#Override
public void onCallback(String s) {
System.out.println("String s = " + s);
}
}
I'm loading my markers(clustering) from a json and it's working.
But the markers is not so fast to render. My solution is show the progressbar while the markers is loading.
But the problem is that the progressbar is gone before the render.
I'm using the AsyncTask to render and I am adding the marker in the onProgressUpdate.
public class GetMarkersAsync extends AsyncTask<String, HistoricoTO, List<HistoricoTO>> {
private final static String OBTER = "http://10.0.0.65/Service.asmx/getEnvios";
GoogleMap map;
private Activity activity;
private ProgressBar progressBar;
public GetMarkersAsync (GoogleMap map, Activity activity) {
this.map = map;
this.activity = activity;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
progressBar = (ProgressBar) activity.findViewById(R.id.progressBar1);
progressBar.setIndeterminate(true);
progressBar.setVisibility(View.VISIBLE);
}
#Override
protected List<HistoricoTO> doInBackground(String... params) {
WebService ws = new WebService();
String response = ws.makeRequest(OBTER);
List<HistoricoTO> listaHistoricos = new ArrayList<HistoricoTO>();
try {
JSONArray array = new JSONArray(response);
HistoricoTO historico;
JSONObject jsonObject;
for (int i = 0; i < array.length(); i++) {
jsonObject = array.getJSONObject(i);
historico = new HistoricoTO();
historico.setName(jsonObject.getString("name"));
historico.setLatitude(jsonObject.getDouble("latitude"));
historico.setLongitude(jsonObject.getDouble("longitude"));
listaHistoricos.add(historico);
publishProgress(historico);
}
} catch (JSONException e) {
e.printStackTrace();
}
return listaHistoricos;
}
#Override
protected void onProgressUpdate(HistoricoTO... historicos) {
super.onProgressUpdate(historicos);
drawMarker(this.map, historicos[0]);
}
#Override
protected void onPostExecute(List<HistoricoTO> historicoTOs) {
super.onPostExecute(historicoTOs);
progressBar.setVisibility(View.GONE)
}
private void drawMarker(GoogleMap gmap, HistoricoTO historicoTO)
{
MyItem offsetItem = new MyItem(historicoTO.getLatitude(), historicoTO.getLongitude(), historicoTO);
MainActivity.mClusterManager.getMarkerCollection().addMarker(mo);
MainActivity.mClusterManager.addItem(offsetItem);
gmap.addMarker(mo);
}
}
PS: It's working, the ProgressBar is showing, but the problem is that the markers only shows when I "move" the map ou touch.
every time you add a new marker, invalidate map again.
so it will draw your item on map.
map.invalidate()
Here in for loop i want to call Async return value. i want to call that value in snippet after title.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_show_full_map);
Intent i = getIntent();
lat = i.getStringArrayListExtra("L");
longi = i.getStringArrayListExtra("Longitude");
len=lat.size();
for(;j<len;j++){
LatLng location = new LatLng(Double.valueOf(lat.get(j)).doubleValue(),
Double.valueOf(longi.get(j)).doubleValue()) ;
new ReverseGeocodingTask(getBaseContext()).execute(location);
googlemap.addMarker(new MarkerOptions()
.title(plat.get(j).toString())
.snippet(snippet)
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_CYAN))
.position(location)
);
}
}
Here Below is my AsyncTask code where i am returning the values. please some take a look and explain me my silly mistake....
private class ReverseGeocodingTask extends AsyncTask<LatLng, Void, String>
{
Context mContext;
public ReverseGeocodingTask(Context context){
super();
mContext = context;
}
// Finding address using reverse geocoding
#Override
protected String doInBackground(LatLng... params) {
Geocoder geocoder = new Geocoder(mContext);
double latitude = params[0].latitude;
double longitude = params[0].longitude;
List<Address> addresses = null;
try {
addresses = geocoder.getFromLocation(latitude, longitude,1);
} catch (IOException e) {
e.printStackTrace();
}
if(addresses != null && addresses.size() > 0 ){
Address address = addresses.get(0);
addressText = String.format("%s, %s, %s",
address.getMaxAddressLineIndex() > 0 ? address.getAddressLine(0) : "",
address.getLocality(),
address.getCountryName());
}
return addressText;
}
#Override
protected void onPostExecute(String addressResult) {
// Setting the title for the marker.
// This will be displayed on taping the marker
snippet = addressResult;
super.onPostExecute(snippet);
//Toast.makeText(Show_full_map.this,addressText,Toast.LENGTH_LONG).show();
}
}
I guess you want snippet immediately after calling execute. This is not how AsyncTask works. You can pass location in constructor of AsyncTask and access it from onPostExecute().
Just move the following code from your for loop to onPostExecute():
#Override
protected void onPostExecute(String snippet) {
super.onPostExecute(snippet);
googlemap.addMarker(new MarkerOptions()
.title(plat.get(j).toString())
.snippet(snippet)
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_CYAN))
.position(location)
);
}
Have the following AsyncTask code:
private class checkChangesTask extends AsyncTask<String, Void, String> {
protected ProgressDialog mProgressDialog2;
protected String _url = "", _idautor="", _idbook="";
#Override
protected void onPreExecute() {
super.onPreExecute();
this.mProgressDialog2 = new ProgressDialog(MainActivity.this);
this.mProgressDialog2.setMessage("Check changes ...");
this.mProgressDialog2.setIndeterminate(false);
this.mProgressDialog2.setCanceledOnTouchOutside(false);
this.mProgressDialog2.setCancelable(true);
this.mProgressDialog2.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
this.mProgressDialog2.setMax(100);
this.mProgressDialog2.setProgress(0);
this.mProgressDialog2.show();
}
#Override
protected String doInBackground(String... params) {
Document doc = null;
String _html = "";
_idautor = params[0];
_idbook = params[1];
_url = params[2];
try {
doc = Jsoup.connect(_url).userAgent("Mozilla").get();
Elements dd = doc.select("dd");
int size = dd.size();
int p = 1;
for (Element src : dd) {
this.mProgressDialog2.setProgress(p*100/size);
if (p <= size-1){
_html += src.outerHtml();
++p;
}
}
} catch (IOException e) {
e.printStackTrace();
}
return Jsoup.clean(_html, Whitelist.basic());
}
#Override
protected void onPostExecute(String result) {
if(!result.equals("")){
String lastfile = readPageFile(_idautor + "_" + _idbook);
if(!lastfile.equals(result)){
savePageToFile(_idautor + "_" + _idbook, result);
}
}else{
Toast.makeText(MainActivity.this, "Error checkChangesTask", Toast.LENGTH_SHORT).show();
}
this.mProgressDialog2.dismiss();
}
the previous code I call in a loop:
public void checkChanges() {
String[][] db_books = db.selectAllBOOKS();
if (db_books.length>0){
for (int j = 0; j < db_books.length; j++){
new checkChangesTask().executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, db_books[j][1], db_books[j][0], db_books[j][2]);
}
}
}
Everything works fine, but the dialog does not display the correct value. First, it is worth it to 0% and then abruptly switches to 100%.
AsyncTask called in sequence (...executeOnExecutor(AsyncTask.SERIAL_EXECUTOR...).
If you run a AsyncTask not in the loop, all the displays are just perfect!
android: targetSdkVersion = "14"
I ask your help.
You need to use onProgressUpdate() inside the AsyncTask. Something like this (at a guess)
#Override
protected void onProgressUpdate(Integer... progress) {
super.onProgressUpdate(progress);
this.mProgressDialog2.setProgress(progress[0] * 100/progress[1]);
}
And replace this line:
this.mProgressDialog2.setProgress(p*100/size);
With this:
publishProgress(new int[]{p,size})