11

Tôi cố gắng để thực hiện AlphabetIndexer với Custom Adaptor như thế nàyAlphabetIndexer với Custom Adaptor quản lý bởi LoaderManager

AlphabetIndexer with Custom Adapter

lớp ContactsCursorAdapter My mở rộng SimpleCursorAdapter và thực hiện SectionIndexer và tôi đang sử dụng một LoaderManager để quản lý con trỏ bộ chuyển đổi của tôi vì vậy tôi đã ghi đè phương thức swapCursor() như câu trả lời thứ hai cho ví dụ ở trên cho biết.

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); 
    } 
} 

Tuy nhiên, điều này ra lỗi nếu tôi đặt listview của tôi để fastScrollEnabled = true

getListView() setFastScrollEnabled (true).

trong lớp của tôi ContactsCursorLoaderListPhân tích mở rộng ListFragment và triển khai LoaderManager.LoaderCallbacks.

Đây là stack trace:

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 

sau khi phương pháp setFastScrollEnabled() được gọi nó gọi phương pháp adapter tùy chỉnh của getSections() đó là nơi nó bị treo.

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); 
     } 

    } 
} 

Và nếu tôi nhận xét các setFastScrollEnabled() cuộc gọi, sau đó nó không lôi ra, nhưng tôi không thấy AlphabetIndexer làm việc.

Điều này có cần phải được triển khai khác nhau do bộ điều hợp tùy chỉnh của tôi được đặt trong một số ListFragment chứ không phải là ListActivity?

Có ai có đề xuất về cách làm cho tất cả điều này hoạt động không?

Trả lời

9

Vì vậy, cuối cùng tôi đã làm việc này. Đây là cách tôi đã làm nó:

Tôi nói thêm:

ListView lv = getListView(); 
lv.setFastScrollEnabled(true); 
lv.setScrollingCacheEnabled(true); 

với phương pháp onLoadFinished() sau con trỏ mới được đổi chỗ ở như vậy

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); 

} 

do đó những ba tuyên bố đã được gỡ bỏ từ phương pháp onActivityCreated() của tùy chỉnh của tôi ListFragment.

+0

Bắt tốt. Cảm ơn. – nobre

+0

Sẽ không tốt hơn nếu chỉ làm cho phương thức 'getSections' của bạn trả về một danh sách trống nếu không có dữ liệu thay vì ném một ngoại lệ con trỏ null? –

+0

Có một ý tưởng hay là trả về một danh sách trống nếu dữ liệu không có sẵn, tuy nhiên getSections() nên được gọi sau khi con trỏ được đổi chỗ vì nó đang thực hiện một CursorLoader. – toobsco42

Các vấn đề liên quan