I have a map. I have a database of points. I want to display points from database in AsyncTask, so user can move around the map, when the points are being loaded. There's not much points (like 353 or etc), but I redraw them all when user gets closer (zoom) to the map with bigger markers. When this redraw occurs, app freezes like for a fraction of a second, but it's noticeable, so I thought AsyncTask would be the answer.
However it's not working. And it's weird. I found a few questions here, but the problem there was mostly not calling the "publishProgress()" method, which is not my case.
In the method "doInBackground()" I open the database, do the query and save it to a Cursor (which is attribute of my ShowPoints class, which extends AsyncTask, so it shoud be accesable by all methods of this class //at least I think that). Than I go through the cursor and each time call "publishProgress()" which shoud call "onProgressUpdate()" and here I create the marker using my cursor from "doInBackgroud()".
It's strange that if I do debug, and go through the code by step, it all works as it shoud. But when I run the app, no markers are added or only a few of them.
private class ShowPoints extends AsyncTask<String, Integer, String> {
private String resp="Body načteny";
private Cursor c_body;
private LatLng marker_pozice;
@Override
protected String doInBackground(String... params) {
int i=0;
try {
DatabaseHelper db = new DatabaseHelper(MainActivity.this);
try {
db.openDataBase();
}catch(SQLException sqle){
throw sqle;
}
c_body = db.query(DatabaseHelper.TABLE_POINTS, allColumns, null, null, null,null, null);
if(c_body.moveToFirst())
{
if(params[0]=="small"){
do {
i++;
int ikona = R.drawable.gray_dot;
int trasa = c_body.getInt(6);
switch(trasa){
case 1: ikona = R.drawable.color_00a750_dot;
break;
case 2: ikona = R.drawable.color_ec1c24_dot;
break;
case 3: ikona = R.drawable.color_ffca05_dot;
break;
case 4: ikona = R.drawable.color_6dcef5_dot;
break;
case 5: ikona = R.drawable.color_f497b0_dot;
break;
case 6: ikona = R.drawable.color_0088cf_dot;
break;
case 7: ikona = R.drawable.color_98d3bf_dot;
break;
case 8: ikona = R.drawable.color_c3792f_dot;
break;
case 9: ikona = R.drawable.color_c5168c_dot;
break;
}
publishProgress(ikona);
Log.i("Thread",String.valueOf(i));
} while (c_body.moveToNext());
}else{
do {
i++;
int ikona = R.drawable.bigg_dot;
int trasa = c_body.getInt(6);
switch(trasa){
case 1: ikona = R.drawable.biggr_00a750_dot;
break;
case 2: ikona = R.drawable.biggr_ec1c24_dot;
break;
case 3: ikona = R.drawable.biggr_ffca05_dot;
break;
case 4: ikona = R.drawable.biggr_6dcef5_dot;
break;
case 5: ikona = R.drawable.biggr_f497b0_dot;
break;
case 6: ikona = R.drawable.biggr_0088cf_dot;
break;
case 7: ikona = R.drawable.biggr_98d3bf_dot;
break;
case 8: ikona = R.drawable.biggr_c3792f_dot;
break;
case 9: ikona = R.drawable.biggr_c5168c_dot;
break;
}
Log.i("Thread",String.valueOf(i));
publishProgress(ikona);
} while (c_body.moveToNext());
}
}
db.close();
} catch (Exception e) {
e.printStackTrace();
resp = e.getMessage();
}
return resp;
}
@Override
protected void onProgressUpdate(Integer... ikona) {
marker_pozice = new LatLng(c_body.getDouble(3), c_body.getDouble(4));
mMap.addMarker(new MarkerOptions()
.position(marker_pozice)
.title(c_body.getString(2))
.snippet(c_body.getString(7)+"\n"+c_body.getString(1))
.icon(BitmapDescriptorFactory.fromResource(ikona[0])));
}
// progress. For example updating ProgessDialog
}
I call this in the onCreate method:
ShowPoints pointShower = new ShowPoints();
pointShower.execute("small");
Also the logging I'm doing in "doInBackgroud()" works, but markers are not added to the map (or not all of them ... sometimes there are drawn 3, sometimes 19 etc).
mMap is accesable, because this class is inside another class, where the map is an attribute and is instantiated before this Async is called. Also as I'm saying, in debuger step by step I can draw all the points.
Also in "onPostExecute()" I have a toast, which is displayed when I launch the app, so there's no doubt it finishes the async (logging works, final method is called).
While your intentions here are good, I just dont see much gain from it because you are still calling back to the UI thread for every single element and I bet you wont see much of a difference in performance. Having said that I am willing to bet your problem is that you are holding onto the cursor and using that in the onProgressUpdate
while your doInBackground
continues on movine the cursor to the next row. Which would explain why when you debug it works correctly because you are stepping along.
What I would recommend for performance increase would be to in your doInBackground
create a list of some object that holds all the information about the map object (icon,position, etc..). Only add the markers to the map where they are in the visible bounding box of the map so you are not plotting markers that are not even visible. then in your onPostExecute
use that list and plot everything there.
While I dont know for sure if this is the cause of the problem but it could very well likely be the problem
I do this by creating a list of MarkerOptions in the asynctask then in the onPostExecute I add these to the map in a loop. Actually I have two tasks that run syncronously. Task1 sets up the list of markeroptions and when it finishes task2 starts and gets / downloads any icon associated with the marker. I do the downloads at the end because chances are you'll reuse markers and you can use a hash to get a previously downloaded marker. You'd probably just be using the 2nd async task which gets the marker icons so as small favor I've included the class I use to get the bitmaps for markers.
Here's a custom class to handle the crp.
package com.gosylvester.bestrides.beans;
import com.google.android.gms.maps.model.MarkerOptions;
public class KmlMarkerOptions {
public MarkerOptions markeroptions;
public String href;
public int hrefhash =-1;
}
here's the 2nd async task that loads the bitmaps for the markers.
private class LoadMarkerBitmapDescriptor extends
AsyncTask<List<KmlMarkerOptions>, Void, Boolean> {
@Override
protected Boolean doInBackground(List<KmlMarkerOptions>... params) {
Boolean ret = true;
List<KmlMarkerOptions> kmlmarkeroptions = params[0];
int markerSize = kmlmarkeroptions.size();
for (int currentMarkerPosition = 0; currentMarkerPosition < markerSize; currentMarkerPosition++) {
KmlMarkerOptions currentMarkerOptions = kmlmarkeroptions
.get(currentMarkerPosition);
int hrefhash = currentMarkerOptions.hrefhash;
if (hrefhash != -1) {
// not the poistion zero marker
if (currentMarkerPosition != 0) {
// search for an existing bitmap descriptor
for (int previousMarkerPosition = 0; previousMarkerPosition < currentMarkerPosition; previousMarkerPosition++) {
KmlMarkerOptions previousMarkerOptions = kmlmarkeroptions
.get(previousMarkerPosition);
if (previousMarkerOptions.hrefhash == hrefhash) {
currentMarkerOptions.markeroptions
.icon(previousMarkerOptions.markeroptions
.getIcon());
break;
}
}
}
if (currentMarkerOptions.markeroptions.getIcon() == null) {
try {
InputStream is = (InputStream) new URL(
currentMarkerOptions.href).getContent();
Bitmap bm = (Bitmap) BitmapFactory.decodeStream(is);
currentMarkerOptions.markeroptions
.icon((BitmapDescriptor) BitmapDescriptorFactory
.fromBitmap(bm));
} catch (Exception e1) {
e1.printStackTrace();
ret = false;
}
}
}
}
return ret;
}
protected void onPostExecute(Boolean result) {
addIcontoMap();
}
protected void addIcontoMap() {
for (KmlMarkerOptions kmlmo : mKmlmo) {
mMap.addMarker(kmlmo.markeroptions);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With