7 Ekim 2011 Cuma

AsyncTask class'tan dönen parametreyi handle etmek.

Merhaba

Android projelerinde genelde AsyncTask class, bir sub class olarak kullanıldığından o activity'e ait bir nesneyi set etmek çok fazla problem olmuyor. Bunun için OnPostExecute methodunda gerekli set işlemini yapmanız yeterli (konuyla ilgili bilgisi olmayanlar için güzel bir makale). Ancak bazı durumlarda network gibi UI thread üzerinde çalışmaya izin verilmeyen ancak bir çok activity tarafından kullanılacağı için inner class olarak tanımlanmasının da mantıklı olmadığı AsyncTask classlara ihtiyacımız olabilir. Bu durumda Context'i parametre olarak geçip AsyncTask class'ında o context'e ait gerekli field'ı ya da methodu set etmek mümkün gibi gözükse de bu çok kullanışlı olmayacaktır çünkü yine o methodu (veya field ya da context'i) cast edip içerisindeki set edeceğiniz field'ı manuel bir şekilde belirtmeniz gerekecektir.

Örneğimizde herhangi bir activity içerisinde soap request göndermek istenilen bir butona basıldığını varsayıyoruz.


public void onClick(View v) {
switch (v.getId()) {
case R.id.btnGonder:
String uri = "http://www.mustafaguven.com.tr/androidDenemeWebservice/Service1.asmx";
String soapAction = "http://tempuri.org/HelloWorld";
KeyValuePair[] parameters = new KeyValuePair[1];
parameters[0] = new KeyValuePair("a", "a parametresine atanan deger burada");
CallSoap soap = new CallSoap(uri, soapAction, parameters);
soap.setDataDownloadListener(new CallSoap.DataDownloadListener() {
public void dataDownloadedSuccessfully(String data) {
Log.e("GELEN DATA",data);
}
public void dataDownloadFailed() {

}
});
soap.execute("");
break;

default:
break;
}
}


Sıra geldi tüm bu istekleri hem dispatch edecek hem de işleyip geriye değer dönecek classımızı yazmaya. Hatırlayacağınız üzere yukarıda bir çok handikaptan bahsetmiştim, bu handikaplardan kurtulmak için kendi tanımlayacağımız bir Listener içeren AsyncTask class yazmak yeterli. Aşağıdaki class farklı activitylerden gelen soap isteklerini arkaplanda çalışan bir thread ile yönetip daha sonra bulduğu sonuç kümesini (result value) onPostExecute ile UI thread'e geçiyor. Buraya kadar yapılanlar, diğer asenkron classların kullanım metodolojisiyle zaten aynı. İşte tam bu noktada DataDownloadListener adlı listenerımız devreye giriyor. onPostExecute'da set edilen dataDownloadedSuccessfully methodu sayesinde bu class'ı call eden activity'de geri dönüş değeri kolaylıkla handle edilebiliyor.



package com.quadro.main.Util;

import org.apache.http.HttpEntity;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;

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

public class CallSoap extends AsyncTask {

private String methodName="";
private String uri="";
private String soapAction="";
private KeyValuePair[] parameters = null;
private String envelope = "";

DataDownloadListener dataDownloadListener;
   public void setDataDownloadListener(DataDownloadListener dataDownloadListener) {
       this.dataDownloadListener = dataDownloadListener;
   }

public CallSoap(String uri, String soapAction, KeyValuePair[] parameters){
this.uri=uri;
this.soapAction=soapAction;
this.parameters = parameters;
int iLastIndexOf = soapAction.lastIndexOf("/");
if(iLastIndexOf>0){
this.methodName=soapAction.substring(iLastIndexOf+1);
}
this.envelope = getSoapTemplate();
}

private String getSoapTemplate() {
String parameterXml="";
if(parameters!=null){
for (int i = 0; i < parameters.length; i++) {
KeyValuePair kv = parameters[i];
parameterXml+=String.format("<%s>%s",kv.getText(),kv.getValue(), kv.getText());
}

}
String envelope="<?xml version=\"1.0\" encoding=\"iso-8859-9\"?>"+
"<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" " +
"soap:encodingStyle=\"http://www.w3.org/2001/12/soap-encoding\">"+
"<soap:Body>"+
"<%s xmlns=\"http://tempuri.org/\">"+
"%s"+
"</%s>"+
"</soap:Body>"+
"</soap:Envelope>";
envelope = String.format(envelope, this.methodName, parameterXml, this.methodName);
return envelope;
}


@Override
protected String doInBackground(String... parameters) {
final DefaultHttpClient httpClient=new DefaultHttpClient();
HttpParams params = httpClient.getParams();
HttpConnectionParams.setConnectionTimeout(params, 10000);
HttpConnectionParams.setSoTimeout(params, 15000);

HttpProtocolParams.setUseExpectContinue(params, true);
HttpPost httppost = new HttpPost(uri);

httppost.setHeader("soapaction", soapAction);
httppost.setHeader("Content-Type", "text/xml; charset=iso-8859-9");

String responseString="";
try {
HttpEntity entity = new StringEntity(envelope, "iso-8859-9");
httppost.setEntity(entity);

ResponseHandler rh=new ResponseHandlerTr();
responseString=httpClient.execute(httppost, rh);
}
catch (Exception e) {
Log.e("exception", e.toString());
}

httpClient.getConnectionManager().shutdown();
return responseString;
}

@Override
protected void onPostExecute(final String responseString) {
       if(responseString != null){            
        dataDownloadListener.dataDownloadedSuccessfully(responseString);
       } else
        dataDownloadListener.dataDownloadFailed();
}

   public static interface DataDownloadListener {
       void dataDownloadedSuccessfully(String data);
       void dataDownloadFailed();
   }

}

Anlaşılmayan bir nokta olursa çekinmeden danışabilirsiniz.

İyi çalışmalar,
Mustafa Güven

2 yorum:

  1. Never fight against three things:

    1. The power
    2. The reality
    3. The unknown

    YanıtlaSil
  2. Merhaba Mustafa, ben çözemedim şu asynctasktan diğer class'a veri döndürmeyi. buton clickte asynctask classini çağırıyorum network işlemleri için. ama textalanına istediğim veriyi yazdırmaya çalışırken text alanının initial değerini yazıyor ama log catte baktığım zaman önce butonclick olayı bitiyor. sonra devreye asynctask girdiği için istediğim veriyi alamıyorum. yardımcı olursan sevinirim. kolay gelsin.

    YanıtlaSil