Android/Java:让继承AppCompatActivity的Activity继承自定义类
解决方案:用组合替代继承实现职责分离
Java不支持多继承,所以你的HereMap(继承AppCompatActivity)无法再继承HereMapClass。正确的做法是组合模式:将HereMapClass作为HereMap的成员变量,让HereMapClass专注于地图下载、地图包管理等业务逻辑,HereMap只负责UI可视化。
步骤1:重构HereMapClass,剥离UI依赖并定义回调
首先清理HereMapClass中的UI相关成员,只保留核心逻辑,并通过回调接口将状态通知给UI层:
public class HereMapClass { private final static String TAG = HereMapClass.class.getSimpleName(); private MapLoader mapLoader; private ArrayList<MapPackage> currentInstalledMaps; private Context context; private MapLoaderCallback callback; // 定义回调接口,用于通知UI层状态变化 public interface MapLoaderCallback { void onDownloadProgress(int progress); void onError(String errorMsg); void onMapPackagesLoaded(ArrayList<MapPackage> installedPackages); } public HereMapClass(Context context, MapLoaderCallback callback) { this.context = context; this.callback = callback; initMapLoader(); } private void initMapLoader() { mapLoader = MapLoader.getInstance(); // 初始化地图加载器的其他逻辑... } // 公开方法:获取已安装地图包 public void fetchInstalledMapPackages() { mapLoader.getMapPackages(mapLoaderHandler); } // MapLoader监听器,内部处理逻辑,通过回调通知UI private MapLoader.Listener mapLoaderHandler = new MapLoader.Listener() { @Override public void onProgress(int progress) { Log.i(TAG, "Progress " + progress + "%"); if (callback != null) { callback.onDownloadProgress(progress); } } @Override public void onInstallationSize(long diskSize, long networkSize) { Log.i(TAG, "Map data require " + diskSize); } @Override public void onGetMapPackagesComplete(MapPackage rootMapPackage, MapLoader.ResultCode resultCode) { if (resultCode == MapLoader.ResultCode.OPERATION_SUCCESSFUL) { Log.i(TAG, "Map packages received successful: " + rootMapPackage.getTitle()); currentInstalledMaps = new ArrayList<>(1); populateInstalledMaps(rootMapPackage); if (callback != null) { callback.onMapPackagesLoaded(currentInstalledMaps); } } else { String errorMsg = "Can't retrieve map packages: " + resultCode.name(); Log.e(TAG, errorMsg); if (callback != null) { callback.onError(errorMsg); } } } private void populateInstalledMaps(MapPackage pac) { if (pac.getInstallationState() == MapPackage.InstallationState.INSTALLED) { Log.i(TAG, "Installed package found: " + pac.getTitle() + " id " + pac.getId()); currentInstalledMaps.add(pac); } else if (pac.getChildren() != null && pac.getChildren().size() > 0) { for (MapPackage p : pac.getChildren()) { populateInstalledMaps(p); } } } }; // 其他地图下载相关的公开方法,比如启动下载、取消下载等 public void startMapDownload(MapPackage packageToDownload) { // 实现地图下载逻辑... } }
步骤2:修改HereMap Activity,组合HereMapClass并处理UI
让HereMap实现HereMapClass.MapLoaderCallback接口,实例化HereMapClass,专注于地图可视化:
import androidx.appcompat.app.AppCompatActivity; public class HereMap extends AppCompatActivity implements HereMapClass.MapLoaderCallback { private final static String TAG = HereMap.class.getSimpleName(); // UI相关成员,只保留可视化需要的 private MapView mapView; private AndroidXMapFragment mapFragment; private Map map; private ProgressBar downloadProgressBar; // 组合HereMapClass,处理业务逻辑 private HereMapClass hereMapClass; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_here_map); // 初始化UI控件 downloadProgressBar = findViewById(R.id.download_progress); initMapView(); // 实例化HereMapClass,传入Context和回调 hereMapClass = new HereMapClass(this, this); // 调用业务方法,获取已安装地图包 hereMapClass.fetchInstalledMapPackages(); } // 初始化地图可视化相关逻辑 private void initMapView() { mapView = findViewById(R.id.map_view); mapView.onCreate(savedInstanceState); mapView.getMapAsync(map -> { this.map = map; // 地图初始化完成后的可视化操作,比如添加标记、设置地图样式等 }); } // 实现回调接口,处理UI更新 @Override public void onDownloadProgress(int progress) { runOnUiThread(() -> downloadProgressBar.setProgress(progress)); } @Override public void onError(String errorMsg) { runOnUiThread(() -> Toast.makeText(HereMap.this, errorMsg, Toast.LENGTH_SHORT).show()); } @Override public void onMapPackagesLoaded(ArrayList<MapPackage> installedPackages) { runOnUiThread(() -> { // 处理已安装地图包的UI展示,比如显示列表 StringBuilder sb = new StringBuilder(); for (MapPackage pac : installedPackages) { sb.append(pac.getTitle()).append("\n"); } // 比如显示在TextView中 // TextView installedMapsTv = findViewById(R.id.installed_maps_tv); // installedMapsTv.setText(sb.toString()); }); } // 其他UI相关方法,比如处理地图点击、添加标记等 private void addMapMarker(GeoCoordinate coordinate) { // 实现标记添加逻辑... } @Override protected void onResume() { super.onResume(); mapView.onResume(); } @Override protected void onPause() { mapView.onPause(); super.onPause(); } @Override protected void onDestroy() { mapView.onDestroy(); super.onDestroy(); } }
关键说明
- 职责分离:
HereMapClass只处理地图下载、地图包管理等无UI的业务逻辑,可在多个组件(比如Service、其他Activity)中复用;HereMap专注于地图的可视化展示和用户交互。 - 回调机制:通过回调接口让
HereMapClass将状态变化通知给UI层,避免直接依赖UI控件,保证类的独立性。 - 生命周期管理:Activity中的地图控件(
MapView)需要正确处理生命周期方法,避免内存泄漏或功能异常。
内容的提问来源于stack exchange,提问作者ΩlostA
相关产品推荐
相关产品推荐

