Question

Imagine a typical scenario where an activity opens, needs to call a REST HTTP API to get some content, and once received updates the UI. Obviously the API call needs doing on a separate thread, but should it be done using AsyncTask, an IntentService, or another approach, and why?

Was it helpful?

Solution

I would recommend the combination of IntentService and ResultReceiver, as described in this post.

Also have a look at Google iosched which implements this model. The 2010 version shows how to persist the ResultReceiver accross configuration changes (i.e. screen rotation) using onRetainNonConfigurationInstance, getLastNonConfigurationInstance and a static class.

I have implemented this model successfully in an application. Let me know if you have any issue with the links provided.

Edit: I forgot the "Why" question ;)

AsyncTask is tighly bound to the activity and it won't handle well configuration changes. It is fine for short tasks within the activity life (between onResume and onPause). I'm using HttpClient for my REST API calls with connection timeout and socket timeout set to 20s (due to poor mobile network...). It means the API call can last as long as 40s. You definitely want to handle such a long task in a service rather than an AsyncTask.

OTHER TIPS

Recyclerview

  <android.support.v7.widget.RecyclerView
    android:id="@+id/recycler_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

SecondActivity

import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.provider.SyncStateContract;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.widget.HorizontalScrollView;
import android.widget.Toast;

import com.bumptech.glide.util.Util;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;

public class SecondActivity extends AppCompatActivity
{
    public RecyclerView recyclerView;
    public Utils utils;
    public Setget setget;
    public ArrayList<Setget>  arrayList;
    public StudentShowAdatpter studentShowAdatpter;
    public  static final String BASE_URL="http://api/";

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        recyclerView= (RecyclerView) findViewById(R.id.recycler_view);

        utils=new Utils(SecondActivity.this);
        if(utils.isConnectingToInternet(SecondActivity.this))
        {
            new getStudentData().execute();
        }
        else
        {
            Toast.makeText(SecondActivity.this, "Please check internter connection.s", Toast.LENGTH_SHORT).show();
        }
    }

    private class getStudentData extends AsyncTask<String,String,String>
    {
        public ProgressDialog pd;

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            pd=new ProgressDialog(SecondActivity.this);
            pd.setMessage("Loading...");
            pd.setCancelable(false);
            pd.show();
        }

        @Override
        protected String doInBackground(String... params)
        {
            String str_response=utils.getResponseofGet(BASE_URL+"get.php?id=7");
            return str_response;
        }

        @Override
        protected void onPostExecute(String s)
        {
            super.onPostExecute(s);
            pd.dismiss();
            try {
                JSONObject jsonObject=new JSONObject(s);
                if(jsonObject.getString("status").equalsIgnoreCase("true"))
                {
                    JSONArray jsonArray=jsonObject.getJSONArray("detail");
                        for (int i=0;i<jsonArray.length();i++)
                        {
                            JSONObject object=jsonArray.getJSONObject(i);
                            setget=new Setget();
                            setget.setStud_name(object.getString(""));
                            setget.setStud_date(object.getString(""));
                            arrayList.add(setget);
                        }
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }

            if(arrayList!=null)
            {
                studentShowAdatpter = new StudentShowAdatpter(SecondActivity.this, arrayList);
                recyclerView.setLayoutManager(new LinearLayoutManager(SecondActivity.this));
                //recyclerView.addItemDecoration(new GridSpacingItemDecoration(2, dpToPx(10), true));
                recyclerView.setItemAnimator(new DefaultItemAnimator());
                recyclerView.setAdapter(studentShowAdatpter);
            }
            else
            {
                Toast.makeText(SecondActivity.this, "Data Not Found", Toast.LENGTH_SHORT).show();
            }
        }
    }

}

Adapter

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import java.util.ArrayList;


public class StudentShowAdatpter extends RecyclerView.Adapter<StudentShowAdatpter.MyViewHolder>
{
public Setget setget;
public ArrayList<Setget> arrayList;
Context context;
public StudentShowAdatpter(SecondActivity secondActivity, ArrayList<Setget> arrayList) {
    this.arrayList=arrayList;
    this.context=secondActivity;
}

@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
    View itemView = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.adapter_stud_list, parent, false);
    return new MyViewHolder(itemView);
}

@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
        setget=arrayList.get(position);
        holder.stud_name.setText(setget.getStud_name());
        holder.stud_date.setText(setget.getStud_date());
}

   @Override
public int getItemCount() {
    return arrayList.size();
}

public class MyViewHolder extends RecyclerView.ViewHolder {
    public TextView stud_name, stud_date;

    public MyViewHolder(View view) {
        super(view);
        stud_date = (TextView) view.findViewById(R.id.stud_date);
        stud_name = (TextView) view.findViewById(R.id.stud_name);
    }
}
}

Calling API Using AsyncTask With LOGIN AND DISPLAY DATA IN RECYCLERVIEW

build.gradle(Module.app)

