【问题标题】:Return data from AsyncTask class从 AsyncTask 类返回数据
【发布时间】:2011-11-28 22:28:59
【问题描述】:

如何从我的 AsyncTask 中获取数据?我的 MainActivity 正在调用触发 AsyncTask 的 DataCall.getJSON 函数,但我不确定如何将数据返回到原始 Activity。

调用 DataCall 的 MainActivity 应返回一个字符串并将其保存在 state_data

String state_data =  DataCall.getJSON(spinnerURL,spinnerContentType); 

数据调用:

public class DataCall extends Activity {
    private static final String TAG = "MyApp";


    private class DownloadWebPageTask extends AsyncTask<String, Void, String> {


        protected String doInBackground(String... urls) {
            String response = "";
            for (String url : urls) {
                DefaultHttpClient client = new DefaultHttpClient();
                HttpGet httpGet = new HttpGet(url);
                try {
                    HttpResponse execute = client.execute(httpGet);
                    InputStream content = execute.getEntity().getContent();

                    BufferedReader buffer = new BufferedReader(
                            new InputStreamReader(content));
                    String s = "";
                    while ((s = buffer.readLine()) != null) {
                        response += s;
                    }

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            return response;
        }


        protected void onPostExecute(String result) {
            //THIS IS WHERE I NEED TO RETURN MY DATA TO THE MAIN ACTIVITY. (I am guessing)
        }

        }

    public void getJSON(String myUrlString, String contentType) {
        DownloadWebPageTask task = new DownloadWebPageTask();
        task.execute(new String[] { "http://www.mywebsite.com/" + myUrlString });

    }

}

【问题讨论】:

  • 为什么不尝试服务驱动的 REST 调用模型?而不是在依赖于 Activity 的线程上执行请求?

标签: java android android-asynctask


【解决方案1】:

修改你的AsyncTask如下:

public class GetData extends AsyncTask<String, Void, String>
{
    DataDownloadListener dataDownloadListener;
    public GetData()
    {
        //Constructor may be parametric 
    }
    public void setDataDownloadListener(DataDownloadListener dataDownloadListener) {
        this.dataDownloadListener = dataDownloadListener;
    }
    @Override
    protected Object doInBackground(Object... param) 
    {
        // do your task...
        return null;
    }
    @Override
    protected void onPostExecute(Object results)
    {       
        if(results != null)
        {               
        dataDownloadListener.dataDownloadedSuccessfully(results);
        }
        else
        dataDownloadListener.dataDownloadFailed();
    }
    public static interface DataDownloadListener {
        void dataDownloadedSuccessfully(Object data);
        void dataDownloadFailed();
    }
}

并在您的活动中使用它

GetData getdata = new GetData();
getdata.setDataDownloadListener(new DataDownloadListener()
{
    @SuppressWarnings("unchecked")
    @Override
    public void dataDownloadedSuccessfully(Object data) {
    // handler result
    }
    @Override
    public void dataDownloadFailed() {
    // handler failure (e.g network not available etc.)
    }
});
getdata.execute("");

注意:对于正在阅读本文的人。

请考虑这个post 以获得最好的,也许是正确的实施。

【讨论】:

  • 但是如何将我的变量传递给 GetData 类?谢谢您的帮助。 +1
  • 好吧,正如我所提到的,您可以通过GetData 的构造函数传递变量,并将它们设为GetData 类的字段,以便在方法中进一步使用它们。
  • 嗨阿迪尔,哪个线程将处理将处理 dataDownloadedSuccessfully() ?是 AsyncTask 线程还是 UI 线程?我希望 UI 线程处理我的结果,以便我可以更新 UI。对此有何见解?
  • Hay @AKh onPostExecute() 在 UI 线程上调用,所以如果你将 dataDownloadedSuccessfully() 放在 onPostExecute() 中,它将在 UI 线程上调用,你可以对 UI 进行更新。
  • 为什么你的AsyncTask 设置为返回String 类型,而doInBackground 设置为返回Object 但实际上返回null?是我自己还是真的错了?
【解决方案2】:

对我来说,关键是创建一个名为 URLWithParams 的类或其他类,因为 AsyncTask 将只允许发送一种类型,并且我需要 URL 和 HTTP 请求的参数。

public class URLWithParams {

    public String url;
    public List<NameValuePair> nameValuePairs;

