我有一个Android移动应用程序,我试图检查特定的LatLng是否在水,所以我使用谷歌静态地图API获取该位置的图像,然后检查图像是否为蓝色。
我正在使用此代码 -
private boolean result;
public boolean IsWater(LatLng position)
{
imageView = (ImageView) this.findViewById(R.id.imageView);
checkText= (TextView) this.findViewById(R.id.checkText);
String lati = Double.toString(position.latitude);
String longi = Double.toString(position.longitude);
String url = "http://maps.googleapis.com/maps/api/staticmap?center="+lati+"," + longi + "&zoom=20&size=1x1&style=element:labels%7Cvisibility:off&style=element:geometry.stroke%7Cvisibility:off";
Picasso.with(MainActivity.this).load(url)
.into(imageView, new com.squareup.picasso.Callback() {
@Override
public void onSuccess() {
Bitmap bitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
int pixel = bitmap.getPixel(0, 0);
int blueValue = Color.blue(pixel);
if(blueValue>250)
result =true;
}
@Override
public void onError() {
result =false;
}
});
return result;
}
问题,我认为,它是不同步的,并且IsWater到达最后一行并在onSuccess启动之前返回结果为空...
有什么想法吗?
答案 0 :(得分:0)
Picasso默认情况下会在后台线程上加载图像。您正在运行的操作是异步的。因此,它不会阻止您的方法在调用result
回调之前返回onSuccess
。
答案 1 :(得分:0)
问题是Picasso正在运行Async。在调用方法" isWater"中,最终发生的是该方法将返回' false'因为它没有等待毕加索完成,因为它不是连续执行的。这是因为函数调用的堆栈帧一旦到达return语句就会从堆栈中弹出。
您需要做的是使用目标。
// make sure to set Target as strong reference
private Target loadtarget;
public void loadBitmap(String url) {
if (loadtarget == null){
loadtarget = new Target() {
@Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
// do something with the Bitmap
handleLoadedBitmap(bitmap);
}
@Override
public void onBitmapFailed() {
}
};
}
Picasso.with(this).load(url).into(loadtarget);
}
public void handleLoadedBitmap(Bitmap b) {
// do something here
}
此代码取自here,可为您提供有关如何使其符合您目标的一些见解。
Target本质上是一个对象,它保存您需要的位图,因此它仍然在内存中。通常用于自定义视图对象,但作为字段。这是文档Target docs
答案 2 :(得分:0)
异步执行是将头部(以及随后的代码)包装起来最困难的事情之一。在我使用的所有JavaScript框架中,网络通信都是在后台线程中完成的。预期的效果是用户界面线程可以自由地让用户不要认为事情被锁定了。鼠标悬停和工具提示仍然有效,而后台线程将数据拖出慢速服务器。
另一方面,代码模式的形状不是很好。
我的问题是/仍然基本上是线性或功能性思考,而不是接受现代JavaScript的事件驱动特性:将函数传递给异步方法,以完全处理该响应。不只是返回一个值,而是执行需要该值的完整任务。回调可以调用其他函数来协助该任务,并且可以填写缓存(无论何种类型),以便可能需要此数据的其他函数不一定必须等待另一个响应。这通常(对我而言)从我正在遵循的逻辑模式中感到倒退,以解决代码的最初目的。
我偶然发现了这种模式翻转,来自C / C ++作为我的第一种编程语言。它有时可以帮助避免回调定义的匿名函数模式,并使用名称定义一个回调函数,然后将名称传递给异步调用,但从长远来看,这是额外的步骤和额外的内存使用。最大的障碍是考虑Event和EventHandler,而不是函数和数据。
我希望这会有所帮助。