我会保持这个简单,我可以。
我在我的控制层使用的类 CallServiceTask
扩展的AsyncTask
的方法。当调用新的 CallServiceTask()。执行(参数)
我如何检索 doInBackground
返回的数据?所有我发现使用该扩展的类的教程的AsyncTask
直接从他们的活动
。
我的问题是更加复杂的比这一点。
我想要的是采取对象[]
按 doInBackground
返回,并将其设置的私有数据成员我的 RestClient
类。
CallServiceTask
是这样的:
私有类CallServiceTask扩展的AsyncTask<对象,太虚,对象[] GT;
{
保护的对象[] doInBackground(对象... PARAMS)
{
HttpUriRequest REQ =(HttpUriRequest)PARAMS [0];
字符串URL =(字符串)PARAMS [1];
返回executeRequest(REQ,URL);
}
}
和我RestClient类看起来是这样的:
公共类RestClient
{
私人的ArrayList<的NameValuePair> PARAMS;
私人的ArrayList<的NameValuePair>头;
私人的JSONObject jsonData;
私有对象[] rtnData;
私人字符串URL;
私人布尔connError;
公众诠释GETRESPONSE code(){
返回响应code;
}
/ **
*
返回:的登录是否成功通过查看JSON对象的响应参数的结果。
* /
公布尔DidLoginSucceed()
{
//会崩溃的套接字错误
返回((的JSONObject)rtnData [0])optBoolean(回应)。
}
公共字符串为gettoken()
{
返回jsonData.optString(令牌);
}
公共RestClient(字符串URL)
{
this.url =网址;
PARAMS =新的ArrayList<的NameValuePair>();
标题=新的ArrayList<的NameValuePair>();
rtnData =新的对象[] {新的JSONObject(),Boolean.TRUE};
}
公共无效AddParam(字符串名称,字符串值)
{
params.add(新BasicNameValuePair(名称,值));
}
公共无效的AddHeader(字符串名称,字符串值)
{
headers.add(新BasicNameValuePair(名称,值));
}
/ **
*这个方法将执行,调用服务,并通过实例executeRequest JSON对象()。
*
*参数的方法要执行该方法的枚举定义。
* @throws异常
* /
公共无效ExecuteCall(RequestMethod方法)抛出异常
{
[对象]参数=新的对象[] {新HTTPGET(),新的String()};
开关(方法){
情况下,应该:
{
//添加参数
字符串combinedParams =;
如果(!params.isEmpty()){
combinedParams + =?;
对于(的NameValuePair号码:PARAMS)
{
字符串中的paramString = p.getName()+=+ URLEn coder.en code(p.getValue());
如果(combinedParams.length()→1)
{
combinedParams + =&放大器; +中的paramString;
}
其他
{
combinedParams + =中的paramString;
}
}
}
HTTPGET请求=新HTTPGET(URL + combinedParams);
//添加页眉
对于(的NameValuePair H:头)
{
request.addHeader(h.getName(),h.getValue());
}
参数[0] =请求;
参数[1] = URL;
新CallServiceTask()执行(参数);
jsonData =((的JSONObject)rtnData [0])optJSONObject(数据)。
connError =(布尔)rtnData [1];
打破;
}
案例POST:
{
HttpPost请求=新HttpPost(URL);
//添加页眉
对于(的NameValuePair H:头)
{
request.addHeader(h.getName(),h.getValue());
}
如果(!params.isEmpty()){
request.setEntity(新UrlEn codedFormEntity(参数,可以HTTP.UTF_8));
}
新CallServiceTask()执行(请求URL)。
打破;
}
}
}
私有对象[] executeRequest(HttpUriRequest要求,字符串URL)
{
HttpClient的客户端=新DefaultHttpClient();
客户= getNewHttpClient();
HTT presponse HTT presponse;
尝试 {
HTT presponse = client.execute(要求);
HttpEntity实体= HTT presponse.getEntity();
如果(实体!= NULL){
InputStream的河道= entity.getContent();
字符串响应= convertStreamToString(河道);
尝试 {
rtnData [0] =新的JSONObject(响应);
rtnData [1] = FALSE;
}赶上(JSONException E1){
rtnData [1] =真;
e1.printStackTrace();
}
//关闭输入流会触发连接释放
instream.close();
}
}赶上(ClientProtocolException E){
client.getConnectionManager()关闭()。
e.printStackTrace();
}赶上(IOException异常E){
client.getConnectionManager()关闭()。
e.printStackTrace();
}
返回rtnData;
}
私有静态字符串convertStreamToString(InputStream的是){
的BufferedReader读卡器=新的BufferedReader(新InputStreamReader的(是));
StringBuilder的SB =新的StringBuilder();
串线= NULL;
尝试 {
而((行= reader.readLine())!= NULL){
sb.append(行+\ N);
}
}赶上(IOException异常E){
e.printStackTrace();
} 最后 {
尝试 {
is.close();
}赶上(IOException异常E){
e.printStackTrace();
}
}
返回sb.toString();
}
/ **
*自定义HTTP客户端接受所有SSL认证的Web服务。
*
* @返回ñHttpClient的对象。
* /
公共HttpClient的getNewHttpClient(){
尝试 {
密钥库的trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(NULL,NULL);
SSLSocketFactory的SF =新MySSLSocketFactory(的trustStore);
sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
的HttpParams PARAMS =新BasicHttpParams();
HttpProtocolParams.setVersion(参数,可以HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(参数,可以HTTP.UTF_8);
SchemeRegistry注册表=新SchemeRegistry();
registry.register(新计划(HTTP,PlainSocketFactory.getSocketFactory(),80));
registry.register(新计划(https开头,SF,443));
ClientConnectionManager CCM =新ThreadSafeClientConnManager(参数,可以登记);
返回新DefaultHttpClient(CCM,则params);
}赶上(例外五){
返回新DefaultHttpClient();
}
}
解决方案
要做到这一点的唯一方法是使用一个回调。你可以这样做:
新CallServiceTask(本).execute(请求URL);
然后在你的CallServiceTask从该类在onPostExecute添加本地类变量和类方法:
私有类CallServiceTask扩展的AsyncTask<对象,太虚,对象[] GT;
{
RestClient来电;
CallServiceTask(RestClient来电){
this.caller =来电;
}
保护的对象[] doInBackground(对象... PARAMS)
{
HttpUriRequest REQ =(HttpUriRequest)PARAMS [0];
字符串URL =(字符串)PARAMS [1];
返回executeRequest(REQ,URL);
}
保护onPostExecute(对象结果){
caller.onBackgroundTaskCompleted(结果);
}
}
然后,只需使用对象,只要你喜欢在你的RestClient类 onBackgroundTaskCompleted()
方法。
一个更优雅且可扩展的解决方案是使用接口。举一个例子执行看到这个库。我刚刚开始,但它拥有你想要的东西的一个例子。
I'll keep this one as simple as I can.
I have a method in my control layer that uses a class CallServiceTask
that extends AsyncTask
. When calling new CallServiceTask().execute(parameters)
How do I retrieve the data returned from doInBackground
? All the tutorials I've found use the class that extends AsyncTask
directly from their Activity
.
My problem is a little bit more complex than that.
All I want is to take the Object[]
returned by doInBackground
and set it to the private data members of my RestClient
class.
CallServiceTask
looks like this :
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);
}
}
And my RestClient class looks like this:
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();
}
}
解决方案
The only way to do this is using a CallBack. You can do something like this:
new CallServiceTask(this).execute(request, url);
Then in your CallServiceTask add a local class variable and class a method from that class in your 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);
}
}
Then simply use the Object as you like in the onBackgroundTaskCompleted()
method in your RestClient class.
A more elegant and extendible solution would be to use interfaces. For an example implementation see this library. I've just started it but it has an example of what you want.