multithreading - BlackBerry-取消在另一个类中执行的线程以刷新位置

标签 multithreading blackberry location

如何从另一个类的获取/刷新位置取消线程。我可以从同一个类中取消一个线程。但是我无法跨类(class)做到这一点。声明GPSThread静态无济于事。有人可以指导吗?

第1类:

public class GPSListener {
    /* Other instantiation code */
    Dialog busyDialog1 = new Dialog("Refreshing Location...",
                                    new String [] { "Cancel" },
                                    new int [] { Dialog.CANCEL},
                                    Dialog.CANCEL,
                                    Bitmap.getPredefinedBitmap(Bitmap.HOURGLASS))
    {
        public void fieldChanged(Field field1, int context1)
        {
            GPSHandler.requestStop();
            busyDialog1.cancel();
        }
    };

    public String refreshCoordinates() {
        String test = "nothing";
        if (GPSHandler.isStopRequested())
        {
            GPSHandler.stopRequested = false;
            return null;
        }
        GPSHandler.getInstance().setListener(this);
        GPSHandler.getInstance().requestLocationUpdates();
        if (GPSHandler.isStopRequested())
        {
            GPSHandler.stopRequested = false;
            return null;
        }
        busyDialog1.setEscapeEnabled(false);
        busyDialog1.show();
        return test;
    }

    public void onLocationReceived(Coordinates location) {
        lblLatitude.setText(Double.toString(location.getLatitude()));
        lblLongitude.setText(Double.toString(location.getLongitude()));
        busyDialog1.cancel();
    }
}

第2类:

public class GPSHandler {
    private GPSThread _gpsThread;
    private Coordinates _location;
    private boolean _gotLocation;
    private GPSListener _listener;

    /** this class will be a Singleton, as the device only has one GPS system */
    private static GPSHandler _instance;

    /** @return the Singleton instance of the GPSHandler */
    public static GPSHandler getInstance() {
        if (_instance == null) {
            _instance = new GPSHandler();
        }
        return _instance;
    }

    public static boolean stopRequested = false;
    public synchronized static void requestStop() {
        stopRequested = true;
    }
    public synchronized static boolean isStopRequested() {
        return stopRequested;
    }

    /** not publicly accessible ... use getInstance() */
    private GPSHandler() {
    }

    /** call this to trigger a new location fix */
    public void requestLocationUpdates() {
        if (_gpsThread == null || !_gpsThread.isAlive()) {
            _gpsThread = new GPSThread();
            _gpsThread.start();
        }
    }

    public void setListener(GPSListener listener) {
        // only supports one listener this way
        _listener = listener;
    }

    private void setLocation(final Coordinates value) {
        _location = value;
        if (value.getLatitude() != 0.0 || value.getLongitude() != 0.0) {
            _gotLocation = true;
            if (_listener != null) {
                // this assumes listeners are UI listeners, and want callbacks on the UI thread:
                UiApplication.getUiApplication().invokeLater(new Runnable() {
                    public void run() {
                        _listener.onLocationReceived(value);
                    }
                });
            }
        }
    }

    private class GPSThread extends Thread {
        private void getLocationFromGoogle() {
            try {
                int cellID = GPRSInfo.getCellInfo().getCellId();
                int lac = GPRSInfo.getCellInfo().getLAC();
                String urlString2 = "http://www.google.com/glm/mmap";

                // Open a connection to Google Maps API
                ConnectionFactory connFact = new ConnectionFactory();
                ConnectionDescriptor connDesc;
                connDesc = connFact.getConnection(urlString2);
                HttpConnection httpConn2;
                httpConn2 = (HttpConnection)connDesc.getConnection();
                httpConn2.setRequestMethod("POST");

                // Write some custom data to Google Maps API
                OutputStream outputStream2 = httpConn2.openOutputStream();//getOutputStream();
                writeDataGoogleMaps(outputStream2, cellID, lac);

                // Get the response
                InputStream inputStream2 = httpConn2.openInputStream();//getInputStream();
                DataInputStream dataInputStream2 = new DataInputStream(inputStream2);

                // Interpret the response obtained
                dataInputStream2.readShort();
                dataInputStream2.readByte();
                final int code = dataInputStream2.readInt();

                UiApplication.getUiApplication().invokeLater(new Runnable() {
                    public void run() {
                        Dialog.alert(code + "");
                    }
                });
                if (code == 0) {
                    final double latitude = dataInputStream2.readInt() / 1000000D;
                    final double longitude = dataInputStream2.readInt() / 1000000D;
                    setLocation(new Coordinates(latitude, longitude, 0.0f));

                    UiApplication.getUiApplication().invokeLater(new Runnable() {
                        public void run() {
                            Dialog.alert(latitude+"-----"+longitude);
                        }
                    });

                    dataInputStream2.readInt();
                    dataInputStream2.readInt();
                    dataInputStream2.readUTF();
                } else {
                    System.out.println("Error obtaining Cell Id ");
                }
                outputStream2.close();
                inputStream2.close();
            } catch (Exception e) {
                System.out.println("Error: " + e.getMessage());
            }
        }

