【发布时间】:2017-03-09 11:52:42
【问题描述】:
我想收集特定时间段内的位置更新,并在最后对位置进行处理。我目前正在跟踪 onLocationChanged 方法中传递的时间。
public class LocationProvider implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
LocationListener {
private static final String TAG = LocationProvider.class.getSimpleName();
private Context mContext;
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
private long mStartTime;
private long mDuration;
List<Location> locations;
public LocationProvider(Context context) {
mContext = context;
GoogleApiAvailability api = GoogleApiAvailability.getInstance();
if (api.isGooglePlayServicesAvailable(mContext) == ConnectionResult.SUCCESS) {
mGoogleApiClient = new GoogleApiClient.Builder(mContext)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
} else {
Log.e(TAG, "Could not connect to Google Play services");
}
}
@Override
public void onConnected(Bundle bundle) {
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.e(TAG, "onConnectionFailed: " + connectionResult.toString());
}
@Override
public void onConnectionSuspended(int i) {
Log.e(TAG, "GoogleApiClient connection has been suspended: " + String.valueOf(i));
}
@Override
public void onLocationChanged(Location location) {
locations.add(location);
if (System.currentTimeMillis() - mStartTime > mDuration) {
stopTracking();
// do stuff
}
}
public void startTracking(long interval, long fastInterval, long duration) {
mDuration = duration;
locations = new ArrayList<>();
mLocationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(interval)
.setFastestInterval(fastInterval);
if (!mGoogleApiClient.isConnected() || !mGoogleApiClient.isConnecting()) {
mGoogleApiClient.connect();
}
mStartTime = System.currentTimeMillis();
}
private void stopTracking() {
if (mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
mGoogleApiClient.disconnect();
}
}
}
但是,我想打破这个逻辑,因为我想根据我的需要对位置做不同的事情。我推断如果我创建一个新线程来注册我的位置侦听器,我可以在主线程上等待,直到位置收集完成才能使用locations 列表。
public class LocationUpdates {
private LocationProvider mLocationProvider;
private Looper mLooper;
public List<Location> gatherUpdates(final Context context,
final long interval,
final long fastInterval,
final long duration)
throws InterruptedException {
long startTime = System.currentTimeMillis();
new Thread() {
@Override
public void run() {
Looper.prepare();
mLooper = Looper.myLooper();
mLocationProvider = new LocationProvider(context);
mLocationProvider.startTracking(interval, fastInterval, duration);
Looper.loop();
}
}.start();
while (System.currentTimeMillis() - startTime < duration) {
}
mLooper.quit();
mLooper.getThread().join();
return mLocationProvider.locations;
}
}
相反,我观察到的是(间隔 3 秒,持续时间 10 秒):
- 到达
mLocationProvider.startTracking(interval, fastInterval, duration);行 -
gatherUpdates在多长时间后返回 -
onLocationChanged现在才第一次调用
因此,即使位置侦听器已注册,也有明显的东西阻止它接收更新。我不明白为什么我的逻辑没有按照我的预期去做。
有没有办法,即使没有线程,也可以在收集完成后收集一堆位置更新并在onLocationChanged 之外使用它们?
【问题讨论】:
-
如果反对者可以指出这个问题缺少什么,我可能会解决它。我仍然对这个问题的答案很感兴趣。
标签: android multithreading android-gps on-location-changed