Update A ListView With Data From Web Service Using Content Provider

This is a simple Android to demonstrate how to fetch data from a Web Service, save it to a SQlite Database, then use Content Provider to update the ListView with that data. This involves a buffet of Android components and represents just one way to accomplish this and not necessarily the best way. This program is an assignment for a gradute class I am taking at Regis University and the assignment is to implement the following design pattern.

Github link

So from the above the diagram, the following need to be accomplished

  1. The Activity (or Fragment) initializes a LoaderManager with a CursorLoader that references a Content Provider where the CursorLoader runs in a background theread
  2. The Content Provider makes the Web service request, updates the backing SQlite database
  3. Updates the UI

Because of other constraints ( the need for a Navigation Drawer), I am using a Fragment instead of an Activity and I am using the Support Library for backward compatibility. The name of my Fragment is ProgramsListFragment.Java and here is the highlights of the code. I have provided a link to the Github page of the source code. It is recommended that you follow the official tutorial of the Content Provider and the Loader API if you have not done so already.

  1. First, this Fragment has to implement the LoaderCallbacks
  2. Then, I define a Projection, which is a String array of the columns I want to fetch using the Content Provider, in my case, all I want to display is list of University programs
  3. Create a SimpleCursorAdapter which will be used to bind data from the Content Provider to the listView, by the way my Fragment is a ListFragment
  4. In the OnCreateView, I initialize the adapter and set the data source to null since the Content Provider is not ready yet.
  5. I set the empty adapter as the adapter for this ListView using the Fragments setListAdapter() method, if you run the application it will run but will show a blank screen.
  6. Then comes the moment of multiple abstractions – I call the getLoaderManager since to get a reference to the. Loader Framework, initialize the Loader, which then calls the onCreateLoader() method, which then creates an instance of my Content Provider, which creates the database, etc we will come back to the Content Provider in a moment
  7. When the above method call completes, the LoaderManager then calls the onLoadFinished() method and in this method, I have to update the adapter by removing the null datasource that I passed in above and then supply the CursorLoader object returned from the onCreateLoader() method call above
    public class ProgramsListFragment extends ListFragment
    		implements LoaderCallbacks{
        private static final String[] PROJECTION = new String[] {
        SimpleCursorAdapter mAdapter;       
    	public void onCreate(Bundle savedInstanceState) {
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            View rootView = inflater.inflate(R.layout.fragment_programs_list, container, false);         
            //create a blank adapter
            mAdapter = new SimpleCursorAdapter(getActivity(), 
            		R.layout.row, null,
            		new String[] {Provider.Programs.NAME}, 
            		new int[] {R.id.name},0);       
           getLoaderManager().initLoader(0, null,this);           
            return rootView;
       	public void onLoadFinished(Loader loader, Cursor cursor) {
       	public void onLoaderReset(Loader loader){
    	public Loader onCreateLoader(int loaderId, Bundle arg) {
    		return (new CursorLoader(getActivity(), Provider.Programs.CONTENT_URI,
    				PROJECTION, null, null, null));

If the data for the Content Provider is coming only from the database, this content should display if you run the application now, however I have added another complexity which is that the data is coming from a REST web service.

The web service in question here is a server at Regis University that just returns a list of Computer related programs. I had a stand alone service that calls this Web Service and returns a JSONArray, however I could not figure out how to start this service from within my Provider class, so I ended up calling the web service from within my Provider class, I know it may not be the best approach but that is what worked for me for now.
The highlights of the Provider class

My Provider class extends Content Provider and I have put it in different package

  1. I created an AsyncTask that makes the Web Service call in the background
  2. In the onPostExecute method of the AsyncTask, I call the insert method of my Content Provider to insert the returned data from the Web Service call to the database.
  3. Very important, once I finish parsing the returned JSON data from the Web Service, I call the. ContentResolver.notifyChange to update the UI, otherwise the ListView will still be blank
  4. In the OnCreate() method of the Content Provider, I start the asyncTask
  5. Also in the onCreate(), I create an instance of my DBHelper class
  6. In the query method, I query the database and return the data. At first the database will be blank, because the web service request and writing to database is slow, so the query runs before the database has any data, which is why it is important to call the ContentResolver.notifiy changes
    public Uri insert(Uri url, ContentValues initialValues) {
    dbhelper.getWritableDatabase().insert(TABLE, Programs.NAME, initialValues);
    return url;
    public boolean onCreate() {
    dbhelper = new LocalDatabase(getContext());
    return((dbhelper == null) ? false : true);
    public Cursor query(Uri url, String[] projection, String selection, String[] selectionArgs,
    String sort) {
    SQLiteQueryBuilder qb=new SQLiteQueryBuilder();
    String orderBy;
    if (TextUtils.isEmpty(sort)) {
    else {
    Cursor c=
    qb.query(dbhelper.getReadableDatabase(), new String[]{"_id", "name"}, selection,
    selectionArgs, null, null, orderBy);
    c.setNotificationUri(getContext().getContentResolver(), url);
    public int update(Uri arg0, ContentValues arg1, String arg2, String[] arg3) {
    // TODO Auto-generated method stub
    return 0;
    private void startWebService(){
    HttpAsyncTask asyncTask = new HttpAsyncTask();
    //class that extents AsyncTask class
    class HttpAsyncTask extends AsyncTask<String, String, String>{
    protected String doInBackground(String... args) {
    Log.i("HttpAsyncTask", "start doinbackground");
    String result = "";
    HttpClient client = new DefaultHttpClient();
    String url = "http://regisscis.net/Regis2/webresources/regis2.program";
    HttpGet httpGet = new HttpGet(url);
    httpGet.setHeader("Accept", "application/json");
    try {
    HttpResponse response = client.execute(httpGet);
    InputStream inputStream = response.getEntity().getContent();
    BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
    String s = "";
    while ((s = reader.readLine()) != null) {
    result += s;
    } catch (Exception e) {
    Log.i("HttpAsyncTask", "EXCEPTION: " + e.getMessage());
    Log.i("HttpAsyncTask", "Returned string : " + result);
    return result;
    protected void onPostExecute(String result) {
    ContentValues values = new ContentValues();
    try {
    JSONArray jsonArray = new JSONArray(result);
    int lenght = jsonArray.length();
    for (int i = 0; i < jsonArray.length(); i++) {
    JSONObject jsonObject = jsonArray.getJSONObject(i);
    String name = jsonObject.getString("name");
    values.put(Programs.NAME, name);
    insert(Programs.CONTENT_URI, values);
    Log.i("Data Changed", "Data changed " + lenght);
    getContext().getContentResolver().notifyChange(Programs.CONTENT_URI, null);
    } catch (JSONException e) {

Github link is https://github.com/ProntoCast/RegisSCICAppGithub link
That it, this works but requires some work to make it better, for example the Web service keeps supplying new data.


About the Author valokafor

I am a Software Engineer with expertise in Android Development. I am available for Android development projects.

follow me on:

Leave a Comment: