Android,从内部数据库加载缓慢
我的应用程序必须从 android 的内部 sqlite 数据库加载一些“点”,并将这些点转换为地图上的线,然后,从数据库中加载其他“点”,这些点将成为地图上的标记。
问题是上述加载过程非常慢。这个过程可能需要几秒钟,在最坏的情况下也可能需要几分钟。
数据库中的点来自追踪您位置的服务。我在此服务中实现了一些方法来避免点过剩,例如时间控制(如果两个后续点的时间太接近,则不会保存第二个点),位置控制(如果两个后续点具有相同的坐标,最后一个将不会被保存)和距离检查(如果两个后续点距离太近,最后一个将不会被保存)。
在加载过程中,这些点上可能会发生其他计算,但在最好的情况下也会出现缓慢的情况,即仅从数据库中读取数据。
这是我创建数组的地方,其中包含用于在地图上绘制线的点。
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);
}
}
这是我构建地图线的地方
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;
}
My application have to load some "points" from internal sqlite database of android, and it converts this points into lines on a map, then, from the database, I load other "points" which becomes markers on the map.
The problem is that the loading process described above is awfully slow. This process can take many seconds, and also minutes in the worst case.
The points in database come from a service, which trace your position. I have implemented in this service some methods to avoid a surplus of points, like time control (if two subsequent points have been taken too near in time, the second is not saved), position control (if two subsequent points have the same coordinates, the last will not be saved) and distance check (if two subsequent points are too near in distance, the last will not be saved).
Other computations can occour on these points during the loading, but slowness is present also in the best case, where it's only the reading from database.
This is where I create the array which contains points for draw lines on 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();
}
}
Here is where I build the array which contains points for markers, for every marker exist one or more images
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);
}
}
This is where I build the line for the 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();
}
If do you need something else, ask freely.
Thank you to all.
EDIT - Here is the method getGeoPoint
public GeoPoint getGeoPoint() {
GeoPoint geoPoint = new GeoPoint(latitude, longitude);
return geoPoint;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我建议您使用 DDMS 进行一些跟踪,它会显示您花费最多时间的地方并帮助您优化。
我怀疑,在处理 GeoPoint 之后,您没有进行足够的缓存。 “new GeoPoint”构造函数非常昂贵,因此如果您要对该实例化执行数百次操作,我建议您重新考虑如何缓存它。
我想了解
codePoint.getGeoPoint()
背后的逻辑我看到您将原始纬度/经度存储在数据库中。这样进出就会很快。同样,我认为创建 GeoPoint 对象需要花费大量时间。遗憾的是,没有办法使 GeoPoint 可序列化并存储它。因此,一旦将其从数据库中取出,您就必须实例化它。
做一个跟踪,让我们看看结果是什么。 :)
I would recommend you do some tracing with DDMS, it'll show you where you're spending your most time and help you optimize.
I suspect, after dealing with GeoPoint, that you're not doing enough caching. The "new GeoPoint" constructor is extremely expensive so if you're doing a few hundred operations of that instantiation, I recommend re-thinking how you cache that.
I'd like to see the logic behind
codePoint.getGeoPoint()
I see that you're storing the raw lat/lng in the database. That will be fast to go in and out. Again, I assume it's the creation of your GeoPoint object that's taking a lot of time. Sadly, there's no way to make GeoPoint serializable and store that. So you're stuck instantiating it as soon as you pull it out of the database.
Do a trace, let's see what the result of that is. :)