    public URLWithParams()
    {
        nameValuePairs = new ArrayList<NameValuePair>();
    }
}

然后我将其发送到 JSONClient:

public class JSONClient extends AsyncTask<URLWithParams, Void, String> {
    private final static String TAG = "JSONClient";

    ProgressDialog progressDialog ;
    GetJSONListener getJSONListener;
    public JSONClient(GetJSONListener listener){
        this.getJSONListener = listener;
    }

    @Override
    protected String doInBackground(URLWithParams... urls) {
        return connect(urls[0].url, urls[0].nameValuePairs);
    }

    public static String connect(String url, List<NameValuePair> pairs)
    {
        HttpClient httpclient = new DefaultHttpClient();

        if(url == null)
        {
            Log.d(TAG, "want to connect, but url is null");
        }
        else
        {
            Log.d(TAG, "starting connect with url " + url);
        }

        if(pairs == null)
        {
            Log.d(TAG, "want to connect, though pairs is null");
        }
        else
        {
            Log.d(TAG, "starting connect with this many pairs: " + pairs.size());
            for(NameValuePair dog : pairs)
            {
                Log.d(TAG, "example: " + dog.toString());
            }
        }

        // Execute the request
        HttpResponse response;
        try {
            // Prepare a request object
            HttpPost httpPost = new HttpPost(url); 
            httpPost.setEntity(new UrlEncodedFormEntity(pairs));
            response = httpclient.execute(httpPost);
            // Examine the response status
            Log.i(TAG,response.getStatusLine().toString());

            BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
            String json = reader.readLine();
            return json;

        } catch (ClientProtocolException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return null;
    }



    @Override
    protected void onPostExecute(String json ) {
        getJSONListener.onRemoteCallComplete(json);
    }


    public interface GetJSONListener {
        public void onRemoteCallComplete(String jsonFromNet);
    }

}

然后像这样从我的主类中调用它

public class BookCatalog implements GetJSONListener {
    private final String TAG = this.getClass().getSimpleName();

    private String catalog_url = "URL";

    private void getCatalogFromServer() {

        URLWithParams mURLWithParams = new URLWithParams();
        mURLWithParams.url = catalog_url;

        try {
            JSONClient asyncPoster = new JSONClient(this);
            asyncPoster.execute(mURLWithParams);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    @Override
    public void onRemoteCallComplete(String jsonBookCatalogList) {

        Log.d(TAG, "received json catalog:");
        Log.d(TAG, jsonBookCatalogList);
    JSONObject bookCatalogResult;
    try {
        bookCatalogResult = (JSONObject) new JSONTokener(jsonBookCatalogList).nextValue();
        JSONArray books = bookCatalogResult.getJSONArray("books");

        if(books != null) {
            ArrayList<String> newBookOrdering = new ArrayList<String>();
            int num_books = books.length();
            BookCatalogEntry temp;

            DebugLog.d(TAG, "apparently we found " + Integer.toString(num_books) + " books.");
            for(int book_id = 0; book_id < num_books; book_id++) {
                JSONObject book = books.getJSONObject(book_id);
                String title = book.getString("title");
                int version = book.getInt("price");
            }
        }

    } catch (JSONException e) {
        e.printStackTrace();
    } 

    }


}

【讨论】:

    【解决方案3】:

    虽然我不同意为那个简单的任务创建一个新的活动,但有

    startActivityForResult()
    

    从另一个活动中获取数据。

    检查this。您可以将数据存储到 Intent 的附加组件中。但是,如果您有大量数据,最好将其写入文件,从完成下载的其他活动中获取结果,然后读取文件。

    【讨论】:

      【解决方案4】:

      序列化然后阅读。我知道的唯一方法。

      【讨论】:

        【解决方案5】:

        一些选项:

        a) 让你的 bean 实现 Serializable 接口,然后你可以通过 Intent 传递你的 bean。

        b) 实现Application 接口(您需要在清单中创建条目),在您的应用程序类中有setter\getter 方法。您可以在 Application 中从 AsyncTask 设置您的 bean,然后从 Activity 中检索。

        【讨论】:

          【解决方案6】:

          抱歉这么晚才回答,我想此时您可能已经解决了这个问题。当我在寻找其他东西时,我遇到了你的问题。我正在粘贴一个链接 here,这可能对其他人有所帮助。

          【讨论】:

            猜你喜欢
            • 2012-02-13
            • 1970-01-01
            • 2014-09-04
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-07-14
            • 1970-01-01
            相关资源
            最近更新 更多