|
Android example source code file (AlphabetIndexer.java)
The AlphabetIndexer.java Android example source code/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package com.example.android.rings_extended; import android.database.Cursor; import android.database.DataSetObserver; import android.util.SparseIntArray; /** * This class essentially helps in building an index of section boundaries of a * sorted column of a cursor. For instance, if a cursor contains a data set * sorted by first name of a person or the title of a song, this class will * perform a binary search to identify the first row that begins with a * particular letter. The search is case-insensitive. The class caches the index * such that subsequent queries for the same letter will return right away. * * <p>This file was copied from the Contacts application. In the future it * should be provided as a standard part of the Android framework. */ public class AlphabetIndexer extends DataSetObserver { protected Cursor mDataCursor; protected int mColumnIndex; protected Object[] mAlphabetArray; private SparseIntArray mAlphaMap; private java.text.Collator mCollator; /** * Constructs the indexer. * @param cursor the cursor containing the data set * @param columnIndex the column number in the cursor that is sorted * alphabetically * @param sections the array of objects that represent the sections. The * toString() method of each item is called and the first letter of the * String is used as the letter to search for. */ public AlphabetIndexer(Cursor cursor, int columnIndex, Object[] sections) { mDataCursor = cursor; mColumnIndex = columnIndex; mAlphabetArray = sections; mAlphaMap = new SparseIntArray(26 /* Optimize for English */); if (cursor != null) { cursor.registerDataSetObserver(this); } // Get a Collator for the current locale for string comparisons. mCollator = java.text.Collator.getInstance(); mCollator.setStrength(java.text.Collator.PRIMARY); } /** * Sets a new cursor as the data set and resets the cache of indices. * @param cursor the new cursor to use as the data set */ public void setCursor(Cursor cursor) { if (mDataCursor != null) { mDataCursor.unregisterDataSetObserver(this); } mDataCursor = cursor; if (cursor != null) { mDataCursor.registerDataSetObserver(this); } mAlphaMap.clear(); } /** * Performs a binary search or cache lookup to find the first row that * matches a given section's starting letter. * @param sectionIndex the section to search for * @return the row index of the first occurrence, or the nearest next letter. * For instance, if searching for "T" and no "T" is found, then the first * row starting with "U" or any higher letter is returned. If there is no * data following "T" at all, then the list size is returned. */ public int indexOf(int sectionIndex) { final SparseIntArray alphaMap = mAlphaMap; final Cursor cursor = mDataCursor; if (cursor == null || mAlphabetArray == null) { return 0; } // Check bounds if (sectionIndex <= 0) { return 0; } if (sectionIndex >= mAlphabetArray.length) { sectionIndex = mAlphabetArray.length - 1; } int savedCursorPos = cursor.getPosition(); int count = cursor.getCount(); int start = 0; int end = count; int pos; String letter = mAlphabetArray[sectionIndex].toString(); letter = letter.toUpperCase(); int key = letter.charAt(0); // Check map if (Integer.MIN_VALUE != (pos = alphaMap.get(key, Integer.MIN_VALUE))) { // Is it approximate? Using negative value to indicate that it's // an approximation and positive value when it is the accurate // position. if (pos < 0) { pos = -pos; end = pos; } else { // Not approximate, this is the confirmed start of section, return it return pos; } } // Do we have the position of the previous section? if (sectionIndex > 0) { int prevLetter = mAlphabetArray[sectionIndex - 1].toString().charAt(0); int prevLetterPos = alphaMap.get(prevLetter, Integer.MIN_VALUE); if (prevLetterPos != Integer.MIN_VALUE) { start = Math.abs(prevLetterPos); } } // Now that we have a possibly optimized start and end, let's binary search pos = (end + start) / 2; while (pos < end) { // Get letter at pos cursor.moveToPosition(pos); String curName = cursor.getString(mColumnIndex); if (curName == null) { if (pos == 0) { break; } else { pos--; continue; } } int curLetter = Character.toUpperCase(curName.charAt(0)); if (curLetter != key) { // Enter approximation in hash if a better solution doesn't exist int curPos = alphaMap.get(curLetter, Integer.MIN_VALUE); if (curPos == Integer.MIN_VALUE || Math.abs(curPos) > pos) { // Negative pos indicates that it is an approximation alphaMap.put(curLetter, -pos); } if (mCollator.compare(curName, letter) < 0) { start = pos + 1; if (start >= count) { pos = count; break; } } else { end = pos; } } else { // They're the same, but that doesn't mean it's the start if (start == pos) { // This is it break; } else { // Need to go further lower to find the starting row end = pos; } } pos = (start + end) / 2; } alphaMap.put(key, pos); cursor.moveToPosition(savedCursorPos); return pos; } @Override public void onChanged() { super.onChanged(); mAlphaMap.clear(); } @Override public void onInvalidated() { super.onInvalidated(); mAlphaMap.clear(); } } Other Android examples (source code examples)Here is a short list of links related to this Android AlphabetIndexer.java source code file: |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.