简体   繁体   中英

Is Thread.sleep() not letting other threads run?

I'm making an Android app, and I made a class to separate and manage more easily the code related to getting the user's location. Since the FusedLocationProviderClient takes some time to give a response and execute the code inside the onSuccess or onFailure listeners, I made a method ( waitForLocation() ) that basically waits until one of the listeners is executed or the time limit is exceeded.

The waitForLocation() method is a blocking method that waits until gotResponse becomes true to let the rest of the thread continue ( gotResponse will also become true if the time limit is exceeded).

The problem is that, for stopping the code from flowing until gotResponse is true , I'm using the Thread.sleep() method, but all of the background tasks, such as the CountDownTimer and the listeners seem to also freeze along with the main thread (the CountDownTimer is not ticking and the listeners never execute).

Please help! Thanks in advance :D

This is my class:

package com.sserrano.stormy;

import android.app.Activity;
import android.location.Location;
import android.os.CountDownTimer;
import android.support.annotation.NonNull;
import android.util.Log;

import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;


public class UserLocationManager {

    public static final String TAG = UserLocationManager.class.getSimpleName();

    private FusedLocationProviderClient locationClient;
    private Activity instActivity;
    private double[] coords = {37.8267, -122.4233}, defaultCoords = {37.8267, -122.4233};
    private volatile boolean gotResponse = false;

    UserLocationManager(Activity instActivity){
        this.instActivity = instActivity;
        locationClient = LocationServices.getFusedLocationProviderClient(instActivity);
    }

    public double[] getLastCoords() {
        try {
            locationClient.getLastLocation().
                    addOnSuccessListener(instActivity, new OnSuccessListener<Location>() {
                        @Override
                        public void onSuccess(Location location) {
                            if(location != null) {
                                coords = new double[]
                                        {location.getLatitude(), location.getLongitude()};
                            }
                            gotResponse = true;
                        }
                    }).addOnFailureListener(instActivity, new OnFailureListener() {
                        @Override
                        public void onFailure(@NonNull Exception e) {
                            gotResponse = true;
                        }
                    });
        } catch (SecurityException e){
            return defaultCoords;
        }

        waitForLocation();
        return coords;
    }


    public double[] getDefaultCoords(){
        return defaultCoords;
    }

    private void waitForLocation(){
        new CountDownTimer(5000, 5000){
            @Override
            public void onFinish() {
                gotResponse = true;
                Log.w(TAG, "Timed out waiting the result of the location request.");
            }

            @Override
            public void onTick(long millisUntilFinished) {

            }
        };
        try{
            while(!gotResponse) {
                Thread.sleep(Constants.getSleepIntervalDuration());
            }
        } catch (InterruptedException e) {
            Log.w(TAG, "Interrupted while waiting the result of the location request." +
                    " The app will likely act like if the location was not received, " +
                    "even if it was.");
        }
        gotResponse = false;
    }
}
  1. This would sleep the UI thread. This is an absolute no-go. I fear you got the usage of CountDownTimer and asynchronous operation very wrong. Please look at more examples.
  2. Also you forgot to call .start() on the CountDownTimer onFinish would never happen.
  3. Assign the timer to a member variable, then it will live until onFinish is called and you can set your gotResponse.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM