Как заставить doInBackground() ждать другую функцию в классе AyncTask?

#java #android #multithreading #android-asynctask

#java #Android #многопоточность #android-asynctask

Вопрос:

У меня есть пользовательский класс AsyncTask, который проверяет, предоставило ли устройство разрешение на местоположение, а затем получает последнее известное местоположение. Если у него нет разрешения, он сначала запрашивает разрешение у пользователя. Итак, в моей функции doInBackground мне нужно вызвать mGoogleApiClient.connect(), и это вызовет OnConnected функцию. Как видно, doInBackground должен ждать OnConnected , в противном случае он возвращает нулевой объект LastKnownLocation . Мой вопрос в том, как мне заставить doInBackground ждать OnConnected?

 public class GetLocationTask extends AsyncTask<Void, Void, Location> implements GoogleApiClient.ConnectionCallbacks
    , GoogleApiClient.OnConnectionFailedListener {

private Context context;
private Activity activity;
private GoogleApiClient mGoogleApiClient;
private Location lastKnownLocation = null; //In case the users reject location permission request, we might initialize the location to something interesting
public AsyncResponseForLocation delegate = null;
private static final int MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION = 1;

public GetLocationTask(Activity activity, Context context) {
    this.activity = activity;
    this.context = context;
}

@Override
protected Location doInBackground(Void... params) {
    if (mGoogleApiClient == null) {
        mGoogleApiClient = new GoogleApiClient.Builder(context)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();
    }
    mGoogleApiClient.connect();
    return lastKnownLocation;
}

@Override
public void onConnected(@Nullable Bundle bundle) {

    if (ActivityCompat.checkSelfPermission(context,
            android.Manifest.permission.ACCESS_FINE_LOCATION)
            != PackageManager.PERMISSION_GRANTED
            amp;amp; ActivityCompat.checkSelfPermission(context,
            android.Manifest.permission.ACCESS_COARSE_LOCATION)
            != PackageManager.PERMISSION_GRANTED) {

        ActivityCompat.requestPermissions(activity,
                new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION},
                MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
    }
    lastKnownLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
}

@Override
public void onConnectionSuspended(int i) {

}


@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {

}

@Override
protected void onPostExecute(Location location) {
    delegate.processFinish(location);
}


public interface AsyncResponseForLocation {

void processFinish(Location location);}
  

Комментарии:

1. Я не могу использовать while(LastKnownLocation == null) {} для ожидания объекта, поскольку в некоторых случаях этот объект может быть нулевым.

2. Проверьте CompletableFuture и используйте get для «Ожидает, если необходимо, завершения этого future, а затем возвращает его результат».

3. Наконец-то я нашел способ обойти это. Но также спасибо Lior за указание на проблему рабочего процесса. Я создал переменную private boolean onConnectedCompleted = false; и в OnConnected() я добавляю onConnectedCompleted = true; в последний раз. Затем в моем doInBackground мне просто нужно проверить это условие.

Ответ №1:

Реализовать Timertask, который выполняется каждые 5 секунд для проверки условия isConnected() .

Попробуйте приведенный ниже код

    private void startTimer(){
            mTimer1 = new Timer();
            mTt1 = new TimerTask() {
                public void run() {
                    mTimerHandler.post(new Runnable() {
                        public void run(){
                            if(isConnected){

                            //call the Async task
                               }
                        }
                    });
                }
            };

        mTimer1.schedule(mTt1, 1, 5000);
    }
  

Ответ №2:

Добавьте это перед вашим doInBackground() методом. AsyncTask() сначала будет выполняться onPreExecute() , а затем doInBackground() .

     @Override
    protected void onPreExecute() {
        super.onPreExecute();
        // your code hear
    }