gpt4 book ai didi

java - 缓存谷歌地图 v2 标记位图

转载 作者:搜寻专家 更新时间:2023-11-01 08:52:54 26 4
gpt4 key购买 nike

它会有点长,但如果您能耐心等待我,我将不胜感激,我相信这对其他人也很有用。

我在我的 Android 应用程序中使用谷歌地图来放置不同的标记。每个标记都属于一个由位图表示的类别。我一直在使用来自 Displaying Bitmaps EfficientlyBitmapFun 示例在我的应用程序中缓存位图,我正在尝试使用我的谷歌地图标记实现相同的解决方案。

我的代码已添加到示例的 ImageWorker.java 中,如下所示(BitmapWorkerTask 已经存在并且已更新以处理标记):

private static Map<Marker, BitmapWorkerTask> markerToTaskMap = new HashMap<Marker, BitmapWorkerTask>();

public void loadImage(Object data, Marker marker) {
if (data == null) {
return;
}

BitmapDrawable value = null;

if (mImageCache != null) {
value = mImageCache.getBitmapFromMemCache(String.valueOf(data));
}

if (value != null) {
// Bitmap found in memory cache
marker.setIcon(BitmapDescriptorFactory.fromBitmap(value.getBitmap()));
} else if (cancelPotentialWork(data, marker)) {
final BitmapWorkerTask task = new BitmapWorkerTask(marker);
markerToTaskMap.put(marker, task);

task.executeOnExecutor(AsyncTask.DUAL_THREAD_EXECUTOR, data);
}
}

private class BitmapWorkerTask extends AsyncTask<Object, Void, BitmapDrawable> {
private Object data;
private WeakReference<ImageView> imageViewReference = null;
private WeakReference<Marker> markerReference = null;

public BitmapWorkerTask(ImageView imageView) {
imageViewReference = new WeakReference<ImageView>(imageView);
}

public BitmapWorkerTask(Marker marker) {
markerReference = new WeakReference<Marker>(marker);
}

/**
* Background processing.
*/
@Override
protected BitmapDrawable doInBackground(Object... params) {
if (BuildConfig.DEBUG) {
Log.d(TAG, "doInBackground - starting work");
}

data = params[0];
final String dataString = String.valueOf(data);
Bitmap bitmap = null;
BitmapDrawable drawable = null;

// Wait here if work is paused and the task is not cancelled
synchronized (mPauseWorkLock) {
while (mPauseWork && !isCancelled()) {
try {
mPauseWorkLock.wait();
} catch (InterruptedException e) {}
}
}

// If the image cache is available and this task has not been cancelled by another
// thread and the ImageView that was originally bound to this task is still bound back
// to this task and our "exit early" flag is not set then try and fetch the bitmap from
// the cache
if (mImageCache != null && !isCancelled() && (getAttachedImageView() != null || getAttachedMarker() != null)
&& !mExitTasksEarly) {
bitmap = mImageCache.getBitmapFromDiskCache(dataString);
}

// If the bitmap was not found in the cache and this task has not been cancelled by
// another thread and the ImageView that was originally bound to this task is still
// bound back to this task and our "exit early" flag is not set, then call the main
// process method (as implemented by a subclass)
if (bitmap == null && !isCancelled() && (getAttachedImageView() != null || getAttachedMarker() != null)
&& !mExitTasksEarly) {
bitmap = processBitmap(params[0]);
}

// If the bitmap was processed and the image cache is available, then add the processed
// bitmap to the cache for future use. Note we don't check if the task was cancelled
// here, if it was, and the thread is still running, we may as well add the processed
// bitmap to our cache as it might be used again in the future
if (bitmap != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
// Running on Honeycomb or newer, so wrap in a standard BitmapDrawable
drawable = new BitmapDrawable(mResources, bitmap);
} else {
// Running on Gingerbread or older, so wrap in a RecyclingBitmapDrawable
// which will recycle automagically
drawable = new RecyclingBitmapDrawable(mResources, bitmap);
}

if (mImageCache != null) {
mImageCache.addBitmapToCache(dataString, drawable);
}
}

if (BuildConfig.DEBUG) {
Log.d(TAG, "doInBackground - finished work");
}

return drawable;
}

/**
* Once the image is processed, associates it to the imageView
*/
@Override
protected void onPostExecute(BitmapDrawable value) {
// if cancel was called on this task or the "exit early" flag is set then we're done
if (isCancelled() || mExitTasksEarly) {
value = null;
}

if (imageViewReference != null) {
final ImageView imageView = getAttachedImageView();
if (value != null && imageView != null) {
if (BuildConfig.DEBUG) {
Log.d(TAG, "onPostExecute - setting bitmap");
}
setImageDrawable(imageView, value);
}
} else if (markerReference != null) {
final Marker marker = getAttachedMarker();
if (value != null && marker != null) {
if (BuildConfig.DEBUG) {
Log.d(TAG, "onPostExecute - setting marker bitmap");
}
markerToTaskMap.remove(marker);
marker.setIcon(BitmapDescriptorFactory.fromBitmap(value.getBitmap()));
}
}
}

@Override
protected void onCancelled(BitmapDrawable value) {
super.onCancelled(value);
synchronized (mPauseWorkLock) {
mPauseWorkLock.notifyAll();
}
}

/**
* Returns the ImageView associated with this task as long as the ImageView's task still
* points to this task as well. Returns null otherwise.
*/
private ImageView getAttachedImageView() {
if (imageViewReference == null) {
return null;
}

final ImageView imageView = imageViewReference.get();
final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);

if (this == bitmapWorkerTask) {
return imageView;
}

return null;
}

private Marker getAttachedMarker() {
if (markerReference == null) {
return null;
}

final Marker marker = markerReference.get();
final BitmapWorkerTask bitmapWorkerTask = markerToTaskMap.get(marker); //getBitmapWorkerTask(marker);

if (this == bitmapWorkerTask) {
return marker;
}

return null;
}
}

public static boolean cancelPotentialWork(Object data, Marker marker) {
final BitmapWorkerTask bitmapWorkerTask = markerToTaskMap.get(marker);

if (bitmapWorkerTask != null) {
final Object bitmapData = bitmapWorkerTask.data;
if (bitmapData == null || !bitmapData.equals(data)) {
bitmapWorkerTask.cancel(true);
if (BuildConfig.DEBUG) {
Log.d(TAG, "cancelPotentialWork - cancelled work for " + data);
}
} else {
// The same work is already in progress.
return false;
}
}
return true;
}

如果您熟悉 BitmapFun 示例,您会发现除了使用 AsyncDrawable 将位图连接到其加载 AsyncTask 之外,一切都与将位图与 ImageView 一起使用几乎相同。由于我无法扩展 Marker 类(它是最终的)并且没有 getIcon() 方法,我必须维护一个 HashMap (markerToTaskMap) 来完成这项工作。

这个解决方案似乎在一般情况下工作,除了一些小故障,我得到了一个错误的标记位图。我不知道为什么。 OOB 示例代码不会发生这种情况。

如果有人可以在这里帮助我,我将不胜感激。谢谢。

最佳答案

我可以通过请求不要这样做来帮助您。

如果你想优化,就要更好地了解你的敌人。对 Google Maps Android API v2 的每次调用都会到达其他进程。而且大部分都需要在主线程上完成。

因为对 API 的每次调用都同步到达其他进程,它会阻塞用户界面。例如。在像样的手机上添加 2000 个标记需要 1 秒(已测试)。另一方面加载 20 个小位图来表示 onCreate 中的类别将花费不到 100 毫秒(未经测试的声明)。因此,您的代码甚至会减慢速度,因为您至少有 2 次调用来添加 Marker。 : addMarkersetIcon .

只需加载所有 Bitmap使用BitmapDescriptorFactory.fromResource进入 Map<Category, BitmapDescriptor>一次并在创建时使用它们 Marker

总结一句话:没有问题就不要优化。

关于java - 缓存谷歌地图 v2 标记位图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21504662/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com