You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AsyncTask阻塞UI线程求助:同类问题无法解决

搞定AsyncTask里权限请求回调失效的问题

嘿,我猜你遇到的问题应该是在ParkLoader这个AsyncTask里处理权限请求时,权限回调根本没触发吧?毕竟好多人都踩过这个坑——AsyncTask本身不是Activity或者Fragment,就算你让它实现了ActivityCompat.OnRequestPermissionsResultCallback接口,也接不到系统的权限回调通知。我给你两个靠谱的解决办法:


方案1:把权限检查移到MainActivity里(最推荐)

权限回调只能由Activity或Fragment来处理,所以最稳妥的方式是先在MainActivity里搞定权限,拿到权限后再启动ParkLoader:

// 在MainActivity里定义权限相关常量
private static final int REQUEST_PARK_PERMISSION = 101;
// 替换成你需要的权限,比如定位权限
private String[] neededPermissions = {Manifest.permission.ACCESS_FINE_LOCATION};

// 调用ParkLoader前先检查权限
private void initParkLoader() {
    // 检查是否已有权限
    if (ActivityCompat.checkSelfPermission(this, neededPermissions[0]) == PackageManager.PERMISSION_GRANTED) {
        // 权限已拿到,直接启动任务
        new ParkLoader(this, parks -> showList(parks)).execute();
    } else {
        // 没有权限,发起请求
        ActivityCompat.requestPermissions(this, neededPermissions, REQUEST_PARK_PERMISSION);
    }
}

// 重写MainActivity的权限回调方法
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == REQUEST_PARK_PERMISSION) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            // 用户同意了权限,启动ParkLoader
            new ParkLoader(this, parks -> showList(parks)).execute();
        } else {
            // 用户拒绝了权限,给个提示或者处理后续逻辑
            Toast.makeText(this, "需要权限才能加载园区数据哦", Toast.LENGTH_SHORT).show();
        }
    }
}

这样就把权限逻辑放到了能正确接收回调的MainActivity里,从根源上解决了问题。


方案2:让ParkLoader通过Activity处理权限(适合必须在AsyncTask里触发请求的场景)

如果你因为某些原因必须在ParkLoader里触发权限请求,可以通过持有Activity的弱引用,让Activity帮你处理回调,之后再通知ParkLoader继续执行:

首先修改ParkLoader的代码:

public class ParkLoader extends AsyncTask<Void, Void, ArrayList<Park>> {
    // 用WeakReference避免内存泄漏
    private WeakReference<MainActivity> activityRef;
    private OnLoadCompleted loadCallback;
    private boolean permissionGranted = false;
    public static final int REQUEST_PARK_PERMISSION = 101;
    // 替换成你的目标权限
    private String[] neededPermissions = {Manifest.permission.ACCESS_FINE_LOCATION};

    public ParkLoader(MainActivity activity, OnLoadCompleted callback) {
        this.activityRef = new WeakReference<>(activity);
        this.loadCallback = callback;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        MainActivity activity = activityRef.get();
        if (activity == null) return;

        // 检查权限
        if (ActivityCompat.checkSelfPermission(activity, neededPermissions[0]) != PackageManager.PERMISSION_GRANTED) {
            // 通过Activity发起权限请求
            ActivityCompat.requestPermissions(activity, neededPermissions, REQUEST_PARK_PERMISSION);
            // 暂时取消任务,等权限回调后再重启
            cancel(false);
        } else {
            permissionGranted = true;
        }
    }

    @Override
    protected ArrayList<Park> doInBackground(Void... voids) {
        if (!permissionGranted || isCancelled()) {
            return null;
        }
        // 这里写你的数据加载逻辑,返回Park列表
        return loadParkDataFromSource();
    }

    @Override
    protected void onPostExecute(ArrayList<Park> parks) {
        super.onPostExecute(parks);
        if (loadCallback != null && parks != null) {
            loadCallback.onLoadCompleted(parks);
        }
    }

    // 给MainActivity调用的方法,权限通过后重启任务
    public void restartAfterPermissionOk() {
        if (!isCancelled()) {
            permissionGranted = true;
            execute();
        }
    }

    // 你的回调接口
    public interface OnLoadCompleted {
        void onLoadCompleted(ArrayList<Park> parks);
    }

    // 模拟数据加载方法
    private ArrayList<Park> loadParkDataFromSource() {
        // 这里替换成你的实际逻辑
        return new ArrayList<>();
    }
}

然后在MainActivity里处理回调并重启任务:

private ParkLoader parkLoader;

// 初始化并启动ParkLoader
private void startParkLoader() {
    parkLoader = new ParkLoader(this, parks -> showList(parks));
    parkLoader.execute();
}

// 权限回调
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == ParkLoader.REQUEST_PARK_PERMISSION && parkLoader != null) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            // 权限通过,重启ParkLoader
            parkLoader.restartAfterPermissionOk();
        }
    }
}

⚠️ 这里用WeakReference持有Activity非常重要,不然容易造成内存泄漏,一定要记得在使用前检查Activity是否为空。


小提醒

另外,我注意到你的ParkLoader继承的是AsyncTask<Void, Void, Void>,但你实际需要返回ArrayList<Park>给回调,建议把泛型改成AsyncTask<Void, Void, ArrayList<Park>>,这样doInBackground可以直接返回数据,逻辑会更清晰规范哦~

内容的提问来源于stack exchange,提问作者Jan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:49:24