Android,从内部数据库加载缓慢

标签 android performance maps

我的应用程序必须从 android 的内部 sqlite 数据库加载一些“点”,并将这些点转换为 map 上的线,然后,从数据库中,我加载其他“点”成为 map 上的标记。

问题是上面描述的加载过程非常慢。这个过程可能需要很多秒,在最坏的情况下也可能需要几分钟。

数据库中的点来自跟踪您的位置的服务。我在此服务中实现了一些方法来避免点过多,例如时间控制(如果两个后续点的时间太近,第二个不保存),位置控制(如果两个后续点具有相同的坐标,最后一个将不会被保存)和距离检查(如果两个后续点的距离太近,最后一个将不会被保存)。

在加载过程中,其他计算可能会在这些点上发生,但在最好的情况下也会出现缓慢,这只是从数据库中读取数据。

这是我创建数组的地方,其中包含用于在 map 上绘制线的点。

public BuildPointsList(Context context, long travelId) {
    this.context=context;
    this.travelId = travelId;
    initializePointList();
}
   private void initializePointList() {
    pointsList = new ArrayList<Points>();
}

public List<Points> fromDB() {
    TravelDB traveldb = new TravelDB(context);
    traveldb.open();
    Cursor cursor = traveldb.fetchAllGpsPoints(travelId);

    loadPoints(cursor);
    cursor.close();
    traveldb.close();
    return pointsList;
}

protected void loadPoints(Cursor cursor) {

    initializePointList();
    cursor.moveToFirst();
    int gpsIndex = cursor.getColumnIndex(colGpsId);
    int latitudeIndex = cursor.getColumnIndex(colGpsLatitude);
    int longitudeIndex = cursor.getColumnIndex(colGpsLongitude);
    int dateIndex = cursor.getColumnIndex(colGpsDate);

    for (int progress=0; progress<cursor.getCount(); progress++) {
        Points points = new Points();
        points.setLatitude(cursor.getInt(latitudeIndex));
        points.setLongitude(cursor.getInt(longitudeIndex));
        points.setDataRilevamento(cursor.getLong(dateIndex));
        points.setGpsId(cursor.getInt(gpsIndex));

        pointsList.add(points);

        cursor.moveToNext();
    } 
}

这里是我构建包含标记点的数组的地方,因为每个标记都存在一个或多个图像

private void buildPoints () {

    List<Images> images = travel.getImages();
    Log.i("DDV", "images:"+images.size());
    // se esistono punti
    if (!images.isEmpty()) {

        length = images.size();

        for (progress = 0 ; progress < length; progress++) {

            currentImage = images.get(progress);

            // verifico se una località con coordinate simili era già stata presa in esame
            // in quel caso la raggruppo insieme alle altre
            if ((oldImage != null) && (near(oldImage.getGeopoint(), currentImage.getGeopoint()))) {

                overlayitem.addImage(currentImage);
                if (currentImage.getAddress().length() == 0) {
                    if (oldImage.getAddress().length() > 0) {
                        currentImage.setAddress(oldImage.getAddress());
                        travel.addImages(currentImage);
                    }
                }
            }

            // in questo caso vuol dire che le coordinate sono troppo differenti per unirle in una
            // quindi salvo l'oggetto vecchio e ne instanzio uno nuovo
            else if (oldImage != null) {
                    setTextAndSave(oldImage);
                    createOverlay(currentImage.getGeopoint());
                    oldImage = currentImage;
                }

            // in questo caso è la prima volta che instanzio una coordinata
            else {

                oldImage = currentImage;

                // geocoding per determinare il nome della via dove è stato generato il contenuto
                // se nel db non è presente

                if (currentImage.getAddress().length() == 0) 
                    currentImage = geoCode(currentImage);                       

                // aggiungo il marker
                createOverlay(currentImage.getGeopoint());
            }                   

            // faccio progredire la sbarra
            onProgressUpdate((int)(progress*100/length));
        }
        setTextAndSave(oldImage);
    }
}   

这是我为 map 建立线的地方

private void buildRoute() {

    points = travel.getPoints();    

    length = points.size();
    long tmp = DateManipulation.getCurrentTimeMs();
    Log.i("DDV", "START PARSIN POINTSL: " +tmp);

    if (length > 1) {

        Points currentPoint = points.get(0);
        Points oldPoint=currentPoint;

        for (int progress=0; progress<length; progress++) {

            currentPoint = points.get(progress);

            if (currentPoint.getGeoPoint() != oldPoint.getGeoPoint()) {
                oldPoint = currentPoint;
                polyLine.add(currentPoint.getGeoPoint());
                setZoomAndCenter(currentPoint);

            }
            onProgressUpdate((int)(progress*100/length));
        }
    }
    saveCenterPosition();
}

如果您还需要其他东西,请随意询问。

谢谢大家

编辑 - 这是方法 getGeoPoint

public GeoPoint getGeoPoint() {
    GeoPoint geoPoint = new GeoPoint(latitude, longitude);
    return geoPoint;
}

最佳答案

我建议您使用 DDMS 进行一些跟踪,它会显示您花费最多时间的地方并帮助您进行优化。

我怀疑,在处理了 GeoPoint 之后,您没有做足够的缓存。 “新 GeoPoint”构造函数非常昂贵,因此如果您对该实例化执行数百次操作,我建议您重新考虑如何缓存它。

我想看看 codePoint.getGeoPoint() 背后的逻辑

我看到您将原始纬度/经度存储在数据库中。这样进出就快了。同样,我认为是 GeoPoint 对象的创建花费了大量时间。遗憾的是,没有办法使 GeoPoint 可序列化并存储它。因此,一旦将其从数据库中拉出,您就无法实例化它。

做一个跟踪,让我们看看结果是什么。 :)

关于Android,从内部数据库加载缓慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9019905/

相关文章:

android - Kotlin fragment 中的API数据

Python 搜索文件中的一百万个字符串并统计每个字符串的出现次数

SQL子查询-有更好的方法吗

linux -/proc/$PID/maps 中的 "/dev/zero (deleted)"、 "anon_inode:dmabuf"来自哪里?

javascript - 使用两个值作为一个值的键

javascript - 更改 map 上的坐标

Android 2.2 appwidget进度条滚轮导致widget失败

android - Paypal 而不是 Android 和 iOS 上的应用内购买/计费

c - 对于较大的 switch case 语句,将它们分开更好吗?

android - Google Play 控制台 Alpha 测试可以为两个不同的组提供两个不同的 apk 吗?