1

別のクラスのフェッチ/リフレッシュ場所からスレッドをキャンセルするにはどうすればよいですか。同じクラス内からスレッドをキャンセルできます。しかし、クラス間でこれを行うことはできません。GPSThread static を宣言しても役に立ちませんでした。誰でもご案内いただけますか?

クラス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();
    }
} 
4

2 に答える 2

2

オブジェクトは現在、 内の内部クラスGPSThreadとして宣言されています。のスコープ外から実行を停止したい (または実際に何かを実行したい)場合は、 としてマークする必要があります。また、スレッドの実行をキャンセルするためのパブリック メカニズム (メソッドなど) を提供する必要があります。privateGPSHandlerGPSHandlerpublicstop()

これを行う最も一般的な方法はboolean、スレッド内にフラグを設定することです (例: shouldStop)。このフラグは、メインの実行ループ内でチェックされ、run()停止する必要があるかどうかが確認されます。stop()メソッドが呼び出されると、がshouldStop設定されtrue、スレッドが停止します。

良い例を次に示します。 Java でスレッドを停止するには?

于 2012-08-16T11:10:31.743 に答える
1

行う必要がある変更には 2 つのグループがあります。

停止要求フラグを変更する

まず、オブジェクト指向言語ではカプセル化が優れていることを思い出してください。のisStopRequested()メソッドまたはstopRequested変数は、GPSHandlerそのクラスの外では使用しないでください。UIGPSListenerでこれらのいずれも使用しようとしないでください。これを使用するように変更します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また、これを作成して他のクラスに使用させてはならないもう 1 つの理由は、これは一般にスレッドセーフではないということです。andメソッドでラップする理由の 1 つは、stopRequestedスレッドセーフを追加することです。これを行うには多くの方法がありますが、これらの 2 つの方法は、キーワードでマークすることによってスレッド セーフを実現します。requestStop()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();
   }
}
于 2012-08-24T09:51:51.367 に答える