【问题标题】:How to make doInBackground() wait for another function in AyncTask class?如何让 doInBackground() 等待 AsyncTask 类中的另一个函数?
【发布时间】:2025-12-18 06:20:04
【问题描述】:

我有一个自定义 AsyncTask 类,它检查设备是否已授予位置权限,然后它获取最后一个已知位置。如果没有权限,则先向用户请求权限。所以在我的 doInBackground 函数中,我需要调用 mGoogleApiClient.connect() 这将触发 onConnected 函数。可以看出,doInBackground需要等待onConnected,否则返回null对象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
            && 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);}

【问题讨论】:

  • 我不能使用 while(lastKnownLocation == null) {} 来等待对象,因为在某些情况下该对象可能为空。
  • 检查CompletableFuture 并使用get 来“在必要时等待此未来完成,然后返回其结果。”
  • 我终于找到了解决办法。但也感谢 Lior 指出工作流程问题。我创建了一个变量 private boolean onConnectedCompleted = false;在 onConnected() 中,我添加 onConnectedCompleted = true;在最后一次。然后在我的 doInBackground 中我只需要检查这个条件。

标签: java android multithreading android-asynctask


【解决方案1】:

您的流程不正确,在您尝试获取位置之前检查您是否有权限...

// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(thisActivity,
            Manifest.permission.ACCESS_FINE_LOCATION)
    != PackageManager.PERMISSION_GRANTED) {

// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
        Manifest.permission.ACCESS_FINE_LOCATION)) {

    // Show an expanation to the user *asynchronously* -- don't block
    // this thread waiting for the user's response! After the user
    // sees the explanation, try again to request the permission.

} else {

    // No explanation needed, we can request the permission.

    ActivityCompat.requestPermissions(thisActivity,
            new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
            MY_PERMISSIONS_REQUEST_LOCATION);

    // MY_PERMISSIONS_REQUEST_LOCATION is an
    // app-defined int constant. The callback method gets the
    // result of the request.
} else{
 // Run your async task here(you have got location permission already)
 new GetLocationTask(Activity).execute();
}

当用户需要批准您的权限请求时,您必须处理 onRequestPermissionsResult 方法:

@Override
public void onRequestPermissionsResult(int requestCode,
    String permissions[], int[] grantResults) {
switch (requestCode) {
    case MY_PERMISSIONS_REQUEST_LOCATION: {
        // If request is cancelled, the result arrays are empty.
        if (grantResults.length > 0
            && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

            // permission was granted, Execute the asynctask here
            new GetLocationTask(Activity).execute();
        } else {

            // permission denied, boo! Disable the
            // functionality that depends on this permission.
        }
        return;
    }

    // other 'case' lines to check for other
    // permissions this app might request
}
}

【讨论】:

    【解决方案2】:

    实现一个 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);
        }
    

    【讨论】:

      【解决方案3】:

      在您的 doInBackground() 方法之前添加它。 AsyncTask() 将首先执行onPreExecute() 然后doInBackground()

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

      【讨论】:

        最近更新 更多