自学HarmonyOS应用开发(61)- 使用异步派发任务后台更新地图数据

面向对象思考

共 3332字,需浏览 7分钟

 · 2021-08-04

当第一次表示某地的地图数据时,由于数据需要从网络下载,因此会造成初次表示时间过长而影响响应速度的问题。我们使用异步派发任务解决这个问题。先看显示效果:

我们甚至可以在地图更新过程中拖动地图。


画面更新时记录需要获得的地图数据

以下是描画地图数据的代码:

private void drawTiles(Canvas canvas){    int tileCol = Tile.getTileX(location.lon, zoom);    int tileRow = Tile.getTileY(location.lat, zoom);    Map<Pair<Integer,Integer>, Tile> missingTile = new HashMap<Pair<Integer,Integer>, Tile>();    Paint paint = new Paint();    for (int col = tileCol - 1; col <= tileCol + 1; col++) {        for (int row = tileRow - 1; row <= tileRow + 1; row++) {            Tile tile = mapData.getData(mapSource, zoom, col, row);            if (tile != null) {                Size offset = tile.calculateOffset(location);                canvas.drawPixelMapHolder(tile,                        getWidth() / 2 + offset.width,                        getHeight() / 2 + offset.height,                        paint);            } else {                missingTile.put(new Pair<Integer, Integer>(row, col), null);            }        }    }    if (missingTile.size() > 0) {        loadMapTile(missingTile);    }}

如果需要的数据不在地图数据缓存中,就将该地图瓦片的坐标存储在missingTile中(代码第16行)。等到本轮描画结束后,调用loadMapTile方法启动后台数据获取过程。


异步获取和更新地图数据

代码第5行启动异步派发任务根据missingTile中存储的坐标获取相应的地图数据。需要注意的是第8行到第18行是在UI以外的上下文中执行的。

public void loadMapTile(Map<Pair<Integer,Integer>, Tile> missingTile){    if(loadMapTileRevocable != null) {        return;    }    loadMapTileRevocable = getContext().getGlobalTaskDispatcher(TaskPriority.HIGH).asyncDispatch(new Runnable() {        @Override        public void run() {            int tileCol = Tile.getTileX(location.lon, zoom);            int tileRow = Tile.getTileY(location.lat, zoom);            boolean need_update = false;            for(Pair<Integer, Integer> pair : missingTile.keySet()){                Tile tile = Tile.createTile(mapSource, pair.s, pair.f, zoom);                if(tile != null) {                    missingTile.put(pair, tile);                    need_update = true;                }            }            getContext().getUITaskDispatcher().asyncDispatch(new Runnable() {                @Override                public void run() {                    for(Pair<Integer, Integer> pair : missingTile.keySet()){                        Tile tile = missingTile.get(pair);                        if(tile != null){                            mapData.setData(mapSource, zoom, pair.s, pair.f, tile);                        }                    }                    TileMap.this.invalidate();                    loadMapTileRevocable = null;                }            });        }    });}

代码18行发起一个UI线程中的异步任务将获得的地图数据保存到地图缓存中。之所以没有直接在获取时直接存储是因为需要避免多任务同时访问地图存储。

地图数据保存完了之后,再发起一次画面更新即可。如果还有没有获取的数据,继续上面的过程。


参考代码

完整代码可以从以下链接下载:

https://github.com/xueweiguo/Harmony/tree/master/StopWatch


作者著作介绍

《实战Python设计模式》是作者去年3月份出版的技术书籍,该书利用Python 的标准GUI 工具包tkinter,通过可执行的示例对23 个设计模式逐个进行说明。这样一方面可以使读者了解真实的软件开发工作中每个设计模式的运用场景和想要解决的问题;另一方面通过对这些问题的解决过程进行说明,让读者明白在编写代码时如何判断使用设计模式的利弊,并合理运用设计模式。

对设计模式感兴趣而且希望随学随用的读者通过本书可以快速跨越从理解到运用的门槛;希望学习Python GUI 编程的读者可以将本书中的示例作为设计和开发的参考;使用Python 语言进行图像分析、数据处理工作的读者可以直接以本书中的示例为基础,迅速构建自己的系统架构。




觉得本文有帮助?请分享给更多人。

关注微信公众号【面向对象思考】轻松学习每一天!

面向对象开发,面向对象思考!



浏览 30
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报