title: Refresh a Loader when data is changed - android
body: <p>I user LoaderManager and CursorLoader to load the data from my database using a ContentProvider.
  Now, the initial load is fine. I have a ListView that display all the rows from the DB(only the names-String adapter).</p>
  
  <p>Now, when I add/delete a row from the database, I want to refresh the ListView so it will display the recent changes.</p>
  
  <p>Currently I just restart the loader with the method "restartLoader" whenever a change is commited but I want to ask if there is another way of doing this without restarting the loader.</p>
  
  <p>Here is my activity class code:
  package com.silverfix.phony.activities;</p>
  
  <pre><code>import java.util.ArrayList;
  
  import com.silverfix.phony.R;
  import com.silverfix.phony.contentprovider.PhonyContentProvider;
  import com.silverfix.phony.database.RingtonesTable;
  
  import android.app.Activity;
  import android.app.LoaderManager.LoaderCallbacks;
  import android.content.ContentValues;
  import android.content.CursorLoader;
  import android.content.Intent;
  import android.content.Loader;
  import android.database.Cursor;
  import android.net.Uri;
  import android.os.Bundle;
  import android.provider.MediaStore;
  import android.text.Editable;
  import android.view.ContextMenu;
  import android.view.Menu;
  import android.view.MenuItem;
  import android.view.View;
  import android.view.ContextMenu.ContextMenuInfo;
  import android.view.View.OnClickListener;
  import android.view.View.OnCreateContextMenuListener;
  import android.widget.AdapterView;
  import android.widget.AdapterView.AdapterContextMenuInfo;
  import android.widget.AdapterView.OnItemClickListener;
  import android.widget.ArrayAdapter;
  import android.widget.Button;
  import android.widget.ListView;
  import android.widget.Toast;
  
  public class RingtonesActivity extends Activity implements LoaderCallbacks&lt;Cursor&gt;{
  
      private final int PICK_RINGTONE_CODE = 1;
      private final int CURSOR_LOADER_ID = 1;
      private final int EDIT_ID = 1;
      private final int DELETE_ID = 2;
      private String[] ContextCommands;
      private ArrayAdapter&lt;String&gt; adapter;
      private ArrayList&lt;String&gt; ringtones;
      private ListView listview;
  
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_ringtones);
          listview = (ListView) findViewById(R.id.list);
          Button add = (Button) findViewById(R.id.add_ringtone);
          add.setOnClickListener(new OnClickListener() {
  
              @Override
              public void onClick(View v) {
                  Intent i = new Intent(
                          Intent.ACTION_PICK,
                          android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI);
                  startActivityForResult(i, PICK_RINGTONE_CODE);
              }
          });
          fillData();
      }
  
      @Override
      protected void onActivityResult(int arg0, int arg1, Intent arg2) {
          super.onActivityResult(arg0, arg1, arg2);
          switch (arg0) {
          case 1: // PICK_RINGTONE_CODE
              if (arg1 == RESULT_OK) {
                  Uri ringtoneURI = arg2.getData();
                  String[] projection = { MediaStore.MediaColumns.DISPLAY_NAME };
                  Cursor cursor = getContentResolver().query(ringtoneURI,
                          projection, null, null, null);
                  cursor.moveToFirst();
                  int column = cursor
                          .getColumnIndex(MediaStore.MediaColumns.DISPLAY_NAME);
                  String displayName = cursor.getString(column);
                  addRingtone(ringtoneURI, displayName);
                  cursor.close();
              }
          }
      }
  
      @Override
      public boolean onCreateOptionsMenu(Menu menu) {
          getMenuInflater().inflate(R.menu.ringtones, menu);
          return true;
      }
  
      @Override
      public boolean onOptionsItemSelected(MenuItem item) {
          int id = item.getItemId();
          if (id == R.id.action_settings) {
              return true;
          }
          return super.onOptionsItemSelected(item);
      }
  
      private void fillData() {
          getLoaderManager().initLoader(CURSOR_LOADER_ID, null, this);
          ringtones = new ArrayList&lt;String&gt;();
          adapter = new ArrayAdapter&lt;String&gt;(this,
                  android.R.layout.simple_list_item_1, ringtones);
          ContextCommands = getResources().getStringArray(R.array.commands);
          listview.setAdapter(adapter);
          listview.setOnItemClickListener(new OnItemClickListener() {
  
              @Override
              public void onItemClick(AdapterView&lt;?&gt; parent, View view,
                      int position, long id) {
                  editRingtone();
              }
          });
          registerForContextMenu(listview);
          listview.setOnCreateContextMenuListener(new OnCreateContextMenuListener() {
  
              @Override
              public void onCreateContextMenu(ContextMenu menu, View v,
                      ContextMenuInfo menuInfo) {
                  if (v.getId()==R.id.list) {
                      AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)menuInfo;
                      menu.setHeaderTitle(ContextCommands[info.position]);
                      String[] menuItems = getResources().getStringArray(R.array.commands);
                      menu.add(Menu.NONE, EDIT_ID, 0, menuItems[0]);
                      menu.add(Menu.NONE, DELETE_ID, 0, menuItems[1]);
                    }
              }
          });
      }
  
      @Override
      public boolean onContextItemSelected(MenuItem item) {
          switch(item.getItemId()) {
          case EDIT_ID:
              editRingtone();
              return true;
          case DELETE_ID:
              String name = adapter.getItem(((AdapterContextMenuInfo) item.getMenuInfo()).position);
              getContentResolver().delete(PhonyContentProvider.RINGTONES_URI, RingtonesTable.COLUMN_NAME
                      + "='" + name + "'", null);
              return true;
          default:
              return super.onContextItemSelected(item);
          }
      }
  
      private void editRingtone() {
          Intent i = new Intent(
                  Intent.ACTION_PICK,
                  android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI);
          startActivityForResult(i, PICK_RINGTONE_CODE);
      }
  
      private void addRingtone(Uri uri, String name) {
          String[] projection = { RingtonesTable.COLUMN_NAME };
          Cursor cursor = getContentResolver().query(
                  PhonyContentProvider.RINGTONES_URI, projection,
                  RingtonesTable.COLUMN_NAME + "='"+name+"'", null, null);
          if (cursor.getCount() == 0) {
              ContentValues values = new ContentValues();
              values.put(RingtonesTable.COLUMN_NAME, name);
              values.put(RingtonesTable.COLUMN_URI, uri.toString());
              getContentResolver().insert(PhonyContentProvider.RINGTONES_URI,
                      values);
              getLoaderManager().restartLoader(CURSOR_LOADER_ID, null, this);
          } else {
              Toast.makeText(this, "You already picked that ringtone!",
                      Toast.LENGTH_LONG).show();
              cursor.close();
          }
      }
  
      @Override
      public Loader&lt;Cursor&gt; onCreateLoader(int id, Bundle args) {
          String[] projection = {RingtonesTable.COLUMN_ID, RingtonesTable.COLUMN_NAME, RingtonesTable.COLUMN_URI};
          return new CursorLoader(this, PhonyContentProvider.RINGTONES_URI, projection, null, null, null);
      }
  
      @Override
      public void onLoadFinished(Loader&lt;Cursor&gt; loader, Cursor data) {
          swapCursor(data);
      }
  
      @Override
      public void onLoaderReset(Loader&lt;Cursor&gt; loader) {
          swapCursor(null);
      }
  
      private void swapCursor(Cursor cursor) {
          if(cursor != null) {
              cursor.moveToFirst();
              ringtones.clear();
              for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
                  int column = cursor.getColumnIndex(RingtonesTable.COLUMN_NAME);
                  ringtones.add(cursor.getString(column));
              }
              adapter.notifyDataSetChanged();
              cursor.close();
              return;
          }
          ringtones.clear();
          adapter.notifyDataSetChanged();
      }
  }
  </code></pre>