dependencies {
     compile 'com.android.support:recyclerview-v7:23.3.+'
     compile 'com.android.support:cardview-v7:23.3.+'
     compile 'com.github.bumptech.glide:glide:3.7.0'
}

AndroidManifest.xml

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>

login.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginLeft="20dp"
    android:layout_marginTop="15dp"
    android:layout_marginRight="10dp"
    android:orientation="vertical">

    <EditText
        android:id="@+id/edit_email"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Enter Email" />

    <EditText
        android:id="@+id/edit_password"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Enter Password" />

    <Button
        android:id="@+id/btn_login"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:text="Login" />

</LinearLayout>

MainActivity.java

import android.app.ProgressDialog;
import android.content.Intent;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.HashMap;

public class MainActivity extends AppCompatActivity
{
public EditText edit_email,edit_password;
public Button btn_login;
public String str_email,str_password;
public Utils utils;
public String emailPattern = "[a-zA-Z0-9._-]+@[a-z]+.[a-z]+";
public  static final String BASE_URL="ffyy/";
@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    utils=new Utils(MainActivity.this);
    edit_email= (EditText) findViewById(R.id.edit_email);
    edit_password= (EditText) findViewById(R.id.edit_password);
    btn_login= (Button) findViewById(R.id.btn_login);

    btn_login.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v)
        {
            if (edit_email.getText().toString().trim().length() == 0)
            {
                edit_email.setError("Enter Email Id");
                return;
            }
            else if (edit_password.getText().toString().trim().length() == 0) {
                edit_password.setError("Enter Password");
                return;
            }
            else {
                str_email = edit_email.getText().toString();
                str_password = edit_password.getText().toString();
                if (utils.isConnectingToInternet(MainActivity.this)) {
                    new getLoginData().execute();
                } else {
                    Toast.makeText(MainActivity.this, "Please check internet connection.", Toast.LENGTH_SHORT).show();
                    }
            }
        }
    });
}

private class getLoginData extends AsyncTask<String,String,String>
{
    public ProgressDialog pd;

    @Override
    protected void onPreExecute()
    {
        super.onPreExecute();
        pd=new ProgressDialog(MainActivity.this);
        pd.setMessage("Loading...");
        pd.setCancelable(false);
        pd.show();
    }

    @Override
    protected String doInBackground(String... params)
    {
        HashMap<String,String> hashMap=new HashMap<>();
        hashMap.put("email", str_email);
        hashMap.put("password", str_password);
        String str_response= utils.getResponseofPost(BASE_URL+"login_for_all.php",hashMap);
        return str_response;
    }

