我将尽可能简化这一过程。
我在控制层中有一个方法,该方法使用扩展CallServiceTask
的类AsyncTask
。调用新的CallServiceTask().execute(parameters)
时
如何检索从doInBackground
返回的数据?我发现的所有教程都使用直接从AsyncTask
扩展Activity
的类。
我的问题要复杂得多。
我只想获取Object[]
返回的doInBackground
并将其设置为RestClient
类的私有(private)数据成员。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);
}
}
我的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();
}
}
最佳答案
唯一的方法是使用CallBack。您可以执行以下操作:
new CallServiceTask(this).execute(request, url);
然后在您的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);
}
}
然后,只需在RestClient类的
onBackgroundTaskCompleted()
方法中随意使用Object即可。一个更优雅,更可扩展的解决方案是使用接口(interface)。有关示例实现,请参见this库。我刚刚启动它,但是它有您想要的示例。