1. 描述:
最近忙做个小项目,涉及到百度地图,其大致功能如下:
从服务器端(webService写的)获取数据,全部接收一次有2M左右,1000+数据,要把这些数据显示到地图上,点击有详细信息,思考了下怎么去写,记录下,方便以后进行查看。
2. 思路:
1. 数据量稍大,按理说应该每次点进界面就刷新数据,但是每次接收2M流量吃不消,且根据数据源更新速度不是很快的问题进行优化,优化思路如下:
- 数据缓存,SQLite数据库进行数据缓存;
- 打开界面时判断是否已经存在数据,存在则根据时间去获取当前时间间隔内的服务器数据(服务器沟通写好)
- 服务器端数据压缩,压缩后安卓端进行解析
2. 要在界面上显示数据,1000+的话只能根据当前界面的经纬度范围去显示当前范围内的数据,百度提供现成的获取当前屏幕尺寸的方法,获取之后发现判断范围不是特别准,就把范围相应扩大,并在范围内数据过多时不显示(数据直接全部从数据库中读取)
3. 实现
1. 根据时间不同进行刷新数据
private void getWebServiceData(String col) {
// 表示第一次访问航标相关数据,需要连接webService进行更新
if (getDataAccordingToTime() == -1) {
new GetShip(webUrl, "Getcbxx", col).execute();
} else if (getDataAccordingToTime() < 600000) {
// 10min内没有访问,不刷新
SQlShipDao sd = new SQlShipDao(NewShipMap.this);
// 先查询数据库中是否有数据,没有则获取
if (!sd.chechkCount(col)) {
new GetShip(webUrl, "Getcbxx", col).execute();
} else {
tipsBD.setText("滑动地图以查看航标情况");
}
} else {
new GetShip(webUrl, "Getcbxx", col,getDataAccordingToTime())
.execute();
}
}
时间和获取数据的方式需要根据自己数据的特点来分析,这里第一次访问的话数据库肯定没有数据直接刷新,若10min内第二次访问则先去判断数据库中是否有数据,有直接查看,没有则刷新,超过10min直接刷新,
获取此时间内的网络数据.
参考函数:
private long getDataAccordingToTime() {
SharedPreferences settings = getSharedPreferences("timeA", 0);
long time = settings.getLong("timeA", 0);
if (time == 0) {
return -1;
} else {
long per = time - System.currentTimeMillis();
return per;
}
}
2. 获取当前屏幕的经纬度,滑动停止的时候重绘界面
private void changeMapGetRegion() {
OnMapStatusChangeListener listener = new OnMapStatusChangeListener() {
/**
* 手势操作地图,设置地图状态等操作导致地图状态开始改变。
*
* @param status
* 地图状态改变开始时的地图状态
*/
public void onMapStatusChangeStart(MapStatus status) {
}
/**
* 地图状态变化中
*
* @param status
* 当前地图状态
*/
public void onMapStatusChange(MapStatus status) {
mMarkerInfoLy.setVisibility(View.GONE);
tipsBD.setVisibility(View.GONE);
}
/**
* 地图状态改变结束
*
* @param status
* 地图状态改变结束后的地图状态
*/
public void onMapStatusChangeFinish(MapStatus status) {
synchronized (this) {
LatLng RTOld = status.bound.northeast;
LatLng LBOld = status.bound.southwest;
//此处哦按段区域范围不是特别准确,故手动加减裕量
LatLng RT = new LatLng(RTOld.latitude + 0.02,
RTOld.longitude + 0.02);
LatLng LB = new LatLng(LBOld.latitude - 0.02,
LBOld.longitude - 0.02);
//数据库中获取当前范围的数据
SQlShipDao sd = new SQlShipDao(NewShipMap.this);
hbList = sd.queryAll(column, RT, LB);
if (hbList.size() > 100) {
hbList = null;
}
//利用Handler更新数据
Message msg = new Message();
msg.what = 0x01;
mHandler.sendMessage(msg);
}
}
};
mMapView.getMap().setOnMapStatusChangeListener(listener);
}
3. Handler更新界面
private void changeUI() {
mHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case 0x01:
// hbList中保存有当前屏幕范围内的航标数据
try {
if (mBaiduMap != null) {
mBaiduMap.clear();
}
} catch (Exception e) {
}
if (hbList == null) {
break;
}
for (HBShipClass hb : hbList) {
LatLng latLng1 = new LatLng(Double.valueOf(hb
.getFLATESTLAT()), Double.valueOf(hb
.getFLATESTLON()));
Bundle bundle = new Bundle();
bundle.putSerializable("info", hb);
if(hb.getFLATESTSPEED().length()<2){//
setMarker(latLng1, blackship);
marker.setExtraInfo(bundle);
}else{
setMarker(latLng1, redship);
marker.setExtraInfo(bundle);
}
}
break;
}
}
};
}
参考方法:
/**
* 设置图标
*
* @param latLng1
* @param bd
*/
private void setMarker(LatLng latLng1, BitmapDescriptor bd) {
oo = new MarkerOptions().position(latLng1).icon(bd).zIndex(9)
.draggable(true);
marker = (Marker) (mBaiduMap.addOverlay(oo));
}
4. 点击图标弹出相应的信息
/**
* 复用弹出面板mMarkerLy的控件
*
* @author lyh
*/
private class ViewHolder {
TextView MMSID;
TextView shipType;
TextView cx;
TextView sydw;
LinearLayout ivDetail;
TextView recTime;
}
private void initMarkerClickEvent() {
// 对Marker的点击
mBaiduMap.setOnMarkerClickListener(new OnMarkerClickListener() {
@Override
public boolean onMarkerClick(final Marker marker) {
// 获得marker中的数据
HBShipClass info = (HBShipClass) marker.getExtraInfo().get(
"info");
InfoWindow mInfoWindow;
Button button = new Button(getApplicationContext());
button.setBackgroundResource(R.drawable.pop3);
button.setPadding(30, 20, 30, 50);
button.setText(info.getMMSID());
button.setTextColor(Color.BLACK);
final LatLng ll = marker.getPosition();
Point p = mBaiduMap.getProjection().toScreenLocation(ll);
p.y -= 47;
LatLng llInfo = mBaiduMap.getProjection().fromScreenLocation(p);
mMarkerInfoLy.setVisibility(View.VISIBLE);
// 为弹出的InfoWindow添加点击事件
mInfoWindow = new InfoWindow(BitmapDescriptorFactory
.fromView(button), llInfo, 0,
new OnInfoWindowClickListener() {
@Override
public void onInfoWindowClick() {
// 隐藏InfoWindow
mBaiduMap.hideInfoWindow();
}
});
// 显示InfoWindow
mBaiduMap.showInfoWindow(mInfoWindow);
popupInfo(mMarkerInfoLy, info);
return true;
}
});
}
protected void popupInfo(RelativeLayout mMarkerLy, HBShipClass info) {
info1=info;
ViewHolder viewHolder = null;
if (mMarkerLy.getTag() == null) {
viewHolder = new ViewHolder();
viewHolder.MMSID = (TextView) findViewById(R.id.MMSID);
viewHolder.shipType = (TextView) findViewById(R.id.shipType);
viewHolder.cx = (TextView) findViewById(R.id.cx);
viewHolder.sydw = (TextView) findViewById(R.id.sydw);
viewHolder.recTime = (TextView) findViewById(R.id.recTime);
viewHolder.ivDetail = (LinearLayout) findViewById(R.id.touchJump);
viewHolder.ivDetail.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
Intent intent = new Intent(NewShipMap.this, HBDetail.class);
Bundle bundle = new Bundle();
bundle.putSerializable("info", info1);
intent.putExtras(bundle);
startActivity(intent);
}
});
mMarkerLy.setTag(viewHolder);
}
viewHolder = (ViewHolder) mMarkerLy.getTag();
viewHolder.MMSID.setText("ID:" + info.getMMSID());
viewHolder.shipType.setText(info.getCBLB());
viewHolder.cx.setText(info.getCX());
viewHolder.sydw.setText(info.getSYDW());
viewHolder.recTime.setText(info.getFLATESTTIME());
}
大致的思路就这样,后面的细节需要自己思考咯~
结果如图:
苦逼学生党,一面准备找工作,一面被**,美工设计服务器全包了...程序思路若是有更好的实现方式,还望各位不吝赐教。