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

AsyncTask类中使用startActivityForResult与onActivityResult的问题解决

问题分析与解决方案

这个问题我之前也碰到过,核心原因是你把图片选择的结果处理逻辑放到了AsyncTask子类里——onActivityResult是Activity(或Fragment)专属的生命周期方法,AsyncTask作为后台任务类,既没有这个方法的上下文,调用super.onActivityResult也完全没有意义(因为AsyncTask的父类根本没有这个方法)。

下面是两种可行的解决办法,优先推荐第一种,更符合Android的职责分离设计:


方案一:将图片选择逻辑移到宿主Activity中(推荐)

把启动相册、处理选择结果的逻辑全部放到你的Activity里,FTPSubir只专注于FTP上传的后台任务,这样分工更清晰,也避免了生命周期冲突。

步骤1:修改宿主Activity代码

在你的Activity中实现相册启动和结果处理:

public class YourActivity extends AppCompatActivity {
    private static final int SELECT_FILE = 1;
    // 替换成你的FTP服务器地址
    private String ftpServerIp = "xxx.xxx.xxx.xxx";

    // 启动相册的方法,你可以在按钮点击等事件中调用它
    public void abrirGaleria() {
        Intent intent = new Intent();
        intent.setType("image/*");
        intent.setAction(Intent.ACTION_GET_CONTENT);
        startActivityForResult(
            Intent.createChooser(intent, "Seleccione una imagen"), 
            SELECT_FILE
        );
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent) {
        super.onActivityResult(requestCode, resultCode, imageReturnedIntent);
        
        if (requestCode == SELECT_FILE && resultCode == RESULT_OK) {
            Uri selectedImage = imageReturnedIntent.getData();
            String selectedPath = selectedImage.getPath();
            
            if (selectedPath != null) {
                File rutaCompleta = new File(selectedPath);
                // 拿到图片路径后,启动FTP上传任务
                FTPSubir ftpUploadTask = new FTPSubir(ftpServerIp, this, rutaCompleta);
                ftpUploadTask.execute();
            }
        }
    }
}

步骤2:重构FTPSubir类

去掉原来的abrirGaleria和onActivityResult方法,添加接收图片文件的构造方法,让它只负责后台上传:

public class FTPSubir extends AsyncTask<Void, Integer, Long> {
    private static final String USUARIO = "你的FTP用户名";
    private static final String PASS = "你的FTP密码";
    
    private String ip;
    private String usuario;
    private String contrasena;
    private FTPClient ftpClient;
    private BufferedInputStream bufferIn;
    private File rutaCompleta;
    private Context context;

    // 新增构造方法,直接接收选中的图片文件
    public FTPSubir(String ip, Context context, File rutaCompleta) {
        this.ip = ip;
        this.usuario = USUARIO;
        this.contrasena = PASS;
        this.context = context;
        this.rutaCompleta = rutaCompleta;
    }

    // 保留原有的登录逻辑
    public boolean login() throws IOException {
        System.out.println("Conectando . . .");
        try {
            ftpClient = new FTPClient();
            ftpClient.connect(ip);
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("Imposible conectar . . .");
            return false;
        }
        
        ftpClient.enterLocalPassiveMode();
        if (ftpClient.login(usuario, contrasena)) {
            System.out.println("Login correcto . . .");
            return true;
        } else {
            System.out.println("Login incorrecto . . .");
            return false;
        }
    }

    // 保留原有的文件上传逻辑
    public boolean SubirArchivo() throws IOException {
        ftpClient.enterLocalActiveMode();
        ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
        
        if (ftpClient.changeWorkingDirectory("ftp")) {
            System.out.println("Carpeta ftp cambiada . . .");
            bufferIn = new BufferedInputStream(new FileInputStream(rutaCompleta));
            
            if (ftpClient.storeFile(rutaCompleta.getName(), bufferIn)) {
                System.out.println("Archivo subido . . .");
                bufferIn.close();
                return true;
            } else {
                System.out.println("Imposible subir archivo . . .");
                bufferIn.close();
                return false;
            }
        } else {
            System.out.println("Carpeta ftp imposible cambiar . . .");
            return false;
        }
    }

    // 后台执行上传任务
    @Override
    protected Long doInBackground(Void... voids) {
        try {
            if (login()) {
                SubirArchivo();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    // 上传完成后的UI反馈(可选)
    @Override
    protected void onPostExecute(Long aLong) {
        super.onPostExecute(aLong);
        Toast.makeText(context, "上传完成", Toast.LENGTH_SHORT).show();
    }

    // 保留原有的getter/setter方法(如果需要的话)
    public String getUsuario() { return usuario; }
    public void setUsuario(String usuario) { this.usuario = usuario; }
    public String getContrasena() { return contrasena; }
    public void setContrasena(String contrasena) { this.contrasena = contrasena; }
}

方案二:通过接口回调传递结果(不推荐)

如果一定要在FTPSubir中处理结果,可以定义一个回调接口,让Activity实现接口,在onActivityResult中把结果传递给FTPSubir。但这种方式会让代码耦合度变高,不如方案一清晰。

步骤1:定义回调接口

public interface OnImageSelectedListener {
    void onImageSelected(File imageFile);
}

步骤2:修改FTPSubir类

实现接口,并在回调中拿到图片文件:

public class FTPSubir extends AsyncTask<Void, Integer, Long> implements OnImageSelectedListener {
    // ... 保留原有成员变量 ...
    private OnImageSelectedListener listener;

    public FTPSubir(String ip, Context context) {
        this.ip = ip;
        this.context = context;
        this.listener = this;
        // ... 其他初始化代码 ...
    }

    // 实现回调方法
    @Override
    public void onImageSelected(File imageFile) {
        this.rutaCompleta = imageFile;
        // 启动上传任务
        this.execute();
    }

    // ... 保留原有login、SubirArchivo等方法 ...
}

步骤3:修改Activity代码

实现接口,在onActivityResult中调用回调:

public class YourActivity extends AppCompatActivity implements OnImageSelectedListener {
    private FTPSubir ftpSubir;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ftpSubir = new FTPSubir("你的FTP地址", this);
    }

    public void abrirGaleria() {
        // 同方案一的相册启动代码
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent) {
        super.onActivityResult(requestCode, resultCode, imageReturnedIntent);
        if (requestCode == SELECT_FILE && resultCode == RESULT_OK) {
            Uri selectedImage = imageReturnedIntent.getData();
            String selectedPath = selectedImage.getPath();
            if (selectedPath != null) {
                File rutaCompleta = new File(selectedPath);
                // 调用回调传递结果
                ftpSubir.onImageSelected(rutaCompleta);
            }
        }
    }

    @Override
    public void onImageSelected(File imageFile) {
        // 这里可以留空,因为FTPSubir自己实现了这个方法
    }
}

内容的提问来源于stack exchange,提问作者Richard Álvarez

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:39:19