Friday 19 September 2014

Volley cache Example


Volley cache Example

Volley is an HTTP library that makes networking for Android apps easier and most importantly, faster. Volley is available through the open AOSP repository.
Volley offers the following benefits:
  • Automatic scheduling of network requests.
  • Multiple concurrent network connections.
  • Transparent disk and memory response caching with standard HTTP cache coherence.
  • Support for request prioritization.
  • Cancellation request API. You can cancel a single request, or you can set blocks or scopes of requests to cancel.
  • Ease of customization, for example, for retry and backoff.
  • Strong ordering that makes it easy to correctly populate your UI with data fetched asynchronously from the network.
  • Debugging and tracing tools.

Volley cache example steps:

1.Create new project.

2.add volley.jar in your libs.clickhere to download vollery.jar.

3.Create AppController.java Singleton class where we initialize all the volley core libs.


public class AppController extends Application {
    public static final String TAG = AppController.class.getSimpleName();
    private RequestQueue mRequestQueue;
    private static AppController mInstance;
    @Override
    public void onCreate() {
        super.onCreate();
        mInstance = this;
    }
    public static synchronized AppController getInstance() {
        return mInstance;
    }
    public RequestQueue getRequestQueue() {
        if (mRequestQueue == null) {
            mRequestQueue = Volley.newRequestQueue(getApplicationContext());
        }
        return mRequestQueue;
    }
    public <T> void addToRequestQueue(Request<T> req, String tag) {
        req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
        getRequestQueue().add(req);
    }
    public <T> void addToRequestQueue(Request<T> req) {
        req.setTag(TAG);
        getRequestQueue().add(req);
    }
    public void cancelPendingRequests(Object tag) {
        if (mRequestQueue != null) {
            mRequestQueue.cancelAll(tag);
        }
    }
}

4.add the AppController.java into the Application tag in manifest.xml to execute this at app launch.and also add internet permission.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.volleycacheexample"
    android:versionCode="1"
    android:versionName="1.0" >
    <uses-sdk
        android:minSdkVersion="14"
        android:targetSdkVersion="14" />
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.WRITE_SETTINGS"/>
    <application
        android:name="com.example.volleycacheexample.AppController"
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

5.Create MainActivity layout for call  json array request and set the response in the listview.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/LinearLayout1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity" >
    <Button
        android:id="@+id/btnClearCache"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#000000"
        android:textColor="#FFFFFF"
        android:padding="5dp"
        android:text="@string/clear_cache" />
    <ListView
        android:id="@+id/listview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >
    </ListView>
</LinearLayout>

6.get the json array requst URL.
Here I am using follow URL.
Json Array request URL:
private String jsonArrayUrl=
"http://www.androidtoppers.com/VolleyExample/ws_API/get_array.php";
Response:
[
{
"id": "1",
"Name": "Bentley",
"image": "http://www.androidtoppers.com/photos/webservice/image1.jpg",
"dec": "Car 1"
},
{
"id": "2",
"Name": "Bentley",
"image": "http://www.androidtoppers.com/photos/webservice/image2.jpg",
"dec": "car 2"
},
{
"id": "4",
"Name": "Bentley",
"image": "http://www.androidtoppers.com/photos/webservice/image3.jpg",
"dec": "car 3 "
},
{
"id": "6",
"Name": "Bentley",
"image": "http://www.androidtoppers.com/photos/webservice/image4.jpg",
"dec": "car 4"
},
{
"id": "7",
"Name": "BMW",
"image": "http://www.androidtoppers.com/photos/webservice/image5.jpg",
"dec": "Car 5"
},
{
"id": "10",
"Name": "BMW",
"image": "http://www.androidtoppers.com/photos/webservice/image6.jpg",
"dec": "car 6"
},
{
"id": "11",
"Name": "BMW",
"image": "http://www.androidtoppers.com/photos/webservice/image7.jpg",
"dec": "car 7"
},
{
"id": "12",
"Name": "BMW",
"image": "http://www.androidtoppers.com/photos/webservice/image8.jpg",
"dec": "car 8"
}
]

7.Call the jsonArrayRequest() in the onCreate of the MainActivity and get the response.
private void callJsonArrayRequest() {
// TODO Auto-generated method stub
showDialog();
JsonArrayRequest jsonarrayReq = new JsonArrayRequest(jsonArrayUrl,
new Response.Listener<JSONArray>() {
@Override
public void onResponse(JSONArray response) {
setData(response,false);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d(TAG, "Error: " + error.getMessage());
Toast.makeText(getApplicationContext(),
error.getMessage(), Toast.LENGTH_SHORT).show();
dismissDialog();
}
});
// Adding request to request queue
AppController.getInstance().addToRequestQueue(jsonarrayReq);
}


