Comment puis-je récupérer les données à partir AsyncTasks doInBackground()?
Je vais garder cette aussi simple que je le peux.
J'ai une méthode dans ma couche de contrôle qui utilise une classe CallServiceTask
qui s'étend AsyncTask
. Lors de l'appel de nouveau CallServiceTask().execute(parameters)
Comment puis-je récupérer les données renvoyées par doInBackground
? Tous les tutoriels que j'ai trouvé l'utilisation de la classe qui étend la classe AsyncTask
directement à partir de leur Activity
.
Mon problème est un peu plus complexe que cela.
Tout ce que je veux, c'est prendre le Object[]
retourné par doInBackground
et les données privées des membres de mon RestClient
classe.
CallServiceTask
ressemble à ceci :
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);
}
}
Et mon RestClient classe ressemble à ceci:
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();
}
}
OriginalL'auteur CodePrimate | 2012-02-14
Vous devez vous connecter pour publier un commentaire.
La seule façon de le faire est d'utiliser un CallBack. Vous pouvez faire quelque chose comme ceci:
Puis dans votre CallServiceTask ajouter une classe locale variable et appeler une méthode de cette classe dans votre onPostExecute:
Puis il suffit d'utiliser l'Objet comme vous le souhaitez dans le
onBackgroundTaskCompleted()
méthode dans votre RestClient classe.Un plus élégant et extensible solution serait d'utiliser des interfaces. Pour un exemple de mise en œuvre voir cette de la bibliothèque. Je viens juste de commencer, mais il a un exemple de ce que vous voulez.
OriginalL'auteur Saad Farooq
@saad-farooq mentionné que vous pouvez utiliser interface. Ainsi, vous pouvez utiliser le Gestionnaire.Rappel ou définir votre propre:
alors vous avez besoin pour mettre en œuvre dans votre CallServiceTask
noter que le costructor est modifié de sorte que vous pouvez appeler à partir de tous les Activité classe.
Ensuite, faire l'instance de cette classe dans votre RestClient
OriginalL'auteur HiB
Vous pouvez utiliser
get()
pour récupérer votrevalue/object
de retour deAsyncTask
.Revenir
computed
résultat que vous êtes de retour. Mais cela va bloquer votre INTERFACE utilisateur jusqu'à ce que votre processus d'arrière-plan est terminé.Une autre option est de créer une Interface ou BroadcastReceiver que vous vous retourne la valeur dès que votre
doInBackground()
est terminé. J'avais créé une démo pour le même à l'aide de l'Interface et de BroadcastReceiver, vous pouvez vérifier si de mon githubAussi, par le moyen de la deuxième approche de votre INTERFACE utilisateur de ne pas être bloqué!
Je ne suis pas. J'ai mon LoginController qui est utilisé par mon Activité lorsque l'utilisateur appuie sur le bouton se Connecter. LoginController instancie ensuite le RestClient et les appels RestCLient.ExecuteCall. ExecuteCall ajoute les paramètres de l'url, puis appelle rtnData = new CallServiceTask().execute(paramètres).get(); Comment ce pas faire de l'Activité s'asseoir et attendre pour get() pour renvoyer?
Autre chose que vous pouvez faire est d'utiliser le résultat calculé dans
onPostExecute()
méthode pour faire un quelconque des éléments d'INTERFACE utilisateur.Je demande peut-être comme un idiot, mais comment sur terre mon AsyncTask savoir à propos de l'INTERFACE utilisateur qui se trouve à 3 couches au-dessus d'elle ?
OriginalL'auteur Lalit Poptani
OriginalL'auteur SourabhPatil
OriginalL'auteur SourabhPatil
OriginalL'auteur bAdmAn