简体   繁体   English

从AsyncTask返回对象时出现问题

[英]Problem returning an object from an AsyncTask

I have a class (RestClient.java) that extends AsyncTask: package org.stocktwits.helper; 我有一个扩展AsyncTask的类(RestClient.java):package org.stocktwits.helper;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONException;
import org.json.JSONObject;

import android.os.AsyncTask;
import android.util.Log;

public class RestClient extends AsyncTask<String, Void, JSONObject>{
    public JSONObject jsonObj = null;
    private static String convertStreamToString(InputStream is) {
        /*
         * To convert the InputStream to String we use the BufferedReader.readLine()
         * method. We iterate until the BufferedReader return null which means
         * there's no more data to read. Each line will appended to a StringBuilder
         * and returned as String.
         */
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        StringBuilder sb = new StringBuilder();

        String line = null;
        try {
            while ((line = reader.readLine()) != null) {
                sb.append(line + "\n");
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return sb.toString();
    }


    /* This is a test function which will connects to a given
     * rest service and prints it's response to Android Log with
     * labels "Praeda".
     */
    public static JSONObject connect(String url)
    {

        HttpClient httpclient = new DefaultHttpClient();


        // Prepare a request object
        HttpGet httpget = new HttpGet(url); 

        // Execute the request
        HttpResponse response;
        try {
            response = httpclient.execute(httpget);
            // Examine the response status
            Log.i("Praeda",response.getStatusLine().toString());

            // Get hold of the response entity
            HttpEntity entity = response.getEntity();

            if (entity != null) {

                // A Simple JSON Response Read
                InputStream instream = entity.getContent();
                String result= convertStreamToString(instream);

                // A Simple JSONObject Creation
                JSONObject json=new JSONObject(result);

                // Closing the input stream will trigger connection release
                instream.close();

                return json;
            }


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

        return null;
    }

    @Override
    protected JSONObject doInBackground(String... urls) {
        return connect(urls[0]);
    }

    @Override
    protected void onPostExecute(JSONObject json ) {
        this.jsonObj = json;
    }

    public void setJSONObject(JSONObject jsonFromUI){
        this.jsonObj = jsonFromUI;
    }

    public JSONObject getJSONObject(){
        return this.jsonObj;
    }

}

I am trying to execute the AsyncTask on my Main class (Main.java): 我试图在我的Main类(Main.java)上执行AsyncTask:

    RestClient rc = new RestClient();
    JSONObject json = new JSONObject();
    rc.setJSONObject(json);
    rc.execute(buildQuery());
    json = rc.getJSONObject();

//do some stuff with the json object
try { JSONObject query = json.getJSONObject("query");
//...
}

json is null because it is called before onPostExecute(). json为null,因为它在onPostExecute()之前调用。 How can I get my JSON? 如何获取JSON?

UPDATE: I need to run this try block in onPostExecute(): 更新:我需要在onPostExecute()中运行以下try块:

try {

            JSONObject query = json.getJSONObject("query");
            JSONObject results = query.getJSONObject("results");

            if (query.getString("count").equals("1")) { // YQL JSON doesn't
                // return an array for
                // single quotes
                JSONObject quote = results.getJSONObject("quote");

                Quote myQuote = new Quote();
                myQuote.setName(quote.getString("Name"));
                myQuote.setSymbol(quote.getString("Symbol"));
                myQuote.setLastTradePriceOnly(quote
                        .getString("LastTradePriceOnly"));
                myQuote.setChange(quote.getString("Change"));
                myQuote.setOpen(quote.getString("Open"));
                myQuote.setMarketCapitalization(quote
                        .getString("MarketCapitalization"));
                myQuote.setDaysHigh(quote.getString("DaysHigh"));
                myQuote.setYearHigh(quote.getString("YearHigh"));
                myQuote.setDaysLow(quote.getString("DaysLow"));
                myQuote.setYearLow(quote.getString("YearLow"));
                myQuote.setVolume(quote.getString("Volume"));
                myQuote.setAverageDailyVolume(quote
                        .getString("AverageDailyVolume"));
                myQuote.setPeRatio(quote.getString("PERatio"));
                myQuote.setDividendYield(quote.getString("DividendYield"));
                myQuote.setPercentChange(quote.getString("PercentChange"));

                quotesAdapter.add(myQuote);}

Hey You can use listeners to fix this problem. 嘿,您可以使用侦听器解决此问题。 I've changed the code slightly to use this. 我已经稍微更改了代码以使用此代码。

package com.insidetip.uob.data;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;

public class JSONClient extends AsyncTask<String, Void, JSONObject>{
    ProgressDialog progressDialog ;
    GetJSONListener getJSONListener;
    Context curContext;
    public JSONClient(Context context, GetJSONListener listener){
        this.getJSONListener = listener;
        curContext = context;
    }
    private static String convertStreamToString(InputStream is) {
        /*
         * To convert the InputStream to String we use the BufferedReader.readLine()
         * method. We iterate until the BufferedReader return null which means
         * there's no more data to read. Each line will appended to a StringBuilder
         * and returned as String.
         */
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        StringBuilder sb = new StringBuilder();

        String line = null;
        try {
            while ((line = reader.readLine()) != null) {
                sb.append(line + "\n");
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return sb.toString();
    }


    public static JSONObject connect(String url)
    {
        HttpClient httpclient = new DefaultHttpClient();

        // Prepare a request object
        HttpGet httpget = new HttpGet(url); 

        // Execute the request
        HttpResponse response;
        try {
            response = httpclient.execute(httpget);
            // Examine the response status
            Log.i("Praeda",response.getStatusLine().toString());

            // Get hold of the response entity
            HttpEntity entity = response.getEntity();

            if (entity != null) {

                // A Simple JSON Response Read
                InputStream instream = entity.getContent();
                String result= convertStreamToString(instream);

                // A Simple JSONObject Creation
                JSONObject json=new JSONObject(result);

                // Closing the input stream will trigger connection release
                instream.close();

                return json;
            }


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

        return null;
    }
    @Override
    public void onPreExecute() {
        progressDialog = new ProgressDialog(curContext);
        progressDialog.setMessage("Loading..Please wait..");
        progressDialog.setCancelable(false);
        progressDialog.setIndeterminate(true);
        progressDialog.show();

    }

    @Override
    protected JSONObject doInBackground(String... urls) {
        return connect(urls[0]);
    }

    @Override
    protected void onPostExecute(JSONObject json ) {
        getJSONListener.onRemoteCallComplete(json);
        progressDialog.dismiss();
    }
}

Use in the calling class like this. 像这样在调用类中使用。

    JSONClient client = new JSONClient(context, listener);
    client.execute(URL);

Dont forget to implement the listener 不要忘记实现监听器

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

I'm be mistaken by result of doInBackground can be consumed in onPostExecute 我被doInBackground的结果误​​认为可以在onPostExecute中使用

doInBackground(Params...), invoked on the background thread immediately after on PreExecute() finishes executing. doInBackground(Params ...),在PreExecute()完成执行后立即在后台线程上调用。 This step is used to perform background computation that can take a long time. 此步骤用于执行可能需要很长时间的后台计算。 The parameters of the asynchronous task are passed to this step. 异步任务的参数将传递到此步骤。 The result of the computation must be returned by this step and will be passed back to the last step . 计算结果必须通过此步骤返回,并将传递回最后一步 This step can also use publishProgress(Progress...) to publish one or more units of progress. 此步骤还可以使用publishProgress(Progress ...)发布一个或多个进度单位。 These values are published on the UI thread, in the onProgressUpdate(Progress...) step. 这些值在onProgressUpdate(Progress ...)步骤中发布在UI线程上。

@Override

protected void onPostExecute(JSONObject json ) {
// DO stuff here ( it's UI thread )
 mJsonFromTheActivity = json;
}

execute() always returns the AsyncTask itself. execute()始终返回AsyncTask本身。 The object you return from doInBackground() is handed to you in onPostExecute(). 从doInBackground()返回的对象将在onPostExecute()中交给您。

如果您将asynctask作为活动的嵌套内部类,则可以将其中一个活动变量设置为asynctask的结果

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM