1. 配置CursorLoader id
private static final int LOADER_ID = 4;
2. 创建CursorLoader
private void loadChatbotContactsCursor() {
getLoaderManager().restartLoader(LOADER_ID, null, this);
}
3. 重写onCreateLoader多种loader用id判断
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle bundle) {
LogUtil.i("NewSearchFragment.onCreateLoader", "loading cursor: " + id);
if (id == CONTACTS_LOADER_ID) {
return new SearchContactsCursorLoader(getContext(), query, isRegularSearch());
} else if (id == NEARBY_PLACES_LOADER_ID) {
// Directories represent contact data sources on the device, but since nearby places aren't
// stored on the device, they don't have a directory ID. We pass the list of all existing IDs
// so that we can find one that doesn't collide.
List<Long> directoryIds = new ArrayList<>();
for (Directory directory : directories) {
directoryIds.add(directory.getId());
}
return new NearbyPlacesCursorLoader(getContext(), query, directoryIds);
} else if (id == DIRECTORIES_LOADER_ID) {
return new DirectoriesCursorLoader(getContext());
} else if (id == DIRECTORY_CONTACTS_LOADER_ID) {
return new DirectoryContactsCursorLoader(getContext(), query, directories);
} else if (id == LOADER_ID) {
return new ContactsLoader(getContext(), query);
} else {
throw new IllegalStateException("Invalid loader id: " + id);
}
}
4. onLoadFinished填充数据到Adapter
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
LogUtil.i("NewSearchFragment.onLoadFinished", "Loader finished: " + loader);
if (cursor != null
&& !(loader instanceof DirectoriesCursorLoader)
&& !(cursor instanceof SearchCursor)) {
throw Assert.createIllegalStateFailException("Cursors must implement SearchCursor");
}
if (loader instanceof SearchContactsCursorLoader) {
adapter.setContactsCursor((SearchCursor) cursor);
} else if (loader instanceof NearbyPlacesCursorLoader) {
adapter.setNearbyPlacesCursor((SearchCursor) cursor);
} else if (loader instanceof DirectoryContactsCursorLoader) {
adapter.setDirectoryContactsCursor((SearchCursor) cursor);
} else if (loader instanceof DirectoriesCursorLoader) {
directories.clear();
directories.addAll(DirectoriesCursorLoader.toDirectories(cursor));
loadNearbyPlacesCursor();
loadDirectoryContactsCursors();
} else if (loader instanceof ContactsLoader) {
adapter.setContactsCursor((SearchCursor) cursor);
} else {
throw new IllegalStateException("Invalid loader: " + loader);
}
}
5. onCreateViewHolder根据getItemType创建不同ViewHolder
@Override
public ViewHolder onCreateViewHolder(ViewGroup root, @RowType int rowType) {
switch (rowType) {
case RowType.CONTACT_ROW:
return new SearchContactViewHolder(
LayoutInflater.from(context).inflate(R.layout.search_contact_row, root, false),
rowClickListener);
case RowType.NEARBY_PLACES_ROW:
return new NearbyPlaceViewHolder(
LayoutInflater.from(context).inflate(R.layout.search_contact_row, root, false),
rowClickListener);
case RowType.CONTACT_HEADER:
case RowType.DIRECTORY_HEADER:
case RowType.NEARBY_PLACES_HEADER:
return new HeaderViewHolder(
LayoutInflater.from(context).inflate(R.layout.header_layout, root, false));
case RowType.DIRECTORY_ROW:
return new DirectoryContactViewHolder(
LayoutInflater.from(context).inflate(R.layout.search_contact_row, root, false),
rowClickListener);
case RowType.SEARCH_ACTION:
return new SearchActionViewHolder(
LayoutInflater.from(context).inflate(R.layout.search_action_layout, root, false),
rowClickListener);
case RowType.LOCATION_REQUEST:
return new LocationPermissionViewHolder(
LayoutInflater.from(context).inflate(R.layout.location_permission_row, root, false),
allowClickListener,
dismissClickListener);
case RowType.INVALID:
default:
throw Assert.createIllegalStateFailException("Invalid RowType: " + rowType);
}
}
6. 绑定数据
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
if (holder instanceof SearchContactViewHolder) {
((SearchContactViewHolder) holder).bind(searchCursorManager.getCursor(position), query);
} else if (holder instanceof NearbyPlaceViewHolder) {
((NearbyPlaceViewHolder) holder).bind(searchCursorManager.getCursor(position), query);
} else if (holder instanceof DirectoryContactViewHolder) {
((DirectoryContactViewHolder) holder).bind(searchCursorManager.getCursor(position), query);
} else if (holder instanceof HeaderViewHolder) {
String header =
searchCursorManager.getCursor(position).getString(SearchCursor.HEADER_TEXT_POSITION);
((HeaderViewHolder) holder).setHeader(header);
} else if (holder instanceof SearchActionViewHolder) {
((SearchActionViewHolder) holder)
.setAction(
searchCursorManager.getSearchAction(position),
position,
TextUtils.isEmpty(rawNumber) ? query : rawNumber);
} else if (holder instanceof LocationPermissionViewHolder) {
// No-op
} else {
throw Assert.createIllegalStateFailException("Invalid ViewHolder: " + holder);
}
}
7. 获取类型
@Override
public @RowType int getItemViewType(int position) {
return searchCursorManager.getRowType(position);
}
8. position在Cursor之间定位
SearchCursor getCursor(int position) {
if (showLocationPermissionRequest) {
if (position == 0) {
return LOCATION_PERMISSION_CURSOR;
}
position--;
}
if (contactsCursor != null) {
int count = contactsCursor.getCount();
if (position - count < 0) {
contactsCursor.moveToPosition(position);
return contactsCursor;
}
position -= count;
}
if (!showLocationPermissionRequest && nearbyPlacesCursor != null) {
int count = nearbyPlacesCursor.getCount();
if (position - count < 0) {
nearbyPlacesCursor.moveToPosition(position);
return nearbyPlacesCursor;
}
position -= count;
}
8. 获取数据类型
int getRowType(int position) {
int cursorCount = getCount();
if (position >= cursorCount) {
throw Assert.createIllegalStateFailException(
String.format("Invalid position: %d, cursor count: %d", position, cursorCount));
} else if (position >= cursorCount - searchActions.size()) {
return RowType.SEARCH_ACTION;
}
SearchCursor cursor = getCursor(position);
if (cursor == contactsCursor) {
return cursor.isHeader() ? RowType.CONTACT_HEADER : RowType.CONTACT_ROW;
}
if (cursor == LOCATION_PERMISSION_CURSOR) {
return RowType.LOCATION_REQUEST;
}
if (cursor == nearbyPlacesCursor) {
return cursor.isHeader() ? RowType.NEARBY_PLACES_HEADER : RowType.NEARBY_PLACES_ROW;
}
if (cursor == corpDirectoryCursor) {
return cursor.isHeader() ? RowType.DIRECTORY_HEADER : RowType.DIRECTORY_ROW;
}
throw Assert.createIllegalStateFailException("No valid row type.");
}
网友评论