OSMDroid源码分析之瓦片载入基类:MapTileModuleProviderBase
来源:互联网 发布:python 设计模式 23种 编辑:程序博客网 时间:2024/05/29 18:08
源码
先来看看源码:
package org.osmdroid.tileprovider.modules;import java.util.HashMap;import java.util.Iterator;import java.util.LinkedHashMap;import java.util.Map;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.RejectedExecutionException;import org.osmdroid.tileprovider.ExpirableBitmapDrawable;import org.osmdroid.tileprovider.MapTile;import org.osmdroid.tileprovider.MapTileRequestState;import org.osmdroid.tileprovider.constants.OpenStreetMapTileProviderConstants;import org.osmdroid.tileprovider.tilesource.ITileSource;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import android.graphics.drawable.Drawable;/** * An abstract base class for modular tile providers * * @author Marc Kurtz * @author Neil Boyd */public abstract class MapTileModuleProviderBase implements OpenStreetMapTileProviderConstants {/** * Gets the human-friendly name assigned to this tile provider. * * @return the thread name */protected abstract String getName();/** * Gets the name assigned to the thread for this provider. * * @return the thread name */protected abstract String getThreadGroupName();/** * It is expected that the implementation will construct an internal member which internally * implements a {@link TileLoader}. This method is expected to return a that internal member to * methods of the parent methods. * * @return the internal member of this tile provider. */protected abstract Runnable getTileLoader();/** * Returns true if implementation uses a data connection, false otherwise. This value is used to * determine if this provider should be skipped if there is no data connection. * * @return true if implementation uses a data connection, false otherwise */public abstract boolean getUsesDataConnection();/** * Gets the minimum zoom level this tile provider can provide * * @return the minimum zoom level */public abstract int getMinimumZoomLevel();/** * Gets the maximum zoom level this tile provider can provide * * @return the maximum zoom level */public abstract int getMaximumZoomLevel();/** * Sets the tile source for this tile provider. * * @param tileSource * the tile source */public abstract void setTileSource(ITileSource tileSource);private final ExecutorService mExecutor;private static final Logger logger = LoggerFactory.getLogger(MapTileModuleProviderBase.class);protected final Object mQueueLockObject = new Object();protected final HashMap<MapTile, MapTileRequestState> mWorking;protected final LinkedHashMap<MapTile, MapTileRequestState> mPending;public MapTileModuleProviderBase(int pThreadPoolSize, final int pPendingQueueSize) {if (pPendingQueueSize < pThreadPoolSize) {logger.warn("The pending queue size is smaller than the thread pool size. Automatically reducing the thread pool size.");pThreadPoolSize = pPendingQueueSize;}mExecutor = Executors.newFixedThreadPool(pThreadPoolSize,new ConfigurablePriorityThreadFactory(Thread.NORM_PRIORITY, getThreadGroupName()));mWorking = new HashMap<MapTile, MapTileRequestState>();mPending = new LinkedHashMap<MapTile, MapTileRequestState>(pPendingQueueSize + 2, 0.1f,true) {private static final long serialVersionUID = 6455337315681858866L;@Overrideprotected boolean removeEldestEntry(final Map.Entry<MapTile, MapTileRequestState> pEldest) {if (size() > pPendingQueueSize) {MapTile result = null;// get the oldest tile that isn't in the mWorking queueIterator<MapTile> iterator = mPending.keySet().iterator();while (result == null && iterator.hasNext()) {final MapTile tile = iterator.next();if (!mWorking.containsKey(tile)) {result = tile;}}if (result != null) {MapTileRequestState state = mPending.get(result);removeTileFromQueues(result);state.getCallback().mapTileRequestFailed(state);}}return false;}};}public void loadMapTileAsync(final MapTileRequestState pState) {synchronized (mQueueLockObject) {if (DEBUG_TILE_PROVIDERS) {logger.debug("MapTileModuleProviderBase.loadMaptileAsync() on provider: "+ getName() + " for tile: " + pState.getMapTile());if (mPending.containsKey(pState.getMapTile()))logger.debug("MapTileModuleProviderBase.loadMaptileAsync() tile already exists in request queue for modular provider. Moving to front of queue.");elselogger.debug("MapTileModuleProviderBase.loadMaptileAsync() adding tile to request queue for modular provider.");}// this will put the tile in the queue, or move it to the front of// the queue if it's already presentmPending.put(pState.getMapTile(), pState);}try {mExecutor.execute(getTileLoader());} catch (final RejectedExecutionException e) {logger.warn("RejectedExecutionException", e);}}private void clearQueue() {synchronized (mQueueLockObject) {mPending.clear();mWorking.clear();}}/** * Detach, we're shutting down - Stops all workers. */public void detach() {this.clearQueue();this.mExecutor.shutdown();}void removeTileFromQueues(final MapTile mapTile) {synchronized (mQueueLockObject) {if (DEBUG_TILE_PROVIDERS) {logger.debug("MapTileModuleProviderBase.removeTileFromQueues() on provider: "+ getName() + " for tile: " + mapTile);}mPending.remove(mapTile);mWorking.remove(mapTile);}}/** * Load the requested tile. An abstract internal class whose objects are used by worker threads * to acquire tiles from servers. It processes tiles from the 'pending' set to the 'working' set * as they become available. The key unimplemented method is 'loadTile'. */protected abstract class TileLoader implements Runnable {/** * Load the requested tile. * * @return the tile if it was loaded successfully, or null if failed to * load and other tile providers need to be called * @param pState * @throws CantContinueException */protected abstract Drawable loadTile(MapTileRequestState pState)throws CantContinueException;protected void onTileLoaderInit() {// Do nothing by default}protected void onTileLoaderShutdown() {// Do nothing by default}protected MapTileRequestState nextTile() {synchronized (mQueueLockObject) {MapTile result = null;// get the most recently accessed tile// - the last item in the iterator that's not already being// processedIterator<MapTile> iterator = mPending.keySet().iterator();// TODO this iterates the whole list, make this faster...while (iterator.hasNext()) {final MapTile tile = iterator.next();if (!mWorking.containsKey(tile)) {if (DEBUG_TILE_PROVIDERS) {logger.debug("TileLoader.nextTile() on provider: " + getName()+ " found tile in working queue: " + tile);}result = tile;}}if (result != null) {if (DEBUG_TILE_PROVIDERS) {logger.debug("TileLoader.nextTile() on provider: " + getName()+ " adding tile to working queue: " + result);}mWorking.put(result, mPending.get(result));}return (result != null ? mPending.get(result) : null);}}/** * A tile has loaded. */protected void tileLoaded(final MapTileRequestState pState, final Drawable pDrawable) {if (DEBUG_TILE_PROVIDERS) {logger.debug("TileLoader.tileLoaded() on provider: " + getName() + " with tile: "+ pState.getMapTile());}removeTileFromQueues(pState.getMapTile());pState.getCallback().mapTileRequestCompleted(pState, pDrawable);}/** * A tile has loaded but it's expired. * Return it <b>and</b> send request to next provider. */protected void tileLoadedExpired(final MapTileRequestState pState, final Drawable pDrawable) {if (DEBUG_TILE_PROVIDERS) {logger.debug("TileLoader.tileLoadedExpired() on provider: " + getName()+ " with tile: " + pState.getMapTile());}removeTileFromQueues(pState.getMapTile());pState.getCallback().mapTileRequestExpiredTile(pState, pDrawable);}protected void tileLoadedFailed(final MapTileRequestState pState) {if (DEBUG_TILE_PROVIDERS) {logger.debug("TileLoader.tileLoadedFailed() on provider: " + getName()+ " with tile: " + pState.getMapTile());}removeTileFromQueues(pState.getMapTile());pState.getCallback().mapTileRequestFailed(pState);}/** * This is a functor class of type Runnable. The run method is the encapsulated function. */@Overridefinal public void run() {onTileLoaderInit();MapTileRequestState state;Drawable result = null;while ((state = nextTile()) != null) {if (DEBUG_TILE_PROVIDERS) {logger.debug("TileLoader.run() processing next tile: " + state.getMapTile());}try {result = null;result = loadTile(state);} catch (final CantContinueException e) {logger.info("Tile loader can't continue: " + state.getMapTile(), e);clearQueue();} catch (final Throwable e) {logger.error("Error downloading tile: " + state.getMapTile(), e);}if (result == null) {tileLoadedFailed(state);} else if (ExpirableBitmapDrawable.isDrawableExpired(result)) {tileLoadedExpired(state, result);} else {tileLoaded(state, result);}}onTileLoaderShutdown();}}/** * Thrown by a tile provider module in TileLoader.loadTile() to signal that it can no longer * function properly. This will typically clear the pending queue. */public class CantContinueException extends Exception {private static final long serialVersionUID = 146526524087765133L;public CantContinueException(final String pDetailMessage) {super(pDetailMessage);}public CantContinueException(final Throwable pThrowable) {super(pThrowable);}}}
这个类主要提供了一个异步加载TileModule的接口,并且这个类默认是提供了对异步加载的同步处理和加载线程队列的处理;
Demo
如果我们自己要实现自己的Tile加载类只需要实现getTileLoader和TileLoader的loadTile接口即可,下面写了个demo:
/* (non-Javadoc) * @see org.osmdroid.tileprovider.modules.MapTileModuleProviderBase#getTileLoader() */@Overrideprotected Runnable getTileLoader() {return new MapTileModuleProviderBase.TileLoader() {@Overrideprotected Drawable loadTile(MapTileRequestState pState) throws CantContinueException {String path = pState.getMapTile().toString();Drawable drawable;try {drawable = getDrawable(path);// do it } catch (final LowMemoryException e) {// low memory so empty the queuethrow new CantContinueException(e);}if (drawable == null) {throw new CantContinueException("not map data!");}return drawable;}};}如果自己管理加载队列需要修改的内容有点多,因为要实现相关UI处理接口等一系列接口(不推荐)。
0 0
- OSMDroid源码分析之瓦片载入基类:MapTileModuleProviderBase
- OSMDroid源码分析之Cache:MapTileFilesystemProvider
- 三、osmdroid离线地图瓦片使用
- Osmdroid源码编译
- cocos2dx源代码分析之TMXTiled 瓦片地图
- 瓦片地图类之CCTMXTiledMap
- 瓦片地图类之CCTMXTiledMap
- osmdroid 在线加载谷歌瓦片(谷歌地图瓦片地址解释)
- Flume-NG源码分析-整体结构及配置载入分析
- 【源码分析】Elastic-Job源码分析之JobScheduler类分析
- cocos2dx之瓦片地图
- cocos2dx之瓦片地图
- spring源码阅读(六)之BeanDefinition的载入
- 2017版高德地图瓦片分析
- Osmdroid 离线地图存放位置的研究和详细分析
- libgdx之瓦片地图(TiledMap)
- Nutch抓取源码分析之Crawl类
- Nutch抓取源码分析之Injector类
- 比较全面的GDB调试用法
- VIM中arg和argdo的使用介绍
- java数据类型转换
- 自己动手编写一个VS插件(五)
- Ice_cream's world I hdu 2120 并查集判断环
- OSMDroid源码分析之瓦片载入基类:MapTileModuleProviderBase
- Linux系统虚拟内存空间
- java循环某年某月的所有天数
- 安卓uses-sdk有警告去除警告的方法
- STL——容器特征总结
- VimScript脚本语言学习------常用的内置函数---(操纵Float)
- 【作品展示】双向热电偶热电阻分度表软件
- go语言获取本地IP地址(图形界面)
- 海贼王