        private void tryGetLocationFromDevice() {
            _gotLocation = false;
            try {
                Criteria myCriteria = new Criteria();
                myCriteria.setCostAllowed(false);
                LocationProvider myLocationProvider = LocationProvider.getInstance(myCriteria);
                try {
                    Location myLocation = myLocationProvider.getLocation(300);
                    setLocation(myLocation.getQualifiedCoordinates());
                } catch ( InterruptedException iex ) {
                    System.out.println(iex.getMessage());
                } catch ( LocationException lex ) {
                    System.out.println(lex.getMessage());
                }
            } catch ( LocationException lex ) {
                System.out.println(lex.getMessage());
            }
            if (!_gotLocation) {
                getLocationFromGoogle();
            }
        }

        public void run() {
            int bbMapsHandle = CodeModuleManager.getModuleHandle("net_rim_bb_lbs"); // OS 4.5 - 6.0
            int bbMapsHandle60 = CodeModuleManager.getModuleHandle("net_rim_bb_maps"); // OS 6.0
            if (bbMapsHandle > 0 || bbMapsHandle60 > 0) {
                tryGetLocationFromDevice();
            } else {
                getLocationFromGoogle();
            }
        }
    }

    private void writeDataGoogleMaps(OutputStream out, int cellID, int lac) throws IOException {
        DataOutputStream dataOutputStream = new DataOutputStream(out);
        dataOutputStream.writeShort(21);
        dataOutputStream.writeLong(0);
        dataOutputStream.writeUTF("en");
        dataOutputStream.writeUTF("Android");
        dataOutputStream.writeUTF("1.0");
        dataOutputStream.writeUTF("Web");
        dataOutputStream.writeByte(27);
        dataOutputStream.writeInt(0);
        dataOutputStream.writeInt(0);
        dataOutputStream.writeInt(3);
        dataOutputStream.writeUTF("");
        dataOutputStream.writeInt(cellID);
        dataOutputStream.writeInt(lac);
        dataOutputStream.writeInt(0);
        dataOutputStream.writeInt(0);
        dataOutputStream.writeInt(0);
        dataOutputStream.writeInt(0);
        dataOutputStream.flush();
    }
} 

最佳答案

您应该进行两组更改。

更改停止请求标志

首先,请记住encapsulation is a good thing in Object-Oriented languages。不应在该类之外使用isStopRequested()方法或stopRequestedGPSHandler变量。用户界面的GPSListener不应尝试使用其中任何一个。我将更改您的GPSHandler来使用它:

private static boolean stopRequested = false;

public synchronized static void requestStop() {
   stopRequested = true;
}

private synchronized static boolean isStopRequested() {
   return stopRequested;
}

只有requestStop()应该是public。您似乎已将stopRequested公开,以允许GPSListener对其进行重置。如果需要重置,请让拥有该变量的类进行重置。例如,在GPSHandler中:

   /** call this to trigger a new location fix */
   public void requestLocationUpdates() {
       if (_gpsThread == null || !_gpsThread.isAlive()) {
          // reset this stop flag:
          stopRequested = false;
          _gpsThread = new GPSThread();
          _gpsThread.start(); 
       }
   }
requestLocationUpdates()实际上是启动线程的方法,因此应该将stopRequested重置为false

另外,您不应将stopRequested设为public并允许其他类使用它的另一个原因是,这通常不是线程安全的。用stopRequestedrequestStop()方法包装isStopRequested()的原因之一是增加线程安全性。有很多方法可以做到这一点,但是这两种方法通过用synchronized关键字标记来实现线程安全。

