如何从AsyncTasks doInBackground()中检索数据?

Cod*_*ate 16 android android-asynctask

我会保持这个尽可能简单.

我的控制层中有一个方法,它使用一个CallServiceTask扩展的类AsyncTask.调用new时CallServiceTask().execute(parameters)
如何检索返回的数据doInBackground?我发现的所有教程都使用AsyncTask直接从它们扩展的类Activity.
我的问题比这复杂一点.
我想要的只是将Object[]返回的doInBackground并将其设置为我RestClient班级的私有数据成员.

CallServiceTask 看起来像这样:

    private class CallServiceTask extends AsyncTask<Object, Void, Object[]>
{

    protected Object[] doInBackground(Object... params) 
    {
        HttpUriRequest req = (HttpUriRequest) params[0];
        String url = (String) params[1];

        return executeRequest(req, url);
    }
}
Run Code Online (Sandbox Code Playgroud)

我的RestClient类看起来像这样:

public class RestClient
{

private ArrayList <NameValuePair> params;
private ArrayList <NameValuePair> headers;

private JSONObject jsonData;

private Object[] rtnData;

private String url;

private boolean connError;

public int getResponseCode() {
    return responseCode;
}

/**
 * 
 * @return  the result of whether the login was successful by looking at the response parameter of the JSON object. 
 */
public Boolean DidLoginSucceed()
{
    // Will Crash on socket error
        return ((JSONObject) rtnData[0]).optBoolean("response");
}

public String GetToken()
{
    return jsonData.optString("token");
}

public RestClient(String url)
{
    this.url = url;
    params = new ArrayList<NameValuePair>();
    headers = new ArrayList<NameValuePair>();
    rtnData = new Object[]{ new JSONObject() , Boolean.TRUE  };
}

public void AddParam(String name, String value)
{
    params.add(new BasicNameValuePair(name, value));
}

public void AddHeader(String name, String value)
{
    headers.add(new BasicNameValuePair(name, value));
}

/**
 * This method will execute, call the service and instantiate the JSON Object through executeRequest().
 * 
 * @param method    an enum defining which method you wish to execute.
 * @throws Exception
 */
public void ExecuteCall(RequestMethod method) throws Exception
{
    Object[] parameters = new Object[]{ new HttpGet() , new String("") };
    switch(method) {
        case GET:
        {
            //add parameters
            String combinedParams = "";
            if(!params.isEmpty()){
                combinedParams += "?";
                for(NameValuePair p : params)
                {
                    String paramString = p.getName() + "=" + URLEncoder.encode(p.getValue());
                    if(combinedParams.length() > 1)
                    {
                        combinedParams  +=  "&" + paramString;
                    }
                    else
                    {
                        combinedParams += paramString;
                    }
                }
            }

            HttpGet request = new HttpGet(url + combinedParams);

            //add headers
            for(NameValuePair h : headers)
            {
                request.addHeader(h.getName(), h.getValue());
            }
            parameters[0] = request;
            parameters[1] = url;

            new CallServiceTask().execute(parameters);

            jsonData = ((JSONObject) rtnData[0]).optJSONObject("data");
            connError = (Boolean) rtnData[1];
            break;

        }
        case POST:
        {
            HttpPost request = new HttpPost(url);

            //add headers
            for(NameValuePair h : headers)
            {
                request.addHeader(h.getName(), h.getValue());
            }

            if(!params.isEmpty()){
                request.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));
            }
            new CallServiceTask().execute(request, url);
            break;
        }
    }
}

