【问题标题】:Error in location :getLocation() method cannot be called from event thread位置错误:无法从事件线程调用getLocation()方法
【发布时间】:2012-10-04 10:37:49
【问题描述】:

我想要做的是通过单击带有两个条件的按钮字段打开地图,用户必须指定位置,然后必须将图像添加到该位置,否则必须将图像添加到用户当前位置。

我遇到的问题是将两个条件都添加到线程/新线程甚至 FieldChangeListener 中的 if 语句中。

我不断收到的错误是:

位置错误:javax.microedition.location.LocationException: getLocation() 方法不能从事件线程 [0.0] 调用 [0.0]

位置错误:getLocation() 方法无法从事件中调用 线程

我的代码:

FieldChangeListener Listener = new FieldChangeListener() {
    public void fieldChanged(Field field, int context) {
        ButtonField buttonClicked = (ButtonField) field;
        if ((buttonClicked.getLabel()).equals("Push")) {
            CustomMapField mMapField;
            Coordinates mCoordinates;
            BlackBerryCriteria blackBerryCriteria = null;
            BlackBerryLocation blackBerryLocation = null;
            BlackBerryLocationProvider blackBerryLocationProvider = null;
            double Doublelat = 0.0;
            double Doublelng = 0.0;
            blackBerryCriteria = new BlackBerryCriteria();
            if(GPSInfo.isGPSModeAvailable(GPSInfo.GPS_MODE_CELLSITE)){
                    blackBerryCriteria.setMode(GPSInfo.GPS_MODE_CELLSITE);
            }else if(GPSInfo.isGPSModeAvailable(GPSInfo.GPS_MODE_ASSIST)){
                blackBerryCriteria.setMode(GPSInfo.GPS_MODE_ASSIST);
            }else if(GPSInfo.isGPSModeAvailable(GPSInfo.GPS_MODE_AUTONOMOUS)){
                blackBerryCriteria.setMode(GPSInfo.GPS_MODE_AUTONOMOUS);
            }else{
                blackBerryCriteria.setCostAllowed(true);
                blackBerryCriteria.setPreferredPowerConsumption(Criteria.POWER_USAGE_LOW);
            } try {
                blackBerryLocationProvider = (BlackBerryLocationProvider) BlackBerryLocationProvider.getInstance(blackBerryCriteria);
                blackBerryLocation = (BlackBerryLocation) blackBerryLocationProvider.getLocation(60);
                QualifiedCoordinates qualifiedCoordinates = blackBerryLocation.getQualifiedCoordinates();
        
                Doublelat = qualifiedCoordinates.getLatitude();
                Doublelng = qualifiedCoordinates.getLongitude();
                mCoordinates = new  Coordinates(Doublelat, Doublelng, 0);
                mMapField = new CustomMapField();
                mMapField.mIcon = Bitmap.getBitmapResource("coin_silver.png");
                mMapField.moveTo(mCoordinates);
                mMapField.setZoom(1);
                add(mMapField);
             }catch(Exception e){
                System.out.println("Debug 5");
                System.out.println("Error in location :"+e.toString());
                System.out.println("Error in location :"+e.getMessage());
             }
        }
    }
};

public class CustomMapField extends MapField {
    Bitmap mIcon;
    XYRect mDest;

    public void moveTo(Coordinates coordinates) {
        super.moveTo(coordinates);
        mDest = null;
    }

    protected void paint(Graphics graphics) {
        super.paint(graphics);
        if (null != mIcon) {
            if (null == mDest) {
                XYPoint fieldOut = new XYPoint();
                convertWorldToField(getCoordinates(), fieldOut);
                int imgW = mIcon.getWidth();
                int imgH = mIcon.getHeight();
                mDest = new XYRect(fieldOut.x - imgW / 2, 
                fieldOut.y - imgH, imgW, imgH);
            }
            graphics.drawBitmap(mDest, mIcon, 0, 0);
        }
    }
}

错误在于以下行add(mMapField);

  Doublelat = qualifiedCoordinates.getLatitude();
  Doublelng = qualifiedCoordinates.getLongitude();
  mCoordinates = new  Coordinates(Doublelat, Doublelng, 0);
  mMapField = new CustomMapField();
  mMapField.mIcon=Bitmap.getBitmapResource("coin_silver.png");
  mMapField.moveTo(mCoordinates);
  mMapField.setZoom(1);
  add(mMapField);

  /*MapView mapView = new MapView();
    mapView.setLatitude(finalintlat);
    mapView.setLongitude(finalintlng);
    mapView.setZoom(10);
    MapsArguments mapsArgs = new MapsArguments(mapView);
    Invoke.invokeApplication(Invoke.APP_TYPE_MAPS, mapsArgs);

请更详细地告诉我如何做到这一点,并举个例子;我不明白为什么“mMapField”是一个自定义 MapField,而“mapView”是一个类 Mapview(请参阅我上面的代码 sn-p)。

【问题讨论】:

  • 请告诉我,您的应用程序在获取位置时是否没有响应......?

标签: blackberry error-handling gps location


【解决方案1】:

获取位置是一项耗时的任务,即使卫星能见度良好,也可能需要 1 分钟,尽管较新的浆果大大缩短了首次定位时间 (TTFF)。

不应在事件线程中执行耗时的任务,例如打开连接或获取修复,因为该线程必须响应用户事件,如果您占用它,那么 GUI 就会冻结。在fieldChanged 中运行的所有内容都在事件线程中运行。因此,RIM 在其新的 BlackBerryLocationProvider 中实现了线程检测并抛出异常是一件好事,现在您已经意识到了糟糕的设计并可以采取纠正措施。

您有多种选择来异步修复:

  1. 使用LocationListener
  2. 产生一个新线程。
  3. 在您需要修复之前(或定期)提前获取修复,然后在按下按钮时快速获取修复(从您之前保存的位置检索它或调用LocationProvider.getLastKnownLocation)。

【讨论】:

    【解决方案2】:

    您应该使用Invoke.invokeApplication(Invoke.APP_TYPE_MAPS, new MapsArguments(mMapField)); 代替add(mMapField);

    【讨论】:

    • @Anzy_ 代码获取经度和纬度,只是我放置所有内容的方式存在问题。如果我把所有东西都拿出来,只使用代码来获取“我的位置”(使用主屏幕中的代码),那么它就可以完美地工作。
    • @Coral Doe,请查看我在帖子中所做的更改,而不是您
    • 解决此问题的正确方法是在我的代码中添加以下内容:'synchronized(UiApplication.getEventLock()) { mainVFM.add(mMapField); }'
    • 抱歉回复晚了..首先恭喜@Nequta,你喜欢的解决方案,但我在代码中没有看到的一件主要事情你没有在新线程上计算纬度/经度......除了 UI 线程(主线程)之外,应用程序确实有必要在另一个线程上保留 lat/long calc ...根据您的说法,此代码在模拟器中工作正常,在设备上尝试此操作可能会得到一些奇怪的结果..因为在模拟器中你已经给出了 lat/long 这就是为什么模拟器没有时间响应 ..但是在设备中你会体验到你的应用程序挂起 ..而 lat/long calc ..
    • 我不使用模拟器测试,只使用设备。这是一个线程的家伙。感谢所有回复:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-09-03
    • 2016-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-13
    • 1970-01-01
    相关资源
    最近更新 更多