公共静态方法中的异步任务返回 null

Posted

技术标签:

【中文标题】公共静态方法中的异步任务返回 null【英文标题】:Async task in public static method returns null 【发布时间】:2012-11-01 16:54:01 【问题描述】:

所以我有一个异步任务,我将它放在一个公共静态方法中,以避免挂起 UI 线程(因为它执行网络调用),同时仍然能够从我的应用程序的几个部分调用它。 Async 任务成功运行并返回一个 JSONOBJECT(我已经记录了部分代码以确认这一点)。但是问题是因为我使用公共静态方法,它应该有一个返回类型(在可能的情况下应该返回 JSONOBJECT)但它总是返回 null ..我怎样才能重新编写我的代码才能返回我的异步任务获取的 JSONOBJECT。代码如下。

public class JSONmethod 
    static InputStream is = null;
    static String res = "";
    static JSONObject jArray = null;
public static JSONObject getJSONfromURL(final String url)


    new AsyncTask<String, Void, JSONObject>() 

        @Override
        protected JSONObject doInBackground(String... params) 

    try
            HttpClient httpclient = new DefaultHttpClient();
            HttpPost httppost = new HttpPost(url);
            HttpResponse response = httpclient.execute(httppost);
            HttpEntity entity = response.getEntity();
            is = entity.getContent();



    
    catch(Exception e)
            Log.e("log_tag", "Error in http connection "+e.toString());
    


    try
            BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8);
            StringBuilder sb = new StringBuilder();
            String line = null;
            while ((line = reader.readLine()) != null) 
                    sb.append(line + "\n");
            
            is.close();
            res=sb.toString();
    
    catch(Exception e)
            Log.e("log_tag", "Error converting result "+e.toString());
    
    Log.i("Result BG ", res);
    try

        jArray = new JSONObject(res);            
    catch(JSONException e)
            Log.e("log_tag", "Error parsing data "+e.toString());
    
    return jArray; //at this point the JSONOBJECT has been fetched

     



    .execute();
    return jArray;  //Always null
 

【问题讨论】:

当然是空的。在 getJSONfromURL 返回之后,doInBackground 会被调用很多次。 【参考方案1】:

如果您的方法应该是异步的,那么它现在无法返回 JSON 结果...

你可以做的是为你的异步任务提供一个回调,当结果可用时将被调用:

    public class JSONmethod 
    static InputStream is = null;
    static String res = "";
    static JSONObject jArray = null;

    public static interface JSONCallback 
        public void onResult(JSONObject result);
    

    public static void getJSONfromURL(final String url, final JSONCallback callback) 

        new AsyncTask<String, Void, JSONObject>() 

            @Override
            protected JSONObject doInBackground(String... params) 

                try 
                    HttpClient httpclient = new DefaultHttpClient();
                    HttpPost httppost = new HttpPost(url);
                    HttpResponse response = httpclient.execute(httppost);
                    HttpEntity entity = response.getEntity();
                    is = entity.getContent();

                 catch (Exception e) 
                    Log.e("log_tag",
                            "Error in http connection " + e.toString());
                

                try 
                    BufferedReader reader = new BufferedReader(
                            new InputStreamReader(is, "iso-8859-1"), 8);
                    StringBuilder sb = new StringBuilder();
                    String line = null;
                    while ((line = reader.readLine()) != null) 
                        sb.append(line + "\n");
                    
                    is.close();
                    res = sb.toString();
                 catch (Exception e) 
                    Log.e("log_tag",
                            "Error converting result " + e.toString());
                
                Log.i("Result BG ", res);
                try 

                    jArray = new JSONObject(res);
                 catch (JSONException e) 
                    Log.e("log_tag", "Error parsing data " + e.toString());
                

                callback.onResult(jArray);

                return jArray; // at this point the JSONOBJECT has been
                                // fetched

            

        .execute();
    

你会这样使用它:

    JSONmethod.getJSONfromURL(url, new JSONCallback() 

        @Override
        public void onResult(JSONObject result) 
            // Do whatever you want with the result
        
    );

【讨论】:

【参考方案2】:

异步任务的基础是,在调用方法作为返回值后,您不会立即得到它的结果。

您的调用(无论是否静态)只会执行创建任务的过程(不执行它!)并立即返回。系统可能不会立即执行真正的任务流程代码(可能队列中有一些先前的任务等)。一旦它完成 AsyncTask.doInBackground() 方法,并在调用 AsyncTask.onPostExecute() 之后,任务将完成。默认情况下,它不会调用您的任何方法。在 AsyncTask.onPostExecute() 方法上更新 UI 是您的责任。

【讨论】:

+1。好的方法确实是使用您在onPostExecute() 中的结果来更新用户界面 @fiddler 我尝试使用 onPostExecute() 但它永远不会被调用。我觉得这很奇怪。让我试试你之前的方法,看看是否有效 @fiddler 我刚刚尝试使用您的解决方案,但仍然无法正常工作,返回的结果仍然为空,未返回 JSONOBJECT 您需要了解您的 getJSONfromURL 不能直接返回 JSON 对象,因为它将在后台计算。这就是提供回调的全部意义,该回调将在 JSON 数据可用时接收

以上是关于公共静态方法中的异步任务返回 null的主要内容,如果未能解决你的问题,请参考以下文章

在异步任务中运行各种命令

异步等待返回任务

linq查询中的异步任务方法问 题在c#中返回

CA1822 错误地应用于发布模式下的 [TestMethod] 异步任务方法?

这个异步任务方法有啥问题?

返回一个空任务还是返回null更好? C#