Android版百度地图MapView维护(dialog中放一个MapView)

本文详细探讨了在Android应用中使用百度地图SDK时遇到的地图刷新问题,并提供了有效的解决方案。通过调整MapView的onResume和onPause方法,确保了地图在Dialog和Activity间的正常切换。

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

最近项目工程使用百度地图,功能确实强大,但就像论坛里很多人提的那样,在MapView的刷新问题上,百度地图还有一定bug,比如在一个dialog中放一个MapView,却发现dialog中的MapView展现效果很差,很多地图上的标志没有刷新出来。比如下图:


我们可以看到整个地图完全乱套了,现在我贴在这个dialog的代码,然后一起分析下问题。

  1. package baidumapsdk.demo;  
  2.   
  3. import android.app.Dialog;  
  4. import android.content.Context;  
  5. import android.view.View;  
  6. import android.view.Window;  
  7. import android.widget.Button;  
  8.   
  9. import com.baidu.mapapi.map.MapView;  
  10. import com.baidu.platform.comapi.basestruct.GeoPoint;  
  11.   
  12. public class MapDialog extends Dialog{  
  13.   
  14.     /** 
  15.      *  MapView 是地图主控件 
  16.      */  
  17.     private MapView mMapView = null;  
  18.     private Button mBtnBack = null;  
  19.     public MapDialog(Context context) {  
  20.         super(context);  
  21.         requestWindowFeature(Window.FEATURE_NO_TITLE);  
  22.         setContentView(R.layout.mapdialog);  
  23.         mMapView = (MapView)findViewById(R.id.bmapView);  
  24.         mMapView.setBuiltInZoomControls(true);  
  25.         mMapView.getController().setCenter(new GeoPoint((int)(39.945 * 1E6), (int)(116.404 * 1E6)));  
  26.         mBtnBack = (Button)findViewById(R.id.btn_back);  
  27.         mBtnBack.setOnClickListener(new View.OnClickListener() {  
  28.               
  29.             @Override  
  30.             public void onClick(View v) {  
  31.                 // TODO Auto-generated method stub  
  32.                 dismiss();  
  33.             }  
  34.         });  
  35.     }  
  36.     @Override  
  37.     public void dismiss() {  
  38.         super.dismiss();  
  39.     }  
  40.           
  41.       
  42. }  

我们看到在Dialog中我们就直接从xml中引用了地图,不过在百度地图Hello World 介绍中,百度地图似乎还调动了MapView的onResume和onPause等方法,虽然它们都是在Activity中调用的,而我们这是Dialog,但没有条件我们可以创造条件调用,直接在构造函数里调用onResume,dismiss()里调用onPause。
  1. package baidumapsdk.demo;  
  2.   
  3. import android.app.Dialog;  
  4. import android.content.Context;  
  5. import android.view.View;  
  6. import android.view.Window;  
  7. import android.widget.Button;  
  8.   
  9. import com.baidu.mapapi.map.MapView;  
  10. import com.baidu.platform.comapi.basestruct.GeoPoint;  
  11.   
  12. public class MapDialog extends Dialog{  
  13.   
  14.     /** 
  15.      *  MapView 是地图主控件 
  16.      */  
  17.     private MapView mMapView = null;  
  18.     private Button mBtnBack = null;  
  19.     public MapDialog(Context context) {  
  20.         super(context);  
  21.         requestWindowFeature(Window.FEATURE_NO_TITLE);  
  22.         setContentView(R.layout.mapdialog);  
  23.         mMapView = (MapView)findViewById(R.id.bmapView);  
  24.         mMapView.setBuiltInZoomControls(true);  
  25.         mMapView.onResume();  
  26.         mMapView.getController().setCenter(new GeoPoint((int)(39.945 * 1E6), (int)(116.404 * 1E6)));  
  27.         mBtnBack = (Button)findViewById(R.id.btn_back);  
  28.         mBtnBack.setOnClickListener(new View.OnClickListener() {  
  29.               
  30.             @Override  
  31.             public void onClick(View v) {  
  32.                 // TODO Auto-generated method stub  
  33.                 dismiss();  
  34.             }  
  35.         });  
  36.     }  
  37.     @Override  
  38.     public void dismiss() {  
  39.         mMapView.onPause();  
  40.         super.dismiss();  
  41.     }  
  42.       
  43.   
  44.       
  45.       
  46. }  

这个时候似乎我们的使用有效果了,这样使用方式Dialog中MapView刷新没有问题了。

