重写TiledServiceLayer实现本地缓存

本文介绍了一种在移动端应用中实现地图切片缓存的方法,通过判断本地是否存在所需地图切片来减少网络请求,提高用户体验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        有时候移动端网络不是很稳定,而且在没有Wifi情况下访问非常费流量,网速也较慢,因此实现本地缓存功能已经显得刻不容缓了。虽然现在Arcgis官方对Android还不支持这个功能,但我们完全可以自己去实现。其实思路很简单,就是在每次访问服务端的之前去判断本地是否有这个图片,如果有就读取本地的,否则去服务端获取并保存到本地。可以更形象一点:

if(本地是否有这个切片){
         读取本地图片;
   }else{
         去服务端获取;
         保存到本地;   
   }
对就是这么简单,下面我们看代码。

一些的参数

 private Envelope fullExtent = new Envelope(38271382.590048, 3958604.25302, 38524317.872452, 4118706.90518);//全服范围
	    private Envelope initExtent = new Envelope(38271382.590048, 3958604.25302, 38524317.872452, 4118706.90518);//初始范围
	    private TileInfo tileInfo; //TiledServiceLayer.TileInfo
            private SpatialReference spatialReference;//空间参考
            private String layerurl; //Url
	    private String cachepath;//本地存储路径
初始化Tileinfo

private void initTileInfo(){
                spatialReference = SpatialReference.create(2363); //空间参考
		/*原点坐标*/
	        Point localPoint = new Point(3.28768E7,1.00021E7);
	        /*地图分辨率*/
		double[] arrayOfDoubleres = {529.16772500211675, 264.58386250105838, 132.29193125052919, 
					66.145965625264594, 33.072982812632297, 16.933367200067735,
					8.4666836000338677,4.2333418000169338, 2.1166709000084669, 
					1.0583354500042335, 0.52916772500211673, 0.26458386250105836};
	       /*地图比例尺*/
	       double[] arrayOfDoublescale = {2000000.0, 1000000.0, 500000.0, 250000.0, 125000.0, 64000.0, 32000.0, 16000.0, 
                                        8000.0, 4000.0, 2000.0, 1000.0};
	       int levels = arrayOfDoublescale.length;
	       int dpi=96;
	       int tileHeight = 256;//图片高度
	       int tileWidth = 256;//图片宽度
	       tileInfo = new TileInfo(localPoint, arrayOfDoublescale, arrayOfDoubleres,levels, dpi, tileWidth, tileHeight);
	}
重载initLayer()方法

@Override
		protected void initLayer() {
			// TODO Auto-generated method stub
			if(getID()==0){
				this.nativeHandle = create();
			}
			setFullExtent(fullExtent);//设置全服地图范围
			setTileInfo(tileInfo);//设置tileInfo
			setInitialExtent(initExtent);//设置初始化地图范围
			setDefaultSpatialReference(spatialReference);//设置空间参考
			super.initLayer();
		}
重载geTile()方法

@Override
		protected byte[] getTile(int level, int col, int row) throws Exception {
			// TODO Auto-generated method stub
			byte[] bytes = getOfflineCacheFile(level,col,row);//从本地获取图片
			   if (bytes == null) {//如果本地没有则去服务端获取
				HashMap localHashMap = new HashMap();
				bytes = a.a(strlayer, localHashMap);
				AddOfflineCacheFile(level, col, row, bytes);//保存到本地
			    }
			}
			return bytes;
		}
下面是完整的代码

package com.test.common.utils;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;

import android.util.Log;

import com.esri.android.map.TiledServiceLayer;
import com.esri.core.geometry.Envelope;
import com.esri.core.geometry.Point;
import com.esri.core.geometry.SpatialReference;
import com.esri.core.internal.b.a.a;
/**
 * 
 * @ClassName:   OfflineCacheTiledServiceLayer
 * @Description: 实现本地缓存
 * @author:              Zrd
 * @version:            v1.0  
 * @modify:      TODO(版本修改信息)
 */

public class OfflineCacheTiledServiceLayer  extends TiledServiceLayer {
	    private SpatialReference spatialReference; //空间参考
	    private Envelope fullExtent = new Envelope(38271382.590048, 3958604.25302, 38524317.872452, 4118706.90518);//全服范围
	    private Envelope initExtent = new Envelope(38271382.590048, 3958604.25302, 38524317.872452, 4118706.90518);//初始范围
	    private TileInfo tileInfo; //TiledServiceLayer.TileInfo
	    
	    private String layerurl; //Url
	    private String cachepath;//本地存储路径
	    