private Object[] executeRequest(HttpUriRequest request, String url)
{
    HttpClient client = new DefaultHttpClient();
    client = getNewHttpClient();

    HttpResponse httpResponse;

    try {
        httpResponse = client.execute(request);
        HttpEntity entity = httpResponse.getEntity();

        if (entity != null) {

            InputStream instream = entity.getContent();
            String response = convertStreamToString(instream);
            try {
                rtnData[0] = new JSONObject(response);
                rtnData[1] = false;

            } catch (JSONException e1) {
                rtnData[1] = true;
                e1.printStackTrace();
            }

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

    } catch (ClientProtocolException e)  {
        client.getConnectionManager().shutdown();
        e.printStackTrace();
    } catch (IOException e) {
        client.getConnectionManager().shutdown();
        e.printStackTrace();
    }
    return rtnData;
}


private static String convertStreamToString(InputStream is) {

    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();
}

/**
 * Custom HTTP Client accepting all SSL Certified Web Services.
 * 
 * @return n HttpClient object.
 */
public HttpClient getNewHttpClient() {
    try {
        KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
        trustStore.load(null, null);

        SSLSocketFactory sf = new MySSLSocketFactory(trustStore);
        sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

        HttpParams params = new BasicHttpParams();
        HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
        HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);

        SchemeRegistry registry = new SchemeRegistry();
        registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
        registry.register(new Scheme("https", sf, 443));

        ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);

        return new DefaultHttpClient(ccm, params);
    } catch (Exception e) {
        return new DefaultHttpClient();
    }
}
Run Code Online (Sandbox Code Playgroud)

Saa*_*ooq 25

唯一的方法是使用CallBack.你可以这样做:

new CallServiceTask(this).execute(request, url);
Run Code Online (Sandbox Code Playgroud)

然后在你的CallServiceTask中添加一个本地类变量,并在你的onPostExecute中调用该类的方法:

private class CallServiceTask extends AsyncTask<Object, Void, Object[]>
{
    RestClient caller;

    CallServiceTask(RestClient caller) {
        this.caller = caller;
    }


    protected Object[] doInBackground(Object... params) 
    {
        HttpUriRequest req = (HttpUriRequest) params[0];
        String url = (String) params[1];
        return executeRequest(req, url);
    }

    protected onPostExecute(Object result) {
        caller.onBackgroundTaskCompleted(result);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后只需onBackgroundTaskCompleted()在RestClient类的方法中使用Object .

更优雅和可扩展的解决方案是使用接口.有关示例实现,请参阅库.我刚刚开始它,但它有一个你想要的例子.


HiB*_*HiB 13

正如@ saad-farooq所提到的,你可以使用接口.所以你可以使用Handler.Callback或定义你自己的:

public interface ClientIF {

    public void onResponseReceived(Object result);

}
Run Code Online (Sandbox Code Playgroud)

那么你需要在你的CallServiceTask中实现它

public abstract class CallServiceTask extends AsyncTask<Object, Void, Object[]> 
    implements ClientIF
{
    Activity activity;

    CallServiceTask(Activity activity) {
        this.activity = activity;
    }

    public abstract void onResponseReceived(Object result); 

    protected Object[] doInBackground(Object... params) 
    {
        HttpUriRequest req = (HttpUriRequest) params[0];
        String url = (String) params[1];
        return executeRequest(req, url);
    }

    protected onPostExecute(Object result) {
        onResponseReceived(result);
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,costructor已更改,因此您可以从每个Activity类调用.然后在RestClient中创建此类的实例

public class RestClient
{
CallServiceTask service = new CallServiceTask() {
    @Override
    public void onResponseReceived(Object result) {
    // TODO Auto-generated method stub

    }
};

}
Run Code Online (Sandbox Code Playgroud)


Lal*_*ani 9

您可以使用get()检索您value/object的背部AsyncTask.

new CallServiceTask().execute(parameters).get();
Run Code Online (Sandbox Code Playgroud)

这将返回您返回的computed结果.但这将阻止您的UI,直到您的后台进程完成.

另一种选择是创建一个Interface或BroadcastReceiver,您可以在doInBackground()完成后立即返回值.我使用Interface和BroadcastReceiver创建了一个相同的演示,你可以从我的github检查

此外,通过使用第二种方法,您的UI将不会被阻止!

  • 但get()也会导致我的应用程序停止并等待,直到方法实际返回,因为使用AsyncTask的整个过程就是异步调用Web服务. (3认同)