fix hanging UI on MapWorker.pause/.proceed

This commit is contained in:
Hannes Janetzek 2012-08-08 22:43:06 +02:00
parent 165221f42a
commit 4cae011d85
8 changed files with 110 additions and 30 deletions

View File

@ -93,7 +93,7 @@ public class MapView extends GLSurfaceView {
private IMapRenderer mMapRenderer; private IMapRenderer mMapRenderer;
private JobQueue mJobQueue; private JobQueue mJobQueue;
private MapWorker mMapWorkers[]; private MapWorker mMapWorkers[];
private int mNumMapWorkers = 6; private int mNumMapWorkers = 4;
private JobParameters mJobParameters; private JobParameters mJobParameters;
private DebugSettings mDebugSettings; private DebugSettings mDebugSettings;
private String mMapFile; private String mMapFile;
@ -301,15 +301,15 @@ public class MapView extends GLSurfaceView {
/** /**
* Calculates all necessary tiles and adds jobs accordingly. * Calculates all necessary tiles and adds jobs accordingly.
*/ */
public synchronized void redrawTiles() { public void redrawTiles() {
if (getWidth() <= 0 || getHeight() <= 0) if (getWidth() > 0 && getHeight() > 0)
return; return;
mMapRenderer.redrawTiles(false); mMapRenderer.redrawTiles(false);
} }
void clearAndRedrawMapView() { void clearAndRedrawMapView() {
if (getWidth() <= 0 || getHeight() <= 0) if (getWidth() > 0 && getHeight() > 0)
return; return;
mMapRenderer.redrawTiles(true); mMapRenderer.redrawTiles(true);
@ -525,7 +525,6 @@ public class MapView extends GLSurfaceView {
} catch (IOException e) { } catch (IOException e) {
Log.e(TAG, e.getMessage()); Log.e(TAG, e.getMessage());
} finally { } finally {
mapWorkersProceed();
try { try {
if (inputStream != null) { if (inputStream != null) {
inputStream.close(); inputStream.close();
@ -533,7 +532,9 @@ public class MapView extends GLSurfaceView {
} catch (IOException e) { } catch (IOException e) {
Log.e(TAG, e.getMessage()); Log.e(TAG, e.getMessage());
} }
mapWorkersProceed();
} }
return false; return false;
} }
@ -604,13 +605,13 @@ public class MapView extends GLSurfaceView {
@Override @Override
protected synchronized void onSizeChanged(int width, int height, int oldWidth, protected synchronized void onSizeChanged(int width, int height, int oldWidth,
int oldHeight) { int oldHeight) {
for (MapWorker mapWorker : mMapWorkers) { mJobQueue.clear();
mapWorker.pause();
mapWorker.awaitPausing(); mapWorkersPause();
super.onSizeChanged(width, height, oldWidth, oldHeight);
mapWorker.proceed(); super.onSizeChanged(width, height, oldWidth, oldHeight);
}
// redrawTiles(); mapWorkersProceed();
} }
void destroy() { void destroy() {
@ -618,6 +619,7 @@ public class MapView extends GLSurfaceView {
// mZoomAnimator.interrupt(); // mZoomAnimator.interrupt();
for (MapWorker mapWorker : mMapWorkers) { for (MapWorker mapWorker : mMapWorkers) {
mapWorker.pause();
mapWorker.interrupt(); mapWorker.interrupt();
try { try {
@ -754,10 +756,12 @@ public class MapView extends GLSurfaceView {
private void mapWorkersPause() { private void mapWorkersPause() {
for (MapWorker mapWorker : mMapWorkers) { for (MapWorker mapWorker : mMapWorkers) {
if (!mapWorker.isPausing()) { if (!mapWorker.isPausing())
mapWorker.pause(); mapWorker.pause();
}
for (MapWorker mapWorker : mMapWorkers) {
if (!mapWorker.isPausing())
mapWorker.awaitPausing(); mapWorker.awaitPausing();
}
} }
} }

View File

@ -28,6 +28,8 @@ public class MapWorker extends PausableThread {
private final IMapGenerator mMapGenerator; private final IMapGenerator mMapGenerator;
private final IMapRenderer mMapRenderer; private final IMapRenderer mMapRenderer;
// private final int mPrio;
/** /**
* @param id * @param id
* thread id * thread id
@ -46,6 +48,7 @@ public class MapWorker extends PausableThread {
mMapRenderer = mapRenderer; mMapRenderer = mapRenderer;
THREAD_NAME = "MapWorker" + id; THREAD_NAME = "MapWorker" + id;
// mPrio = Math.max(Thread.MIN_PRIORITY + id, Thread.NORM_PRIORITY - 1);
} }
public IMapGenerator getMapGenerator() { public IMapGenerator getMapGenerator() {
@ -63,7 +66,6 @@ public class MapWorker extends PausableThread {
if (mMapGenerator == null || mapGeneratorJob == null) if (mMapGenerator == null || mapGeneratorJob == null)
return; return;
// Log.d(THREAD_NAME, "processing: " + mapGeneratorJob.tile);
boolean success = mMapGenerator.executeJob(mapGeneratorJob); boolean success = mMapGenerator.executeJob(mapGeneratorJob);
@ -77,10 +79,15 @@ public class MapWorker extends PausableThread {
return THREAD_NAME; return THREAD_NAME;
} }
@Override
protected void takeabreak() {
mMapGenerator.getMapDatabase().cancel();
}
@Override @Override
protected int getThreadPriority() { protected int getThreadPriority() {
// return (Thread.NORM_PRIORITY + Thread.MIN_PRIORITY) / 2; return (Thread.NORM_PRIORITY + Thread.MIN_PRIORITY) / 2;
return Thread.MIN_PRIORITY; // return mPrio;
} }
@Override @Override

View File

@ -58,6 +58,7 @@ public abstract class PausableThread extends Thread {
public final synchronized void pause() { public final synchronized void pause() {
if (!mShouldPause) { if (!mShouldPause) {
mShouldPause = true; mShouldPause = true;
takeabreak();
notify(); notify();
} }
} }
@ -116,6 +117,10 @@ public abstract class PausableThread extends Thread {
// do nothing // do nothing
} }
protected void takeabreak() {
// do nothing
}
/** /**
* Called once at the end of the {@link #run()} method. The default implementation is empty. * Called once at the end of the {@link #run()} method. The default implementation is empty.
*/ */

View File

@ -71,4 +71,6 @@ public interface IMapDatabase {
*/ */
public abstract String readString(int position); public abstract String readString(int position);
public abstract void cancel();
} }

View File

@ -173,4 +173,10 @@ public class MapDatabase implements IMapDatabase {
return null; return null;
} }
@Override
public void cancel() {
// TODO Auto-generated method stub
}
} }

View File

@ -976,4 +976,10 @@ public class MapDatabase implements IMapDatabase {
return zoomTable; return zoomTable;
} }
@Override
public void cancel() {
// TODO Auto-generated method stub
}
} }

View File

@ -17,6 +17,8 @@ package org.mapsforge.database.pbmap;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.util.HashMap; import java.util.HashMap;
import java.util.zip.GZIPInputStream; import java.util.zip.GZIPInputStream;
@ -24,8 +26,17 @@ import org.apache.http.Header;
import org.apache.http.HttpEntity; import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse; import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus; import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.params.HttpClientParams;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicHeader; import org.apache.http.message.BasicHeader;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.mapsforge.core.BoundingBox; import org.mapsforge.core.BoundingBox;
import org.mapsforge.core.GeoPoint; import org.mapsforge.core.GeoPoint;
import org.mapsforge.core.Tag; import org.mapsforge.core.Tag;
@ -36,7 +47,6 @@ import org.mapsforge.database.IMapDatabase;
import org.mapsforge.database.IMapDatabaseCallback; import org.mapsforge.database.IMapDatabaseCallback;
import org.mapsforge.database.MapFileInfo; import org.mapsforge.database.MapFileInfo;
import android.net.http.AndroidHttpClient;
import android.util.Log; import android.util.Log;
/** /**
@ -63,12 +73,17 @@ public class MapDatabase implements IMapDatabase {
private Tag[] curTags = new Tag[1000]; private Tag[] curTags = new Tag[1000];
private int mCurTagCnt; private int mCurTagCnt;
private AndroidHttpClient mClient; // private AndroidHttpClient mClient;
private HttpClient mClient;
private IMapDatabaseCallback mMapGenerator; private IMapDatabaseCallback mMapGenerator;
private float mScaleFactor; private float mScaleFactor;
@Override @Override
public void executeQuery(Tile tile, IMapDatabaseCallback mapDatabaseCallback) { public void executeQuery(Tile tile, IMapDatabaseCallback mapDatabaseCallback) {
mCanceled = false;
if (mClient == null)
createClient();
String url = String.format(URL, Integer.valueOf(tile.zoomLevel), String url = String.format(URL, Integer.valueOf(tile.zoomLevel),
Long.valueOf(tile.tileX), Long.valueOf(tile.tileY)); Long.valueOf(tile.tileX), Long.valueOf(tile.tileY));
@ -100,6 +115,7 @@ public class MapDatabase implements IMapDatabase {
InputStream is = null; InputStream is = null;
GZIPInputStream zis = null; GZIPInputStream zis = null;
try { try {
// is = AndroidHttpClient.getUngzippedContent(entity);
is = entity.getContent(); is = entity.getContent();
zis = new GZIPInputStream(is); zis = new GZIPInputStream(is);
@ -113,6 +129,10 @@ public class MapDatabase implements IMapDatabase {
is.close(); is.close();
entity.consumeContent(); entity.consumeContent();
} }
} catch (SocketException ex) {
Log.d(TAG, "Socket exception: " + ex.getMessage());
} catch (SocketTimeoutException ex) {
Log.d(TAG, "Socket exception: " + ex.getMessage());
} catch (Exception ex) { } catch (Exception ex) {
getRequest.abort(); getRequest.abort();
ex.printStackTrace(); ex.printStackTrace();
@ -134,10 +154,27 @@ public class MapDatabase implements IMapDatabase {
return mOpenFile; return mOpenFile;
} }
private void createClient() {
// mClient = AndroidHttpClient.newInstance("Android");
mOpenFile = true;
HttpParams params = new BasicHttpParams();
HttpConnectionParams.setStaleCheckingEnabled(params, false);
HttpConnectionParams.setConnectionTimeout(params, 10 * 1000);
HttpConnectionParams.setSoTimeout(params, 60 * 1000);
HttpConnectionParams.setSocketBufferSize(params, 8192);
mClient = new DefaultHttpClient(params);
HttpClientParams.setRedirecting(params, false);
SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("http",
PlainSocketFactory.getSocketFactory(), 80));
}
@Override @Override
public FileOpenResult openFile(File mapFile) { public FileOpenResult openFile(File mapFile) {
mOpenFile = true; createClient();
mClient = AndroidHttpClient.newInstance("Android");
return new FileOpenResult(); return new FileOpenResult();
} }
@ -145,7 +182,7 @@ public class MapDatabase implements IMapDatabase {
public void closeFile() { public void closeFile() {
mOpenFile = false; mOpenFile = false;
if (mClient != null) if (mClient != null)
mClient.close(); mClient.getConnectionManager().shutdown();
} }
@Override @Override
@ -361,20 +398,18 @@ public class MapDatabase implements IMapDatabase {
private int decodeWayCoordinates() throws IOException { private int decodeWayCoordinates() throws IOException {
int bytes = decodeVarint32(); int bytes = decodeVarint32();
int cnt = 0;
// int end = bytesRead + bytes;
readBuffer(bytes); readBuffer(bytes);
int pos = bufferPos; int pos = bufferPos;
int end = pos + bytes; int end = pos + bytes;
float[] coords = tmpCoords; float[] coords = tmpCoords;
byte[] buf = buffer; byte[] buf = buffer;
int cnt = 0;
int result; int result;
// read repeated sint32
while (pos < end) { while (pos < end) {
if (cnt >= MAX_WAY_COORDS) { if (cnt >= MAX_WAY_COORDS) {
// Log.d(TAG, "increase coords array " + MAX_WAY_COORDS);
MAX_WAY_COORDS += 128; MAX_WAY_COORDS += 128;
float[] tmp = new float[MAX_WAY_COORDS]; float[] tmp = new float[MAX_WAY_COORDS];
System.arraycopy(coords, 0, tmp, 0, cnt); System.arraycopy(coords, 0, tmp, 0, cnt);
@ -457,10 +492,10 @@ public class MapDatabase implements IMapDatabase {
return; return;
if (size > BUFFER_SIZE) { if (size > BUFFER_SIZE) {
Log.d(TAG, "EEEK too large"); // FIXME throw exception for now, but frankly better
// FIXME throw exception, but frankly better sanitize tile data on compilation // sanitize tile data on compilation.
// this only happen with Strings larger than 32kb // this only happen with strings or coordinates larger than 64kb
return; throw new IOException("EEEK requested size too large");
} }
if ((size - bufferSize) + bufferPos > BUFFER_SIZE) { if ((size - bufferSize) + bufferPos > BUFFER_SIZE) {
@ -574,4 +609,13 @@ public class MapDatabase implements IMapDatabase {
return (n >>> 1) ^ -(n & 1); return (n >>> 1) ^ -(n & 1);
} }
private boolean mCanceled;
@Override
public void cancel() {
mCanceled = true;
mClient.getConnectionManager().shutdown();
mClient = null;
}
} }

View File

@ -366,4 +366,10 @@ public class MapDatabase implements IMapDatabase {
int count = data.getInt(); int count = data.getInt();
parseGeometryArray(data, count); parseGeometryArray(data, count);
} }
@Override
public void cancel() {
// TODO Auto-generated method stub
}
} }