更改检查标志的方式/位置

完成这些修复后,您需要更改,在中检查是否已请求停止。您实际上并不想在isStopRequested()方法中检查refreshCoordinates()。该方法几乎不涉及任何工作。即使在获取位置修复的过程中启动,也仅启动一个线程,但是获取位置的实际工作是在后台线程上完成的(您的GPSThread)。如果调用requestStop(),则非常不太可能在refreshCoordinates()的中间调用它,因此您不应该在此检查它。

isStopRequested()类的方法GPSHandlertryGetLocationFromDevice()中多次检查getLocationFromGoogle()。这些是执行缓慢处理的方法。这些是您可能希望在中间打断的那些。因此,如下所示:

     private void getLocationFromGoogle() {
         try { 
            int cellID = GPRSInfo.getCellInfo().getCellId(); 
            int lac = GPRSInfo.getCellInfo().getLAC(); 

            String urlString2 = "http://www.google.com/glm/mmap"; 

            if (isStopRequested()) return;

            // Open a connection to Google Maps API  
            ConnectionFactory connFact = new ConnectionFactory(); 
            ConnectionDescriptor connDesc; 
            connDesc = connFact.getConnection(urlString2); 

            HttpConnection httpConn2; 
            httpConn2 = (HttpConnection)connDesc.getConnection(); 
            httpConn2.setRequestMethod("POST"); 

            // Write some custom data to Google Maps API  
            OutputStream outputStream2 = httpConn2.openOutputStream();//getOutputStream(); 
            writeDataGoogleMaps(outputStream2, cellID, lac); 

            if (isStopRequested()) return;

            // Get the response   
            InputStream inputStream2 = httpConn2.openInputStream();//getInputStream(); 
            DataInputStream dataInputStream2 = new DataInputStream(inputStream2); 

            // Interpret the response obtained  
            dataInputStream2.readShort(); 
            dataInputStream2.readByte(); 

            if (isStopRequested()) return;

            final int code = dataInputStream2.readInt(); 
            UiApplication.getUiApplication().invokeLater(new Runnable() {
               public void run() {
                  Dialog.alert(code + "");   
               }
            });                        

tryGetLocationFromDevice()中,您可以执行此操作(确保在下面添加成员变量和新方法):

      private LocationProvider _locationProvider;  // must be a member variable!

      public void requestStop() {
         if (_locationProvider != null) {
             // this will interrupt the _locationProvider.getLocation(300) call
             _locationProvider.reset();
         }
      }

      private void tryGetLocationFromDevice() {
         _gotLocation = false;
         try {
            Criteria myCriteria = new Criteria(); 
            myCriteria.setCostAllowed(false); 
            _locationProvider = LocationProvider.getInstance(myCriteria); 

            try { 
               Location myLocation = _locationProvider.getLocation(300); 
               setLocation(myLocation.getQualifiedCoordinates()); 
            } catch ( InterruptedException iex ) { 
               // this may be caught if stop requested!!!!
               System.out.println(iex.getMessage());
            } catch ( LocationException lex ) { 
               System.out.println(lex.getMessage());
            } 
         } catch ( LocationException lex ) { 
            System.out.println(lex.getMessage());
         }

         if (!_gotLocation && !isStopRequested()) { 
            getLocationFromGoogle();
         } 
      }

然后,从外部GPSThread.requestStop()方法调用GPSHandler.requestStop()方法:

public synchronized static void requestStop() {
   stopRequested = true;
   if (_gpsThread != null) {
       _gpsThread.requestStop();
   }
}

关于multithreading - BlackBerry-取消在另一个类中执行的线程以刷新位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11983852/

相关文章:

python - 如何确保共享变量是线程安全的?

cocoa - 核心数据损坏的多线程

python - 在 PyQt5 中停止工作线程中的无限循环最简单的方法

blackberry - 如何在黑莓的 Hashtable 中将 null 作为键值处理?

java - JVM 如何通知被 `join()` 阻塞的线程?

java - j2me :question about Landmark class

user-interface - BlackBerry - 带有标签垂直滚动的主屏幕

c# - 如何防止 WebClient 类自动跟随 header 中的位置?

java - 计算地点与用户位置之间的距离Android Studio

iOS 使用 GPS 设备获取当前位置