Search code examples
androidjsonweb-serviceswcfandroid-asynctask

How can convert AsyncTask to Retrofit for get data from WCF Webservice in Android


I have a WCF webservice that returns SQL Server database data in JSON format, Now i'm using AsyncTask for get this data in Android by this code :

public class FetchInfo extends AsyncTask {

private String year = "94";
private String month = "1";
private String requested_column = "";
private String kodemelli = "";

public FetchInfo(String year, String month,String requested_column, String kodemelli) {
    this.year = year;
    this.month = month;
    this.requested_column = requested_column;
    this.kodemelli = kodemelli;
}
@Override
protected String doInBackground(Object[] params) {
    try {
        System.out.println("guru");
        DefaultHttpClient httpClient=new DefaultHttpClient();

        //Connect to the server
        HttpGet httpGet=new HttpGet("http://SERVERIP:8005/Service1.svc/checkLogin1?year="+year+"&month="+month+"&requested_column="+requested_column+"&kode_melli="+kodemelli);
        //Get the response

        String result = "";
        HttpResponse httpResponse = httpClient.execute(httpGet);
        HttpEntity httpEntity = httpResponse.getEntity();
        InputStream stream=httpEntity.getContent();
        result = convertStreamToString(stream);
        //Convert the stream to readable format
        if (result.contains("\"error\"") || result.contains("\"server error\"")){
            Main.result = "0";
            MainFish.result = "0";
        }else {
            Main.result = result;
            MainFish.result = result;
        }

    } catch (Exception e) {
        Main.result = "error";
        MainFish.result = "error";
    }

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

By this ,when the requests is more than for example 10 request, the response time is very long. From this topic How to speed up fetching of data from server using JSON? I realized that I should to use Retrofit instead AsyncTask to make my program work.

Now my question is how can convert AsyncTask class to a Retrofit?


Solution

  • Ok so first you will not use an async task with retrofit. Retrofit takes care of the async part. First you need do define a rest adapter.

    Here is a default rest adapter with your parameters in it.

    public class ApiClient {
    
    private static ApiInterface sApiInterface;
    
    public static ApiInterface getApiClient(Context context) {
    
    //build the rest adapter
    if (sApiInterface == null) {
        final RestAdapter restAdapter = new RestAdapter.Builder()
                .setEndpoint("http://SERVERIP:8005")
                .build();
        sApiInterface = restAdapter.create(ApiInterface.class);
    }
    return sApiInterface;
    }
    
    
    public interface ApiInterface {
    // /Service1.svc/checkLogin1?year="+year+"&month="+month+"&requested_column="+requested_column+"&kode_melli="+kodemelli
    @GET("/Service1.svc/checkLogin1")
    void getYourObject(
        @Query("year") String year,       
        @Query("month") String month,    
        @Query("requested_column") String requested_column,
        @Query("kode_melli") String kodemelli,
        RetrofitCallback<YourObjectModel> callback);
    
    }
    

    After you have a rest adapter you need a model to put the data in. Use jsonschema2pojo to convert valid JSON to a POJO model. Here is an example of one of my json responses and its model.

    {
    "id": "37",
    "title": "",
    "short_name": "",
    "short_description": "",
    "full_description": "",
    "url": "http:\/\/\/shows\/programname",
    "Image": {
        "url": "https:\/\/s3.amazonaws.com\/image\/original\/b2mWDPX.jpg",
        "url_sm": "https:\/\/s3.amazonaws.com\/image\/small\/b2mWDPX.jpg",
    },
    "image": "b2mWDPX.jpg",
    "hosts": [{
        "id": "651",
        "display_name": "",
        "username": "",
        "Image": {
            "url": "https:\/\/s3.amazonaws.com\/image\/original\/selfie.jpg",
            "url_sm": "https:\/\/s3.amazonaws.com\/image\/small\/selfie.jpg",
        }
    }],
    "airtimes": [{
        "start": "11:00:00",
        "end": "13:30:00",
        "weekday": "6"
    }],
    "categories": [{
        "id": "84",
        "title": "Bluegrass",
        "short_name": "bluegrass"
    }],
    "meta": []
    }
    

    I get this model. And a few others to go with it.

    public class Program {
    @Expose
    private doublea.models.Airtime Airtime;
    @Expose
    private String id;
    @Expose
    private String title;
    @SerializedName("short_name")
    @Expose
    private String shortName;
    @SerializedName("full_description")
    @Expose
    private String fullDescription;
    @SerializedName("short_description")
    @Expose
    private String shortDescription;
    @Expose
    private doublea.models.Image Image;
    @SerializedName("image")
    @Expose
    private String imageName;
    @Expose
    private List<Host> hosts = new ArrayList<Host>();
    @Expose
    private List<Category> categories = new ArrayList<Category>();
    @Expose
    private List<Airtime> airtimes = new ArrayList<Airtime>();
    
    /** Getters and Setters */
    
    public Program() {
    }
    

    Then make sure you take care of failure cases.

    public class RetrofitCallback<S> implements Callback<S> {
    private static final String TAG = RetrofitCallback.class.getSimpleName();
    
    
    @Override
    public void success(S s, Response response) {
    
    }
    
    @Override
    public void failure(RetrofitError error) {
        Log.e(TAG, "Failed to make http request for: " + error.getUrl());
        Response errorResponse = error.getResponse();
        if (errorResponse != null) {
            Log.e(TAG, errorResponse.getReason());
            if (errorResponse.getStatus() == 500) {
                Log.e(TAG, "Handle Server Errors Here");
            }
        }
    }
    }
    

    And finally making the api call.

    private void executeProgramApiCall(String year, String month, String requested_column, String kodemelli) {
    ApiClient.getApiClient(this).getProgram(year, month, requested_column, kodemelli, new RetrofitCallback<Program>() {
    
        @Override
        public void success(YourObjectModel program, Response response) {
            super.success(YourObjectModel , response);
            //TODO: Do something here with your ObjectMadel
        }
    });
    }
    

    I would highly recommend taking a look at the retrofit documentation in case you need anything special like headers or request interceptors.