【问题标题】:Android: get result from callback (networking KOUSH ION)Android:从回调中获取结果(网络 KOUSH ION)
【发布时间】:2015-12-14 11:04:22
【问题描述】:

对于我的应用,我需要从返回一些 JSON 的服务器联系我们的 API。

在下载 JSON 时,它应该显示一个进度条。

我认为我应该在进行网络操作时使用 Android 的 AsyncTask 来处理 GUI,所以我在 Activity 中写了以下内容:

 class DownloadManager extends AsyncTask<String, Void, Boolean> {

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        mLoadingSpinner.setVisibility(View.VISIBLE);
    }

    @Override
    protected Boolean doInBackground(String... params) {
        String id = params[0];
        downloadUtility.getId(id);

        return true;
    }

    @Override
    protected void onPostExecute(Boolean result) {
        super.onPostExecute(result);

        mLoadingSpinner.setVisibility(View.INVISIBLE);

    }

}

基本上,onPreExecute 显示加载微调器,doInBackGround 下载一些 JSON,onPostExecute 停止微调器。

问题是,在downloadUtility.getId(id) 中我需要:

  1. 如果下载成功,则打开一个新意图。
  2. 如果下载失败,请继续执行相同的活动并显示错误 Toast。

getId的代码:

public Future getId(final String id) {
    // set url
    String url = IPAddress.PRODUCTION + Variables.get_id+ id;
    downloading = Ion.with(context)
            .load("GET", url)
            .asJsonObject()
            .withResponse()
            .setCallback(new FutureCallback<Response<JsonObject>>() {
                @Override
                public void onCompleted(Exception e, Response<JsonObject> response) {
                    //try catch here for null getHeaders
                    if (response != null) {
                        if (response.getHeaders().code() == 200) {

                            //SUCCESS !! Open new intent!


                        } else {
                            //FAIL!! Show TOAST!
                        }
                    }

                }
            });


    return downloading;

}

如您所见,我正在返回一个未来对象。我如何从 future 对象中知道 onCompleted (void) 是成功还是失败,以便我可以在 asynctask 中处理结果(成功:打开新意图,失败:toast)?

