AlphabetIndexer con adaptador personalizado administrado por LoaderManager
Estoy tratando de implementar AlphabetIndexer
con adaptador personalizado como este
AlphabetIndexer con adaptador personalizado
- Actualizar SimpleCursorAdapter mientras mantiene la posición de desplazamiento en ListView
- Enfoque para rellenar la vista de lista expandible con la base de datos SQlite local
- SimpleCursorAdapter obsoleto en la versión 15 de la API?
- Android - Obtención de la lista de contactos con direcciones de calle, pero no con valores bajos como Skype, donde la dirección es sólo una ciudad y un estado
- Android, usando SimpleCursorAdapter para establecer el color no sólo las cadenas
Mi clase ContactsCursorAdapter extiende SimpleCursorAdapter
e implementa SectionIndexer
y estoy usando un LoaderManager
para manejar el cursor de mi adaptador así que he sobrepasado el método swapCursor()
como la segunda respuesta al ejemplo anterior indica.
public class ContactsCursorAdapter extends SimpleCursorAdapter implements SectionIndexer{ private LayoutInflater mInflater; private Context mContext; private AlphabetIndexer mAlphaIndexer; public ContactsCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to) { super(context, layout, c, from, to); mInflater = LayoutInflater.from(context); mContext = context; } public View getView(final int position, View convertView, ViewGroup parent) { ... } @Override public int getPositionForSection(int section) { return mAlphaIndexer.getPositionForSection(section); } @Override public int getSectionForPosition(int position) { return mAlphaIndexer.getSectionForPosition(position); } @Override public Object[] getSections() { return mAlphaIndexer.getSections(); } public Cursor swapCursor(Cursor c) { // Create our indexer if (c != null) { mAlphaIndexer = new AlphabetIndexer(c, c.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME), " ABCDEFGHIJKLMNOPQRSTUVWXYZ"); } return super.swapCursor(c); } }
Sin embargo, este error si establezco mi listview a fastScrollEnabled = true
GetListView (). SetFastScrollEnabled (true);
En mi clase ContactsCursorLoaderListFragment que extiende ListFragment
e implementa LoaderManager.LoaderCallbacks.
Aquí está el rastreo de la pila:
04-25 01:37:23.280: E/AndroidRuntime(711): FATAL EXCEPTION: main 04-25 01:37:23.280: E/AndroidRuntime(711): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.sendit/com.sendit.ContactManager}: java.lang.NullPointerException 04-25 01:37:23.280: E/AndroidRuntime(711): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1956) 04-25 01:37:23.280: E/AndroidRuntime(711): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1981) 04-25 01:37:23.280: E/AndroidRuntime(711): at android.app.ActivityThread.access$600(ActivityThread.java:123) 04-25 01:37:23.280: E/AndroidRuntime(711): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1147) 04-25 01:37:23.280: E/AndroidRuntime(711): at android.os.Handler.dispatchMessage(Handler.java:99) 04-25 01:37:23.280: E/AndroidRuntime(711): at android.os.Looper.loop(Looper.java:137) 04-25 01:37:23.280: E/AndroidRuntime(711): at android.app.ActivityThread.main(ActivityThread.java:4424) 04-25 01:37:23.280: E/AndroidRuntime(711): at java.lang.reflect.Method.invokeNative(Native Method) 04-25 01:37:23.280: E/AndroidRuntime(711): at java.lang.reflect.Method.invoke(Method.java:511) 04-25 01:37:23.280: E/AndroidRuntime(711): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784) 04-25 01:37:23.280: E/AndroidRuntime(711): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551) 04-25 01:37:23.280: E/AndroidRuntime(711): at dalvik.system.NativeStart.main(Native Method) 04-25 01:37:23.280: E/AndroidRuntime(711): Caused by: java.lang.NullPointerException 04-25 01:37:23.280: E/AndroidRuntime(711): at com.sendit.ContactsCursorAdapter.getSections(ContactsCursorAdapter.java:222) 04-25 01:37:23.280: E/AndroidRuntime(711): at android.widget.FastScroller.getSectionsFromIndexer(FastScroller.java:507) 04-25 01:37:23.280: E/AndroidRuntime(711): at android.widget.FastScroller.init(FastScroller.java:269) 04-25 01:37:23.280: E/AndroidRuntime(711): at android.widget.FastScroller.<init>(FastScroller.java:155) 04-25 01:37:23.280: E/AndroidRuntime(711): at android.widget.AbsListView.setFastScrollEnabled(AbsListView.java:1144) 04-25 01:37:23.280: E/AndroidRuntime(711): at com.sendit.LoaderCursor$ContactsCursorLoaderListFragment.onActivityCreated(LoaderCursor.java:107) 04-25 01:37:23.280: E/AndroidRuntime(711): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:847) 04-25 01:37:23.280: E/AndroidRuntime(711): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1032) 04-25 01:37:23.280: E/AndroidRuntime(711): at android.app.BackStackRecord.run(BackStackRecord.java:622) 04-25 01:37:23.280: E/AndroidRuntime(711): at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1382) 04-25 01:37:23.280: E/AndroidRuntime(711): at android.app.Activity.performStart(Activity.java:4474) 04-25 01:37:23.280: E/AndroidRuntime(711): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1929) 04-25 01:37:23.280: E/AndroidRuntime(711): ... 11 more
Después de que el método setFastScrollEnabled()
se llama, llama al método getSections()
del adaptador personalizado, que es donde se bloquea.
public class LoaderCursor extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); FragmentManager fm = getFragmentManager(); // Create the list fragment and add it as our sole content. if (fm.findFragmentById(android.R.id.content) == null) { ContactsCursorLoaderListFragment list = new ContactsCursorLoaderListFragment(); fm.beginTransaction().add(android.R.id.content, list).commit(); } } public static class ContactsCursorLoaderListFragment extends ListFragment implements LoaderManager.LoaderCallbacks<Cursor> { ContactsCursorAdapter mAdapter; Cursor mCursor; String mCurFilter; @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); populateContactList(); // Prepare the loader. Either re-connect with an existing one, // or start a new one. getLoaderManager().initLoader(0, null, this); ListView lv = getListView(); lv.setFastScrollEnabled(true); //lv.setScrollingCacheEnabled(true); lv.setDivider(getResources().getDrawable(R.drawable.list_divider)); } // These are the Contacts rows that we will retrieve. final String[] CONTACTS_SUMMARY_PROJECTION = new String[] { ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME, ContactsContract.Contacts.PHOTO_ID, }; public Loader<Cursor> onCreateLoader(int id, Bundle args) { // This is called when a new Loader needs to be created. This // sample only has one Loader, so we don't care about the ID. // First, pick the base URI to use depending on whether we are // currently filtering. Uri baseUri; if (mCurFilter != null) { baseUri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_FILTER_URI,Uri.encode(mCurFilter)); } else { baseUri = ContactsContract.Contacts.CONTENT_URI; } // Now create and return a CursorLoader that will take care of // creating a Cursor for the data being displayed. String selection = "((" + ContactsContract.Contacts.DISPLAY_NAME + " NOTNULL) AND (" + ContactsContract.Contacts.HAS_PHONE_NUMBER + "=1) AND (" + ContactsContract.Contacts.DISPLAY_NAME + " != '' ))"; String sortOrder = ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"; return new CursorLoader(getActivity(), baseUri, CONTACTS_SUMMARY_PROJECTION, selection, null, sortOrder); } public void onLoadFinished(Loader<Cursor> loader, Cursor data) { // Swap the new cursor in. (The framework will take care of closing the // old cursor once we return.) mAdapter.swapCursor(data); } public void onLoaderReset(Loader<Cursor> loader) { // This is called when the last Cursor provided to onLoadFinished() // above is about to be closed. We need to make sure we are no // longer using it. mAdapter.swapCursor(null); } /** * Populate the contact list */ private void populateContactList() { // start mappings String[] from = new String[] { ContactsContract.Contacts.DISPLAY_NAME }; int[] to = new int[] { R.id.contactInfo }; // Create an empty adapter we will use to display the loaded data. mAdapter = new ContactsCursorAdapter(getActivity().getApplicationContext(), R.layout.contact_manager, null, from, to); setListAdapter(mAdapter); } } }
Y si comento la llamada de setFastScrollEnabled()
, entonces no hace error hacia fuera, pero no veo el funcionamiento de AlphabetIndexer
.
¿Es necesario implementar esto de forma diferente porque mi adaptador personalizado se establece en un ListFragment
y no en ListActivity
?
¿Alguien tiene sugerencias sobre cómo hacer que todo esto funcione?
- ¿Qué bandera usar en SimpleCursorAdapter?
- Cómo obtener datos de Cursor en ContextMenu
- Cursor se desactiva antes de llamar a este método
- SimpleCursorAdapter y CursorAdapter
- Cómo solucionar esto sólo se debe llamar cuando el cursor es válido utilizando ExpandableListView
- Cómo establecer onClick escucha de un ImageButton en ViewBinder?
- ListView no se actualiza al agregar a SQLiteDatabase
- El constructor SimpleCursorAdapter (Context, int, Cursor, String , int ) está obsoleto
Así que finalmente conseguí esto para trabajar. Aquí es cómo lo hice:
Yo añadí:
ListView lv = getListView(); lv.setFastScrollEnabled(true); lv.setScrollingCacheEnabled(true);
onLoadFinished()
método onLoadFinished()
después de que el nuevo cursor se cambió de forma similar
public void onLoadFinished(Loader<Cursor> loader, Cursor data) { // Swap the new cursor in. (The framework will take care of closing the // old cursor once we return.) mAdapter.swapCursor(data); ListView lv = getListView(); lv.setFastScrollEnabled(true); lv.setScrollingCacheEnabled(true); }
En consecuencia, estas tres instrucciones se eliminaron del método onActivityCreated()
de mi ListFragment
personalizado.
- Android Studio ignorar –core-library flag
- Por qué la clave Api de Google map necesita cambiar frecuentemente