我正在尝试在此Android教程中构建示例联系人应用代码:http://developer.android.com/training/contacts-provider/retrieve-details.html
那里有示例代码,它只显示给定联系人的地址信息。我能够扩展它来拉取所有其他字段,但我不能让其他字段以正确的顺序显示在布局中。
我认为这是因为片段为每个部分使用了多个Loader并在onLoaderFinished()中进行了每个部分的布局 - 但是它们完成的顺序是不可预测的。
就像联系人的应用程序一样,我需要能够仅在有该部分的数据时动态显示部分。例如,电话应该是第一个,但如果联系人没有电话号码,那么电子邮件应该先行,等等。
处理此问题的最佳方法是什么?我想到的一些可能性(尝试失败):
有什么想法?
以下是代码的一些片段---
这是启动Loader的地方,这由onActivityCreated调用:
public void setContact(Uri contactLookupUri) { mContactUri = contactLookupUri; // If the Uri contains data, load the contact's image and load contact details. if (contactLookupUri != null) { // Asynchronously loads the contact image mImageLoader.loadImage(mContactUri, mImageView); // Shows the contact photo ImageView and hides the empty view mImageView.setVisibility(View.VISIBLE); mEmptyView.setVisibility(View.GONE); // Shows the edit contact action/menu item if (mEditContactMenuItem != null) { mEditContactMenuItem.setVisible(true); } // Starts queries to retrieve contact information from the Contacts Provider. // restartLoader() is used instead of initLoader() as this method may be called // multiple times. getLoaderManager().restartLoader(ContactDetailQuery.QUERY_ID, null, this); getLoaderManager().restartLoader(ContactOrgQuery.QUERY_ID, null, this); getLoaderManager().restartLoader(ContactPhoneQuery.QUERY_ID, null, this); getLoaderManager().restartLoader(ContactEmailQuery.QUERY_ID, null, this); getLoaderManager().restartLoader(ContactAddressQuery.QUERY_ID, null, this); getLoaderManager().restartLoader(ContactGroupsQuery.QUERY_ID, null, this); getLoaderManager().restartLoader(ContactEventsQuery.QUERY_ID, null, this); } }
这里是onCreateLoader(),其中加载器开始查询内容提供者:
public Loader<Cursor> onCreateLoader(int id, Bundle args) { final Uri uri = Uri.withAppendedPath(mContactUri, Contacts.Data.CONTENT_DIRECTORY); switch (id) { case ContactDetailQuery.QUERY_ID: // This query loads main contact's name return new CursorLoader(getActivity(), mContactUri, ContactDetailQuery.PROJECTION, null, null, null); case ContactOrgQuery.QUERY_ID: // This query loads contact's company and title details. return new CursorLoader(getActivity(), uri, ContactOrgQuery.PROJECTION, ContactOrgQuery.SELECTION, null, null); case ContactPhoneQuery.QUERY_ID: // This query loads contact address details. return new CursorLoader(getActivity(), uri, ContactPhoneQuery.PROJECTION, ContactPhoneQuery.SELECTION, null, null); case ContactEmailQuery.QUERY_ID: // This query loads contact email details. return new CursorLoader(getActivity(), uri, ContactEmailQuery.PROJECTION, ContactEmailQuery.SELECTION, null, null); case ContactAddressQuery.QUERY_ID: // This query loads contact address details. return new CursorLoader(getActivity(), uri, ContactAddressQuery.PROJECTION, ContactAddressQuery.SELECTION, null, null); case ContactGroupsQuery.QUERY_ID: // This query loads contact groups the contact belongs to. return new CursorLoader(getActivity(), uri, ContactGroupsQuery.PROJECTION, ContactGroupsQuery.SELECTION, null, null); case ContactEventsQuery.QUERY_ID: // This query loads contact events (birthday, etc) the contact belongs to. return new CursorLoader(getActivity(), uri, ContactEventsQuery.PROJECTION, ContactEventsQuery.SELECTION, null, null); } return null; }
这是onLoadFinished(),它使用一个开关为每个加载器加载buildLayout函数:
public void onLoadFinished(Loader<Cursor> loader, Cursor data) { // If this fragment was cleared while the query was running // eg. from a call like setContact(uri) then don't do // anything. if (mContactUri == null) { Log.i(TAG, "mContactUri is null"); return; } final LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); switch (loader.getId()) { case ContactDetailQuery.QUERY_ID: // Moves to the first row in the Cursor if (data.moveToFirst()) { // For the contact details query, fetches the contact display name. // ContactDetailQuery.DISPLAY_NAME maps to the appropriate display // name field based on OS version. final String contactName = data.getString(ContactDetailQuery.DISPLAY_NAME); if (mIsTwoPaneLayout && mContactName != null) { // In the two pane layout, there is a dedicated TextView // that holds the contact name. mContactName.setText(contactName); } else { // In the single pane layout, sets the activity title // to the contact name. On HC+ this will be set as // the ActionBar title text. getActivity().setTitle(contactName); } } break; case ContactOrgQuery.QUERY_ID: if (data.moveToFirst()) { final String company = data.getString(ContactOrgQuery.COMPANY); final String title = data.getString(ContactOrgQuery.TITLE); //TODO Add Company|Title subtitle here to the ActionBar. } } break; case ContactPhoneQuery.QUERY_ID: // This query loads the contact phone details. Same as addresses above. // Loops through all the rows in the Cursor if (data.moveToFirst()) { // Displays the header for this category final FrameLayout headerLayout = addHeaderLayout(ContactPhoneQuery.header); mDetailsLayout.addView(headerLayout, layoutParams); do { // Builds the phone layout final LinearLayout layout = buildLayout( data.getInt(ContactPhoneQuery.TYPE), data.getString(ContactPhoneQuery.LABEL), data.getString(ContactPhoneQuery.NUMBER), ContactPhoneQuery.QUERY_ID); // Adds the new address layout to the details layout mDetailsLayout.addView(layout, layoutParams); } while (data.moveToNext()); } else { // If nothing found, adds an empty layout mDetailsLayout.addView(buildEmptyLayout(), layoutParams); } break; // Etc for all the Loaders that were called in setContact()
}
答案 0 :(得分:0)
我明白了。我将所有内容都放在一个Loader中,然后用不同的SELECTION运行几个查询。现在好多了!