【问题讨论】:

    标签: android android-asynctask callback future


    【解决方案1】:

    在这里,您正在另一个异步任务中运行一个异步任务,这不是您可以直接在活动中调用 getId 方法的正确方法,它不需要另一个异步任务,因为以下代码本身就是一个异步任务。

     downloading = Ion.with(context)
            .load("GET", url)
            .asJsonObject()
            .withResponse()
            .setCallback(new FutureCallback<Response<JsonObject>>() {
                @Override
                public void onCompleted(Exception e, Response<JsonObject> response) {
                    //try catch here for null getHeaders
                    if (response != null) {
                        if (response.getHeaders().code() == 200) {
    
                            //SUCCESS !! Open new intent!
    
    
                        } else {
                            //FAIL!! Show TOAST!
                        }
                    }
    
                }
            });
    

    //添加新答案

    如果您想将整个下载代码与您的活动分开,那么您可以在下载实用程序类中创建自定义回调。它将充当活动和您的下载类之间的沟通者。我只是在下面给出一种方法来完成这项任务。

    DownloadUtility 类接缝如下所示

    public class DownloadUtility {
    
    
    //DO Your all other Stuff
    
    /**
     * Custom Callback
     */
    public interface customCallBack {
        void onCompleted(Exception e, Response<JsonObject> response);
    }
    
    
    /**
     * Your getID code 
     * 
     * @param context
     * @param id
     * @param mLoadingSpinner
     * @param callBack
     */
    public static void getId(Activity context,final String id, Spinner mLoadingSpinner, final customCallBack callBack) {
        // set url
        mLoadingSpinner.setVisibility(View.VISIBLE);
        String url = IPAddress.PRODUCTION + Variables.get_id + id;
        downloading = Ion.with(context)
                .load("GET", url)
                .asJsonObject()
                .withResponse()
                .setCallback(new FutureCallback<Response<JsonObject>>() {
                    @Override
                    public void onCompleted(Exception e, Response<JsonObject> response) {
                        mLoadingSpinner.setVisibility(View.GONE);
                       if(callBack != null)
                        callBack.onCompleted(e,response);
                        }
                    }
                });
    }
    

    }

    调用您的活动

    DownloadUtility.getId(this, "ID", spinnerObj, new DownloadUtility.customCallBack() {
    @Override
    public void onCompleted(Exception e, Response<JsonObject> response) {
        if (response != null) {
            if (response.getHeaders().code() == 200) {
                //SUCCESS !! Open new intent!
            } else {
                //FAIL!! Show TOAST!
            }
    }
    

    });

    【讨论】:

    • 这不是意味着你要在 Activity 类中编写下载代码吗?我创建一个 DownloadUtility 类的原因是摆脱将下载代码放在活动中的整个事实,并将其放在它所属的类中。
    • 我根据您的要求对答案进行了一些更改,希望对您有所帮助。
    • 在上面的代码中你不想传递mLoadingSpinnerObject,你可以在activity本身中启动它,你可以在调用那个函数之前启动它,onComplete你可以停止。
    【解决方案2】:

    我认为您不需要 AsyncTask 进行网络操作,因为您的 ion 库已经在内部使用 asynctask。 你可以这样做

    mLoadingSpinner.setVisibility(View.VISIBLE);
    downloading = Ion.with(context)
                .load("GET", url)
                .asJsonObject()
                .withResponse()
                .setCallback(new FutureCallback<Response<JsonObject>>() {
                    @Override
                    public void onCompleted(Exception e, Response<JsonObject> response) {
                        //try catch here for null getHeaders
                        if (response != null) {
                            if (response.getHeaders().code() == 200) {
    
                                //SUCCESS !! Open new intent!
                                mLoadingSpinner.setVisibility(View.INVISIBLE);
                            } else {
                                mLoadingSpinner.setVisibility(View.INVISIBLE);
                            }
                        }
    
                    }
                });
        return downloading;
    

    如果有问题请告诉我。

    【讨论】:

    • 这不是意味着你要在 Activity 类中编写下载代码吗?我创建一个 DownloadUtility 类的原因是摆脱将下载代码放在活动中的整个事实,并将其放在它所属的类中。
    • 是的,创建一个单独的类并在函数中添加此代码,以便您可以将其分开
    • 如果我要创建一个单独的类,我将无法调用 mLoadingSpinner,因为该类不是一个活动。我可以将 loadingspinner 传递给 downloadUtility 对象的构造函数,但这不是最好的方法。 (我曾经试过这个)。此外,为了从非活动中打开新意图,我必须使用 FLAG 从普通类中打开新活动。这不是很好的代码
    • 活动的内部类
    【解决方案3】:

    在我看来,最简洁的解决方案是创建一个服务来处理脏下载逻辑并返回自定义响应类的未来,其中包含成功信息和 json 对象。

    // in e.g JsonResponse.java
    public class JsonResponse() {
        public boolean ok;
        public JsonObject json;
    }
    
    // in Service.java
    public Future<JsonResponse> getId(final String id) {
        final SimpleFuture<JsonResponse> jsonFuture = new SimpleFuture<>();
    
        String url = IPAddress.PRODUCTION + Variables.get_id + id;
        Ion.with(context)
        .load("GET", url)
        .asJsonObject()
        .withResponse()
        .setCallback(new FutureCallback<Response<JsonObject>>() {
            @Override
            public void onCompleted(Exception e, Response<JsonObject> response) {
                JsonResponse jsonResponse = new JsonResponse();
                if (response != null) {
                    if (response.getHeaders().code() != 200) {
                        jsonResponse.ok = false;
                    } else {
                        jsonResponse.ok = true;
                        jsonResponse.json = response.getResult();   
                    }
                }
                jsonFuture.setComplete(jsonResponse);
            }
        });
    
        return jsonFuture;
    }
    
    
    // in Activity.java
    private void loadUser(String userId) {    
        mLoadingSpinner.setVisibility(View.VISIBLE);
    
        service.getId(userId)
        .setCallback(new FutureCallback<JsonResponse>() {
    
            // onCompleted is executed on ui thread
            @Override
            public void onCompleted(Exception e, JsonResponse jsonResponse) {
                mLoadingSpinner.setVisibility(View.GONE);
                if (jsonResponse.ok) {
                    // Show intent using info from jsonResponse.json
                } else {
                    // Show error toast
                }
            }
        });
    }
    

    【讨论】:

    • 我没有测试代码,希望没有大错 :)
    猜你喜欢
    • 1970-01-01
    • 2017-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-15
    • 2018-09-24
    • 2016-03-21
    • 1970-01-01
    相关资源
    最近更新 更多