如何处理以不可预测的顺序完成的多个加载器的布局?

时间:2013-10-24 16:21:29

标签: android android-layout android-fragments

我正在尝试在此Android教程中构建示例联系人应用代码:http://developer.android.com/training/contacts-provider/retrieve-details.html

那里有示例代码,它只显示给定联系人的地址信息。我能够扩展它来拉取所有其他字段,但我不能让其他字段以正确的顺序显示在布局中。

我认为这是因为片段为每个部分使用了多个Loader并在onLoaderFinished()中进行了每个部分的布局 - 但是它们完成的顺序是不可预测的。

就像联系人的应用程序一样,我需要能够仅在有该部分的数据时动态显示部分。例如,电话应该是第一个,但如果联系人没有电话号码,那么电子邮件应该先行,等等。

处理此问题的最佳方法是什么?我想到的一些可能性(尝试失败):

  1. 而不是在onLoadFinished中为每个游标构建布局, 使用联系人填充新的Contact类对象 细节。我遇到的问题是我无法想象 在哪里构建布局,并确保Contact对象 人口稠密。我得到空指针异常。
  2. 创建一个单独的ContactLoader类,片段调用该类 处理所有Loaders并返回指向Contact对象的指针。 问题:如何确定Contact对象已完成 在我开始布局之前填充?
  3. 使用调用所有联系人的单个查询加载所有联系人数据 数据列一次。我在设置正确方面遇到了很多麻烦 选择查询并解析Cursor。
  4. 有什么想法?

    以下是代码的一些片段---

    这是启动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() 
    
         

    }

1 个答案:

答案 0 :(得分:0)

我明白了。我将所有内容都放在一个Loader中,然后用不同的SELECTION运行几个查询。现在好多了!