Set the response into the adapter.
private class ListAdapter extends BaseAdapter{
private LayoutInflater inflater;
@Override
public int getCount() {
// TODO Auto-generated method stub
return listModel.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return listModel.get(position);
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public View getView(int position, View view, ViewGroup parent) {
// TODO Auto-generated method stub
if(inflater==null)
inflater=(LayoutInflater)getLayoutInflater();
if(view==null)
view=inflater.inflate(R.layout.list_item, null);
TextView nameTv=(TextView)view.findViewById(R.id.name);
TextView imageTv=(TextView)view.findViewById(R.id.url);
ListModel listmodel=listModel.get(position);
nameTv.setText(listmodel.getName());
imageTv.setText(listmodel.getImage());
return view;
}
}
finally add the request url to the requestQueue,

AppController.getInstance().addToRequestQueue(jsonarrayReq);

Handling volley cache:
If you want to cache the response of the particular API .You can use the following method to cache the response for the feature use in volley.
Cache cache = AppController.getInstance().getRequestQueue().getCache();
Entry entry = cache.get(jsonArrayUrl);
if(entry != null){
//Cache data available.
try {
String data = new String(entry.data, "UTF-8");
Log.d("CACHE DATA", data);
JSONArray jsonArray=new JSONArray(data);
setData(jsonArray,true);
Toast.makeText(getApplicationContext(), "Loading from cache.", Toast.LENGTH_SHORT).show();
}
catch (UnsupportedEncodingException e) {      
e.printStackTrace();
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else{
// Cache data not exist.
callJsonArrayRequest();
}
the full code of mainactivity is,

MainActivity.java
public class MainActivity extends Activity {
private ListView listview;
private ProgressDialog mdialog;
private String jsonArrayUrl="http://www.androidtoppers.com/VolleyExample/ws_API/get_array.php";
private static String TAG = MainActivity.class.getSimpleName();
private List<ListModel> listModel=new ArrayList<ListModel>();
private ListAdapter adapter;
private Button btnClearCache;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// TODO Auto-generated method stub
listview=(ListView)findViewById(R.id.listview);
btnClearCache=(Button)findViewById(R.id.btnClearCache);
adapter =new ListAdapter();
listview.setAdapter(adapter);
//set progressbar
mdialog=new ProgressDialog(this);
mdialog.setMessage("Loading..");
mdialog.setCancelable(false);
btnClearCache.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
AppController.getInstance().getRequestQueue().getCache().remove(jsonArrayUrl);
Toast.makeText(getApplicationContext(), "Cache cleared.", Toast.LENGTH_SHORT).show();
}
});
Cache cache = AppController.getInstance().getRequestQueue().getCache();
Entry entry = cache.get(jsonArrayUrl);
if(entry != null){
//Cache data available.
try {
String data = new String(entry.data, "UTF-8");
Log.d("CACHE DATA", data);
JSONArray jsonArray=new JSONArray(data);
setData(jsonArray,true);
Toast.makeText(getApplicationContext(), "Loading from cache.", Toast.LENGTH_SHORT).show();
}
catch (UnsupportedEncodingException e) {      
e.printStackTrace();
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else{
// Cache data not exist.
callJsonArrayRequest();
}
}
private void callJsonArrayRequest() {
// TODO Auto-generated method stub
showDialog();
JsonArrayRequest jsonarrayReq = new JsonArrayRequest(jsonArrayUrl,
new Response.Listener<JSONArray>() {
@Override
public void onResponse(JSONArray response) {
setData(response,false);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d(TAG, "Error: " + error.getMessage());
Toast.makeText(getApplicationContext(),
error.getMessage(), Toast.LENGTH_SHORT).show();
dismissDialog();
}
});
// Adding request to request queue
AppController.getInstance().addToRequestQueue(jsonarrayReq);
}
private class ListAdapter extends BaseAdapter{
private LayoutInflater inflater;
@Override
public int getCount() {
// TODO Auto-generated method stub
return listModel.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return listModel.get(position);
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public View getView(int position, View view, ViewGroup parent) {
// TODO Auto-generated method stub
if(inflater==null)
inflater=(LayoutInflater)getLayoutInflater();
if(view==null)
view=inflater.inflate(R.layout.list_item, null);
TextView nameTv=(TextView)view.findViewById(R.id.name);
TextView imageTv=(TextView)view.findViewById(R.id.url);
ListModel listmodel=listModel.get(position);
nameTv.setText(listmodel.getName());
imageTv.setText(listmodel.getImage());
return view;
}
}
private void setData(JSONArray response,Boolean isCache){
Log.d(TAG, response.toString());
try {
for (int i = 0; i < response.length(); i++) {
JSONObject person = (JSONObject) response.get(i);
ListModel model=new ListModel();
model.setName(person.getString("Name"));
model.setImage(person.getString("image"));
listModel.add(model);
}
} catch (JSONException e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(),"Error: " + e.getMessage(),Toast.LENGTH_LONG).show();
}
adapter.notifyDataSetChanged();
if(!isCache){
Toast.makeText(getApplicationContext(), "Cache not available..Loading from service", Toast.LENGTH_SHORT).show();
dismissDialog();
}
}
private class ListModel{
private String name;
private String image;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
}
private void dismissDialog() {
// TODO Auto-generated method stub
if(mdialog.isShowing()){
mdialog.dismiss();
}
}
private void showDialog() {
// TODO Auto-generated method stub
if(!mdialog.isShowing()){
mdialog.show();
}
}
}

Clear cache from volley:
if you want to clear the cache for the particular URL in volley you can use this code to do that,
AppController.getInstance().getRequestQueue().getCache().remove(URL);

Clear all the cache in volley:
Use this code to delete all the URL cache in volley.
AppController.getInstance().getRequestQueue().getCache().clear(url);

Invalidate cache from volley:
In this method used to invalidate the cache of the API.that means when the changes added in the API response the cache will updated to latest response.
AppController.getInstance().getRequestQueue().getCache().invalidate(url,true);

Turning off cache for volley:
You can also turning off the cache for the particular API response using the following code.
/ String reqest
StringRequest stringReq = new StringRequest(....);
// disable cache

stringReq.setShouldCache(false);

Cancel single request in volley:
You can cancel the request using the tag name of the request.
String json_array_tag="tag_name";
ApplicationController.getInstance().getRequestQueue().cancelAll("tag_name");

Cancel all request in volley:
Use this code to cancel all the request.
sApplicationController.getInstance().getRequestQueue().cancelAll();
Screenshot:

2 comments:

sumit kumawat said...

thank u sir its really awesome tutorial to manage cache in volly

sumit kumawat said...

but how to load images in listview....after got url