2015-01-09 3 views
1

I пользователь LoaderManager и CursorLoader загружают данные из моей базы данных с помощью ContentProvider. Теперь начальная загрузка прекрасна. У меня есть ListView, который отображает все строки из БД (только имена - String адаптер).Обновить загрузчик при изменении данных - android

Теперь, когда я добавляю/удаляю строку из базы данных, я хочу обновить ListView, чтобы отобразить последние изменения.

В настоящее время я просто перезагружаю загрузчик с помощью метода «restartLoader» всякий раз, когда происходит изменение, но я хочу спросить, есть ли другой способ сделать это без перезапуска загрузчика.

Это мой класс занятия: package com.silverfix.phony.activities;

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<Cursor>{ 

    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<String> adapter; 
    private ArrayList<String> 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<String>(); 
     adapter = new ArrayAdapter<String>(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<?> 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<Cursor> 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<Cursor> loader, Cursor data) { 
     swapCursor(data); 
    } 

    @Override 
    public void onLoaderReset(Loader<Cursor> 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(); 
    } 
} 

ответ

2

Поскольку у вас уже есть доступ к загрузчику, вы не можете ожидать, что много изменений, но другой способ реализации этого является наличие настройки PhonyContentProvider.RINGTONES_URI в качестве уведомления URI курсор и уведомления Ури когда это изменения базы данных.

Соответствующие методы:
setNotificationUri
notifyChange

+0

Большое спасибо! –

+0

Это работает только для CursorLoader, который использует данные ContentProvider, зарегистрированные для изменений уведомлений. Для других видов погрузчиков это не работает! –