但是新问题来了。我们Dialog一般都是在Activity中调用的,如果调用的Activity中也有MapView。

  1. package baidumapsdk.demo;  
  2.   
  3. import android.app.Activity;  
  4. import android.content.Intent;  
  5. import android.graphics.Bitmap;  
  6. import android.os.Bundle;  
  7. import android.view.View;  
  8. import android.view.View.OnClickListener;  
  9. import android.widget.Button;  
  10. import android.widget.Toast;  
  11.   
  12. import com.baidu.mapapi.BMapManager;  
  13. import com.baidu.mapapi.map.MKMapViewListener;  
  14. import com.baidu.mapapi.map.MKOfflineMap;  
  15. import com.baidu.mapapi.map.MKOfflineMapListener;  
  16. import com.baidu.mapapi.map.MapController;  
  17. import com.baidu.mapapi.map.MapPoi;  
  18. import com.baidu.mapapi.map.MapView;  
  19. import com.baidu.platform.comapi.basestruct.GeoPoint;  
  20.   
  21. /** 
  22.  * 演示MapView的基本用法 
  23.  */  
  24. public class BaseMapDemo extends Activity implements MKOfflineMapListener{  
  25.   
  26.     final static String TAG = "MainActivity";  
  27.     /** 
  28.      *  MapView 是地图主控件 
  29.      */  
  30.     private MapView mMapView = null;  
  31.     /** 
  32.      *  用MapController完成地图控制  
  33.      */  
  34.     private MapController mMapController = null;  
  35.       
  36.     private Button mBtnDialog = null;  
  37.     private Button mBtnActivity = null;  
  38.       
  39.     private MKOfflineMap mOffline = null;  
  40.       
  41.       
  42.     @Override  
  43.     public void onCreate(Bundle savedInstanceState) {  
  44.         super.onCreate(savedInstanceState);  
  45.         /** 
  46.          * 使用地图sdk前需先初始化BMapManager. 
  47.          * BMapManager是全局的,可为多个MapView共用,它需要地图模块创建前创建, 
  48.          * 并在地图地图模块销毁后销毁,只要还有地图模块在使用,BMapManager就不应该销毁
  49.          */  
  50.         DemoApplication app = (DemoApplication)this.getApplication();  
  51.         if (app.mBMapManager == null) {  
  52.             app.mBMapManager = new BMapManager(this);  
  53.             /** 
  54.              * 如果BMapManager没有初始化则初始化BMapManager 
  55.              */  
  56.             app.mBMapManager.init(DemoApplication.strKey,new DemoApplication.MyGeneralListener());  
  57.         }  
  58.         /** 
  59.           * 由于MapView在setContentView()中初始化,所以它需要在BMapManager初始化之后 
  60.           */  
  61.         setContentView(R.layout.activity_main);  
  62.         mMapView = (MapView)findViewById(R.id.bmapView);  
  63.         mMapView.setBuiltInZoomControls(true);  
  64.         /** 
  65.          * 获取地图控制器 
  66.          */  
  67.         mMapController = mMapView.getController();  
  68.         /** 
  69.          *  设置地图是否响应点击事件  . 
  70.          */  
  71.         mMapController.enableClick(true);  
  72.         /** 
  73.          * 设置地图缩放级别 
  74.          */  
  75.         mMapController.setZoom(12);  
  76.          
  77.         /** 
  78.          * 将地图移动至指定点 
  79.          * 使用百度经纬度坐标,可以通过http://api.map.baidu.com/lbsapi/getpoint/index.html查询地理坐
  80.          * 如果需要在百度地图上显示使用其他坐标系统的位置,请发邮件至mapapi@baidu.com申请坐标转换接口。
  81.          */  
  82.         GeoPoint p ;  
  83.         double cLat = 39.945 ;  
  84.         double cLon = 116.404 ;  
  85.         Intent  intent = getIntent();  
  86.         if ( intent.hasExtra("x") && intent.hasExtra("y") ){  
  87.             //当用intent参数时,设置中心点为指定点  
  88.             Bundle b = intent.getExtras();  
  89.             p = new GeoPoint(b.getInt("y"), b.getInt("x"));  
  90.         }else{  
  91.             //设置中心点为天安门  
  92.              p = new GeoPoint((int)(cLat * 1E6), (int)(cLon * 1E6));  
  93.         }  
  94.           
  95.         mMapController.setCenter(p);  
  96.           
  97.         mOffline = new MKOfflineMap();      
  98.         /** 
  99.          * 初始化离线地图模块,MapControler可从MapView.getController()获取 
  100.          */  
  101.         mOffline.init(mMapController, this);  
  102.    //     mOffline.scan();  
  103.         mBtnActivity = (Button)findViewById(R.id.btn_activity);  
  104.         mBtnDialog = (Button)findViewById(R.id.btn_dialog);  
  105.         mBtnActivity.setOnClickListener(new OnClickListener() {  
  106.               
  107.             @Override  
  108.             public void onClick(View v) {  
  109.                 // TODO Auto-generated method stub  
  110.                 Intent intent = new Intent(BaseMapDemo.this, GeometryDemo.class);  
  111.                 startActivity(intent);  
  112.             }  
  113.         });  
  114.         mBtnDialog.setOnClickListener(new OnClickListener() {  
  115.               
  116.             @Override  
  117.             public void onClick(View v) {  
  118.                 // TODO Auto-generated method stub  
  119.                 MapDialog dialog = new MapDialog(BaseMapDemo.this);  
  120.                 dialog.show();  
  121.             }  
  122.         });  
  123.     }  
  124.       
  125.     @Override  
  126.     protected void onPause() {  
  127.         /** 
  128.          *  MapView的生命周期与Activity同步,当activity挂起时需调用MapView.onPause()
  129.          */  
  130.         mMapView.onPause();  
  131.         super.onPause();  
  132.     }  
  133.       
  134.     @Override  
  135.     protected void onResume() {  
  136.         /** 
  137.          *  MapView的生命周期与Activity同步,当activity恢复时需调用MapView.onResume()
  138.          */  
  139.         mMapView.onResume();  
  140.         super.onResume();  
  141.     }  
  142.       
  143.     @Override  
  144.     protected void onDestroy() {  
  145.         /** 
  146.          *  MapView的生命周期与Activity同步,当activity销毁时需调用MapView.destroy()
  147.          */  
  148.         mMapView.destroy();  
  149.         super.onDestroy();  
  150.     }  
  151.       
  152.     @Override  
  153.     protected void onSaveInstanceState(Bundle outState) {  
  154.         super.onSaveInstanceState(outState);  
  155.         mMapView.onSaveInstanceState(outState);  
  156.           
  157.     }  
  158.       
  159.     @Override  
  160.     protected void onRestoreInstanceState(Bundle savedInstanceState) {  
  161.         super.onRestoreInstanceState(savedInstanceState);  
  162.         mMapView.onRestoreInstanceState(savedInstanceState);  
  163.     }  
  164.   
  165.     @Override  
  166.     public void onGetOfflineMapState(int arg0, int arg1) {  
  167.         // TODO Auto-generated method stub  
  168.           
  169.     }  
  170.       
  171. }  

这个Activity的中使用MapView的方式就是百度官方代码使用MapView的方式,当我们dimiss了dialog,发现Activity上的MapView的刷新也出问题了,甚至我测试有的时候Activity上的MapView连动都不能动,整个屏幕像死机了一样。


而且刷新混乱的方式跟之前Dialog混乱的方式很像,之前我们解决Dialog刷新混乱的问题的时候,是在Dialog调用了MapView的onResume方法,现在我们也来在dismiss了Dialog后再次调用Activity中MapView的onResume,有onResume方法就得有相应的onPause方法对应,显然,是在show Dialog的时候让Activity中的MapView onPause。

现在我们把Dialog和Activity中代码修改如下:

  1. package baidumapsdk.demo;  
  2.   
  3. import android.app.Dialog;  
  4. import android.content.Context;  
  5. import android.view.View;  
  6. import android.view.Window;  
  7. import android.widget.Button;  
  8. import baidumapsdk.demo.BaseMapDemo.MapDialogCallback;  
  9.   
  10. import com.baidu.mapapi.map.MapView;  
  11. import com.baidu.platform.comapi.basestruct.GeoPoint;  
  12.   
  13. public class MapDialog extends Dialog{  
  14.   
  15.     /** 
  16.      *  MapView 是地图主控件 
  17.      */  
  18.     private MapView mMapView = null;  
  19.     private Button mBtnBack = null;  
  20.     private MapDialogCallback mCallback;  
  21.     public MapDialog(Context context) {  
  22.         super(context);  
  23.         requestWindowFeature(Window.FEATURE_NO_TITLE);  
  24.         setContentView(R.layout.mapdialog);  
  25.         mMapView = (MapView)findViewById(R.id.bmapView);  
  26.         mMapView.setBuiltInZoomControls(true);  
  27.         mMapView.onResume();  
  28.         mMapView.getController().setCenter(new GeoPoint((int)(39.945 * 1E6), (int)(116.404 * 1E6)));  
  29.         mBtnBack = (Button)findViewById(R.id.btn_back);  
  30.         mBtnBack.setOnClickListener(new View.OnClickListener() {  
  31.               
  32.             @Override  
  33.             public void onClick(View v) {  
  34.                 // TODO Auto-generated method stub  
  35.                 dismiss();  
  36.             }  
  37.         });  
  38.     }  
  39.     @Override  
  40.     public void dismiss() {  
  41.         mMapView.onPause();  
  42.         mCallback.mapback();  
  43.         super.dismiss();  
  44.     }  
  45.       
  46.     public void registerCallback(MapDialogCallback callback) {  
  47.         mCallback = callback;  
  48.     }  
  49.       
  50.       
  51. }  

  1. package baidumapsdk.demo;  
  2.   
  3. import android.app.Activity;  
  4. import android.content.Intent;  
  5. import android.graphics.Bitmap;  
  6. import android.os.Bundle;  
  7. import android.view.View;  
  8. import android.view.View.OnClickListener;  
  9. import android.widget.Button;  
  10. import android.widget.Toast;  
  11.   
  12. import com.baidu.mapapi.BMapManager;  
  13. import com.baidu.mapapi.map.MKMapViewListener;  
  14. import com.baidu.mapapi.map.MKOfflineMap;  
  15. import com.baidu.mapapi.map.MKOfflineMapListener;  
  16. import com.baidu.mapapi.map.MapController;  
  17. import com.baidu.mapapi.map.MapPoi;  
  18. import com.baidu.mapapi.map.MapView;  
  19. import com.baidu.platform.comapi.basestruct.GeoPoint;  
  20.   
  21. /** 
  22.  * 演示MapView的基本用法 
  23.  */  
  24. public class BaseMapDemo extends Activity implements MKOfflineMapListener{  
  25.   
  26.     final static String TAG = "MainActivity";  
  27.     /** 
  28.      *  MapView 是地图主控件 
  29.      */  
  30.     private MapView mMapView = null;  
  31.     /** 
  32.      *  用MapController完成地图控制  
  33.      */  
  34.     private MapController mMapController = null;  
  35.       
  36.     private Button mBtnDialog = null;  
  37.     private Button mBtnActivity = null;  
  38.       
  39.     private MKOfflineMap mOffline = null;  
  40.       
  41.     public interface MapDialogCallback{  
  42.         void mapback();  
  43.     }  
  44.       
  45.     @Override  
  46.     public void onCreate(Bundle savedInstanceState) {  
  47.         super.onCreate(savedInstanceState);  
  48.         /** 
  49.          * 使用地图sdk前需先初始化BMapManager. 
  50.          * BMapManager是全局的,可为多个MapView共用,它需要地图模块创建前创建, 
  51.          * 并在地图地图模块销毁后销毁,只要还有地图模块在使用,BMapManager就不应该销毁
  52.          */  
  53.         DemoApplication app = (DemoApplication)this.getApplication();  
  54.         if (app.mBMapManager == null) {  
  55.             app.mBMapManager = new BMapManager(this);  
  56.             /** 
  57.              * 如果BMapManager没有初始化则初始化BMapManager 
  58.              */  
  59.             app.mBMapManager.init(DemoApplication.strKey,new DemoApplication.MyGeneralListener());  
  60.         }  
  61.         /** 
  62.           * 由于MapView在setContentView()中初始化,所以它需要在BMapManager初始化之后
  63.           */  
  64.         setContentView(R.layout.activity_main);  
  65.         mMapView = (MapView)findViewById(R.id.bmapView);  
  66.         mMapView.setBuiltInZoomControls(true);  
  67.         /** 
  68.          * 获取地图控制器 
  69.          */  
  70.         mMapController = mMapView.getController();  
  71.         /** 
  72.          *  设置地图是否响应点击事件 
  73.          */  
  74.         mMapController.enableClick(true);  
  75.         /** 
  76.          * 设置地图缩放级别 
  77.          */  
  78.         mMapController.setZoom(12);  
  79.          
  80.         /** 
  81.          * 将地图移动至指定点 
  82.          * 使用百度经纬度坐标,可以通过http://api.map.baidu.com/lbsapi/getpoint/index.html查询地理坐标 
  83.          * 如果需要在百度地图上显示使用其他坐标系统的位置,请发邮件至mapapi@baidu.com申请坐标转换接口。
  84.          */  
  85.         GeoPoint p ;  
  86.         double cLat = 39.945 ;  
  87.         double cLon = 116.404 ;  
  88.         Intent  intent = getIntent();  
  89.         if ( intent.hasExtra("x") && intent.hasExtra("y") ){  
  90.             //当用intent参数时,设置中心点为指定点。 
  91.             Bundle b = intent.getExtras();  
  92.             p = new GeoPoint(b.getInt("y"), b.getInt("x"));  
  93.         }else{  
  94.             //设置中心点为天安门  
  95.              p = new GeoPoint((int)(cLat * 1E6), (int)(cLon * 1E6));  
  96.         }  
  97.           
  98.         mMapController.setCenter(p);  
  99.           
  100.         mOffline = new MKOfflineMap();      
  101.         /** 
  102.          * 初始化离线地图模块,MapControler可从MapView.getController()获取。
  103.          */  
  104.         mOffline.init(mMapController, this);  
  105.    //     mOffline.scan();  
  106.         mBtnActivity = (Button)findViewById(R.id.btn_activity);  
  107.         mBtnDialog = (Button)findViewById(R.id.btn_dialog);  
  108.         mBtnActivity.setOnClickListener(new OnClickListener() {  
  109.               
  110.             @Override  
  111.             public void onClick(View v) {  
  112.                 // TODO Auto-generated method stub  
  113.                 Intent intent = new Intent(BaseMapDemo.this, GeometryDemo.class);  
  114.                 startActivity(intent);  
  115.             }  
  116.         });  
  117.         mBtnDialog.setOnClickListener(new OnClickListener() {  
  118.               
  119.             @Override  
  120.             public void onClick(View v) {  
  121.                 // TODO Auto-generated method stub  
  122.                 mMapView.onPause();  
  123.                 MapDialog dialog = new MapDialog(BaseMapDemo.this);  
  124.                 dialog.registerCallback(new MapDialogCallback() {  
  125.                       
  126.                     @Override  
  127.                     public void mapback() {  
  128.                         // TODO Auto-generated method stub  
  129.                         mMapView.onResume();  
  130.                     }  
  131.                 });  
  132.                 dialog.show();  
  133.             }  
  134.         });  
  135.     }  
  136.       
  137.     @Override  
  138.     protected void onPause() {  
  139.         /** 
  140.          *  MapView的生命周期与Activity同步,当activity挂起时需调用MapView.onPause()
  141.          */  
  142.         mMapView.onPause();  
  143.         super.onPause();  
  144.     }  
  145.       
  146.     @Override  
  147.     protected void onResume() {  
  148.         /** 
  149.          *  MapView的生命周期与Activity同步,当activity恢复时需调用MapView.onResume()
  150.          */  
  151.         mMapView.onResume();  
  152.         super.onResume();  
  153.     }  
  154.       
  155.     @Override  
  156.     protected void onDestroy() {  
  157.         /** 
  158.          *  MapView的生命周期与Activity同步,当activity销毁时需调用MapView.destroy()
  159.          */  
  160.         mMapView.destroy();  
  161.         super.onDestroy();  
  162.     }  
  163.       
  164.     @Override  
  165.     protected void onSaveInstanceState(Bundle outState) {  
  166.         super.onSaveInstanceState(outState);  
  167.         mMapView.onSaveInstanceState(outState);  
  168.           
  169.     }  
  170.       
  171.     @Override  
  172.     protected void onRestoreInstanceState(Bundle savedInstanceState) {  
  173.         super.onRestoreInstanceState(savedInstanceState);  
  174.         mMapView.onRestoreInstanceState(savedInstanceState);  
  175.     }  
  176.   
  177.     @Override  
  178.     public void onGetOfflineMapState(int arg0, int arg1) {  
  179.         // TODO Auto-generated method stub  
  180.           
  181.     }  
  182.       
  183. }  
按照这个方法修改代码后发现地图无论是在Dialog和Activity中都能正常使用,刷新问题不复存在。


由于我们看不到onResume和onPause中的源码,因此对于这个刷新问题,我们只能做猜测,我个人觉得MapView中有些刷新和显示上的控制是在onResume中操作,而在onPause中去暂停操作,个人觉得绘制地图应该是很耗资源的事情,所以确实需要这样的一些操作。但可能有些操作可能是静态全局性的,所以不管一个工程中有多少个MapView,都有些共用的操作,因此才会导致不同地图的刷新问题似乎会相互影响。

经过几天研究,我个人觉得目前的解决方案是每个MapView要有单独维护的onResume和onPause调用,不管这个MapView是在Dialog还是Activity中显示,在你需要使用MapView就调用其onResume方法,在你暂时不需要使用的时候就调用其onPause方法。

本编博文的源码在 源码可以下载到。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值