		public OfflineCacheTiledServiceLayer(String layerurl,String cachepath) {
			super(layerurl);
			// TODO Auto-generated constructor stub
			this.layerurl = layerurl;
			this.cachepath = cachepath;
			initTileInfo();
			OfflineCacheTiledServiceLayer.this.initLayer();
		}
		private void initTileInfo(){
			spatialReference = SpatialReference.create(2363); //空间参考
			/*原点坐标*/
	        Point localPoint = new Point(3.28768E7,1.00021E7);
	        /*地图分辨率*/
		    double[] arrayOfDoubleres = {529.16772500211675, 264.58386250105838, 132.29193125052919, 
					66.145965625264594, 33.072982812632297, 16.933367200067735,
					8.4666836000338677,4.2333418000169338, 2.1166709000084669, 
					1.0583354500042335, 0.52916772500211673, 0.26458386250105836};
		    /*地图比例尺*/
		    double[] arrayOfDoublescale = {2000000.0, 1000000.0, 500000.0, 250000.0, 125000.0, 64000.0, 32000.0, 16000.0, 8000.0, 4000.0, 2000.0, 1000.0};
			int k = arrayOfDoublescale.length;
			int dpi=96;
			int tileHeight = 256;//图片高度
		    int tileWidth = 256;//图片宽度
			tileInfo = new TileInfo(localPoint, arrayOfDoublescale, arrayOfDoubleres, k, dpi, tileWidth, tileHeight);
		}
		
		@Override
		protected void initLayer() {
			// TODO Auto-generated method stub
			if(getID()==0){
				this.nativeHandle = create();
			}
			setFullExtent(fullExtent);//设置全服地图范围
			setTileInfo(tileInfo);//设置tileInfo
			setInitialExtent(initExtent);//设置初始化地图范围
			setDefaultSpatialReference(spatialReference);//设置空间参考
			super.initLayer();
		}


		@Override
		public TileInfo getTileInfo() {
			// TODO Auto-generated method stub
			return this.tileInfo;
		}

		@Override
		public Envelope getFullExtent() {
			// TODO Auto-generated method stub
			return this.fullExtent;
		}

		@Override
		public SpatialReference getSpatialReference() {
			// TODO Auto-generated method stub
			return this.spatialReference;
		}

		
		@Override
		protected byte[] getTile(int level, int col, int row) throws Exception {
			// TODO Auto-generated method stub
			System.out.println("level=" + level + " col=" + col + " row=" + row);
			String strlayer = layerurl+"/tile/"+level+"/"+row+"/"+col;
			System.out.println(strlayer);
			Log.i("strlayer", strlayer);
			byte[] bytes = getOfflineCacheFile(level,col,row);
			    if (bytes == null) {
				HashMap localHashMap = new HashMap();
				bytes = a.a(strlayer, localHashMap);
				Log.e("test", bytes.toString());
				AddOfflineCacheFile(level, col, row, bytes);
			    }
			}
			return bytes;
		}
		//将图片保存到本地 目录结构可以随便定义 只要你找得到对应的图片
		private byte[] AddOfflineCacheFile(int level, int col, int row,byte[] bytes){
			File file = new File(cachepath);
			if(!file.exists()){
				file.mkdirs();
			}
			File levelfile = new File(cachepath+"/"+level);
			if(!levelfile.exists()){
				levelfile.mkdirs();
			}
			File colfile = new File(cachepath+"/"+level+"/"+col);
			if(!colfile.exists()){
				colfile.mkdirs();
			}
			File rowfile = new File(cachepath+"/"+level+"/"+col+"/"+row+".dat");
			if(!rowfile.exists()){
				try {
					FileOutputStream out = new FileOutputStream(rowfile);
					out.write(bytes);
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			return bytes;
			
		}
		//从本地获取图片
		private byte[] getOfflineCacheFile(int level, int col, int row){
			byte[] bytes = null;
			File rowfile = new File(cachepath+"/"+level+"/"+col+"/"+row+".dat");
			if(rowfile.exists()){
				try {
					bytes = CopySdcardbytes(rowfile);
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}else{
				bytes = null;
			}
			return bytes;
		}
        //读取本地图片流
		public byte[] CopySdcardbytes(File file) throws IOException  
	    {  
	        FileInputStream in = new FileInputStream(file);  
	          
	        ByteArrayOutputStream out = new ByteArrayOutputStream(1024);  
	          
	        byte[] temp=new byte[1024];  
	          
	        int size=0;  
	          
	        while((size=in.read(temp))!=-1)  
	        {  
	            out.write(temp,0,size);  
	        }  
	        in.close();  
	        byte[] bytes=out.toByteArray();  
	        return bytes;  
	    }  

}





评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值