【问题标题】:onPostExecute in AsyncTask inside Retrofit is fired too earlyRetrofit 中的 AsyncTask 中的 onPostExecute 过早触发
【发布时间】:2017-10-31 05:16:22
【问题描述】:

我正在尝试将多个图像上传到服务器并通过 Asynctask 将它们一张一张发送。上传图片后,我将 url 保存到本地列表并将其发送到 onPostExecute 进行处理。但是,我遇到了问题,因为 onPostExecute 触发得太早并且 doInBackground 只返回一个空列表。

将 URI 传递给 Asynctask

new UploadImages().execute(arrayUri);

我的异步任务

private class UploadImages extends AsyncTask<Uri,Void,List<String>>{

        @Override
        protected List<String> doInBackground(Uri... params) {
            final ArrayList<String> urlList = new ArrayList<>();

            for(Uri uri : params) {
                File file = new File(uri.getPath());
                RequestBody requestBody = RequestBody.create(MediaType.parse("image/*"), file);
                MultipartBody.Part body = MultipartBody.Part.createFormData("image", file.getName(), requestBody);
                RequestBody folderName = RequestBody.create(MediaType.parse("text/plain"), folder);

                ApiEndpointInterface apiEndpointInterface = RetrofitManager.getApiInterface();

                Call<FileInfo> call4File = apiEndpointInterface.postFile(body, folderName);

                call4File.enqueue(new ApiCallback<FileInfo>() {
                    @Override
                    protected void do4Failure(Throwable t) {
                        Log.d(TAG, t.toString());
                        snackbar = Snackbar.make(newIncidentLayout, R.string.sb_image_upload_error, Snackbar.LENGTH_SHORT);
                        snackbar.show();
                    }

                    @Override
                    protected void do4PositiveResponse(Response<FileInfo> response) {
                        FileInfo fileDetails = response.body();
                        urlList.add(fileDetails.getImage());
                        Log.d(TAG, "Uploaded Image");
                    }

                    @Override
                    protected void do4NegativeResponse(Response<FileInfo> response) {
                        String bodyMsg = "";
                        try {
                            bodyMsg = new String(response.errorBody().bytes());
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        Log.d(TAG, bodyMsg);
                        snackbar = Snackbar.make(newIncidentLayout, R.string.sb_image_upload_error, Snackbar.LENGTH_SHORT);
                        snackbar.show();
                    }
                });
            }
            return urlList;
        }

        @Override
        protected void onPostExecute(List<String> urlList) {
            super.onPostExecute(urlList);

            //Post Incident
            setProgressMessage("Posting incident...");
            //other code here
        }
    }

我尝试添加一个 thread.sleep,但结果却不尽相同。有时我会得到一个列表作为回报,其他时候什么都没有发生。

我不确定为什么会这样。我希望你能帮助我。谢谢。

【问题讨论】:

  • 每当您enqueue() 带有回调对象参数的东西时,这是一个很好的迹象,表明它已经是一个异步操作。也就是说,您不需要AsyncTask

标签: android android-asynctask retrofit


【解决方案1】:

在 android 中,retrofit 调用默认在后台线程中进行。你不应该/不需要使用AsyncTask

您可以在改造回调的方法 onResponse(或者在您的情况下为 do4PositiveResponsedo4NegativeResponse)中编写 onPostExecute 的代码。

【讨论】:

    【解决方案2】:

    有两种类型的调用同步和异步。您正在使用异步的入队,因此您不需要使用异步任务。只需从您的代码中删除异步任务并使用其余代码即可完成这项工作,因此请使用以下代码代替上面的整个代码:

    ArrayList<String> urlList = new ArrayList<>();
    
                for(Uri uri : params) {
                    File file = new File(uri.getPath());
                    RequestBody requestBody = RequestBody.create(MediaType.parse("image/*"), file);
                    MultipartBody.Part body = MultipartBody.Part.createFormData("image", file.getName(), requestBody);
                    RequestBody folderName = RequestBody.create(MediaType.parse("text/plain"), folder);
    
                    ApiEndpointInterface apiEndpointInterface = RetrofitManager.getApiInterface();
    
                    Call<FileInfo> call4File = apiEndpointInterface.postFile(body, folderName);
    
                    call4File.enqueue(new ApiCallback<FileInfo>() {
                        @Override
                        protected void do4Failure(Throwable t) {
                            Log.d(TAG, t.toString());
                            snackbar = Snackbar.make(newIncidentLayout, R.string.sb_image_upload_error, Snackbar.LENGTH_SHORT);
                            snackbar.show();
                        }
    
                        @Override
                        protected void do4PositiveResponse(Response<FileInfo> response) {
                            FileInfo fileDetails = response.body();
                            urlList.add(fileDetails.getImage());
                            Log.d(TAG, "Uploaded Image");
                        }
    
                        @Override
                        protected void do4NegativeResponse(Response<FileInfo> response) {
                            String bodyMsg = "";
                            try {
                                bodyMsg = new String(response.errorBody().bytes());
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                            Log.d(TAG, bodyMsg);
                            snackbar = Snackbar.make(newIncidentLayout, R.string.sb_image_upload_error, Snackbar.LENGTH_SHORT);
                            snackbar.show();
                        }
                    });
                }
    

    在那之后你在 onPostExecute 做的事情在 for 循环完成后做。

    【讨论】:

    • 它会为你工作。另外,如果它有效,请告诉我并将我的帖子标记为您问题的答案。它会给我声誉哥们:)
    猜你喜欢
    • 1970-01-01
    • 2019-06-23
    • 2011-11-13
    • 2020-06-05
    • 2016-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多