    @Override
    protected void onPostExecute(String s)
    {
        super.onPostExecute(s);
        pd.dismiss();
        try {
            JSONObject jsonObject=new JSONObject(s);
            if(jsonObject.getString("status").equalsIgnoreCase("true"))
            {
                Toast.makeText(MainActivity.this, jsonObject.getString("msg"), Toast.LENGTH_SHORT).show();

            }
            else
            {
                Toast.makeText(MainActivity.this, jsonObject.getString("msg"), Toast.LENGTH_SHORT).show();
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
}
}

Utils.java

   import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.location.Location;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkInfo;
import android.os.Build;
import android.os.StrictMode;
import android.preference.PreferenceManager;
import android.util.Base64;
import android.util.Log;


import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Type;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.net.ssl.HttpsURLConnection;


public class Utils {
    static Context context;
    SharedPreferences sp;
    Location getLocation;

    public Utils(Context context) {
        this.context = context;
        //sp = context.getSharedPreferences(Constant.Prefrence, Context.MODE_PRIVATE);
    }

   /* public String getReadSharedPrefrenceIsFirstTime(Context activity, String userid) {
        String defValue = "";
        String resposne = sp.getString(Constant.ISFIRSTTIME, defValue);
        return resposne;
    }
*/
/*
    public static String convertToGson(Object object) {
        Gson gson = new Gson();
        String loginResult = gson.toJson(object);
        return loginResult;
    }

    public static <T> T GsonToObject(String strObj, Type classObject) {
        Gson gson = new Gson();
        return gson.fromJson(strObj, classObject);
    }
*/


    public void clearSharedPreferenceData() {
        sp.edit().clear().commit();
    }

    public String getResponseofPost(String URL, HashMap<String, String> postDataParams) {
        URL url;
        String response = "";
        try {
            url = new URL(URL);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setReadTimeout(15000);
            conn.setConnectTimeout(15000);
            conn.setRequestMethod("POST");
            conn.setDoInput(true);
            conn.setDoOutput(true);
            OutputStream os = conn.getOutputStream();
            BufferedWriter writer = new BufferedWriter(
                    new OutputStreamWriter(os, "UTF-8"));

            writer.write(getPostDataString(postDataParams));
            writer.flush();
            writer.close();
            os.close();
            int responseCode = conn.getResponseCode();
            if (responseCode == HttpsURLConnection.HTTP_OK) {
                String line;
                BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                while ((line = br.readLine()) != null) {
                    response += line;
                }
            } else {
                response = "";
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return response;
    }

    public static String getResponseofGet(String URL) {
        URL url;
        String response = "";
        try {

            StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
            StrictMode.setThreadPolicy(policy);
            url = new URL(URL);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setReadTimeout(15000);
            conn.setConnectTimeout(15000);
            conn.setRequestMethod("GET");
            conn.setDoInput(true);
            conn.setDoOutput(true);

            OutputStream os = conn.getOutputStream();
            BufferedWriter writer = new BufferedWriter(
                    new OutputStreamWriter(os, "UTF-8"));

            writer.flush();
            writer.close();
            os.close();
            int responseCode = conn.getResponseCode();
            Log.d("URL - ResponseCode", URL + " - " + responseCode);
            if (responseCode == HttpsURLConnection.HTTP_OK) {
                String line;
                BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                while ((line = br.readLine()) != null) {
                    response += line;
                }
            } else {
                response = "";
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return response;
    }

    private String getPostDataString(HashMap<String, String> params) throws
            UnsupportedEncodingException {
        StringBuilder result = new StringBuilder();
        boolean first = true;
        for (Map.Entry<String, String> entry : params.entrySet()) {
            if (first)
                first = false;
            else
                result.append("&");

            result.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
            result.append("=");
            result.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
        }
        return result.toString();
    }

    public String MakeServiceCall(String URLSTR) {
        StringBuilder response = null;
        try {
            response = new StringBuilder();
            URL url = new URL(URLSTR);
            HttpURLConnection httpconn = (HttpURLConnection) url.openConnection();
            if (httpconn.getResponseCode() == HttpURLConnection.HTTP_OK) {
                BufferedReader input = new BufferedReader(new InputStreamReader(httpconn.getInputStream()), 8192);
                String strLine = null;
                while ((strLine = input.readLine()) != null) {
                    response.append(strLine);
                }
                input.close();
            }
        } catch (Exception e) {
        }
        return response.toString();
    }

    private boolean appInstalledOrNot(String packageName) {
        PackageManager pm = context.getPackageManager();
        boolean app_installed;
        try {
            pm.getPackageInfo(packageName, PackageManager.GET_ACTIVITIES);
            app_installed = true;
        } catch (PackageManager.NameNotFoundException e) {
            app_installed = false;
        }
        return app_installed;
    }

    public static boolean isConnectingToInternet(Context context)
    {
        ConnectivityManager connectivityManager = (ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Network[] networks = connectivityManager.getAllNetworks();
            NetworkInfo networkInfo;
            for (Network mNetwork : networks)
            {
                networkInfo = connectivityManager.getNetworkInfo(mNetwork);
                if (networkInfo.getState().equals(NetworkInfo.State.CONNECTED)) {
                    return true;
                }
            }
        } else {
            if (connectivityManager != null)
            {
                NetworkInfo[] info = connectivityManager.getAllNetworkInfo();
                if (info != null) {
                    for (NetworkInfo anInfo : info) {
                        if (anInfo.getState() == NetworkInfo.State.CONNECTED) {
                            return true;
                        }
                    }
                }
            }
        }
        return false;
    }

    public static void WriteSharePrefrence(Context context, String key, String value)
    {
        final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
        final SharedPreferences.Editor editor = preferences.edit();
        editor.putString(key, value);
        editor.commit();
    }

    public static String ReadSharePrefrence(Context context, String key)
    {
        String data;
        final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
        final SharedPreferences.Editor editor = preferences.edit();
        data = preferences.getString(key, "");
        editor.commit();
        return data;
    }




    public static void Clear(Context context, String key)
    {
        String data;
        final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
        final SharedPreferences.Editor editor = preferences.edit().clear();
        editor.commit();
    }

    public static void ClearaSharePrefrence(Context context) {
        String data;
        final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
        final SharedPreferences.Editor editor = preferences.edit().clear();
        editor.commit();
    }

    public static String encodeToBase64(Bitmap image, Bitmap.CompressFormat compressFormat, int quality) {
        ByteArrayOutputStream byteArrayOS = new ByteArrayOutputStream();
        image.compress(compressFormat, quality, byteArrayOS);
        return Base64.encodeToString(byteArrayOS.toByteArray(), Base64.DEFAULT);
    }

    public static String getLeaveStatus(String status) {
        String result = "";
        switch (status) {
            case "0":
                result = "Pending";
                break;
            case "1":
                result = "Aproved";
                break;
            case "2":
                result = "Cancel";
                break;
        }
        return result;
    }


    public String parseDateToddMMyyyy(String time)
    {
        String inputPattern = "yyyy-MM-dd HH:mm:ss";
        String outputPattern = "yyyy-MM-dd";
        SimpleDateFormat inputFormat = new SimpleDateFormat(inputPattern);
        SimpleDateFormat outputFormat = new SimpleDateFormat(outputPattern);
        Date date = null;
        String str = null;
        try {
            date = inputFormat.parse(time);
            str = outputFormat.format(date);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return str;
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top