diff --git a/core/lib/Drupal/Core/Entity/Display/EntityViewDisplayInterface.php b/core/lib/Drupal/Core/Entity/Display/EntityViewDisplayInterface.php
index 8a9ce80aae48659f31ece4b46bac11363c6dbb73..8d86a6badc5bfded092236ae3d9c2b2f328acf32 100644
--- a/core/lib/Drupal/Core/Entity/Display/EntityViewDisplayInterface.php
+++ b/core/lib/Drupal/Core/Entity/Display/EntityViewDisplayInterface.php
@@ -7,9 +7,48 @@
 
 namespace Drupal\Core\Entity\Display;
 
+use Drupal\Core\Entity\ContentEntityInterface;
+
 /**
  * Provides a common interface for entity view displays.
  */
 interface EntityViewDisplayInterface extends EntityDisplayInterface {
 
+  /**
+   * Returns a renderable array for the components of an entity.
+   *
+   * See the buildMultiple() method for details.
+   *
+   * @param \Drupal\Core\Entity\ContentEntityInterface $entity
+   *   The entity being displayed.
+   *
+   * @return array
+   *   A renderable array for the entity.
+   *
+   * @see \Drupal\Core\Entity\Display\EntityViewDisplayInterface::buildMultiple()
+   */
+  public function build(ContentEntityInterface $entity);
+
+  /**
+   * Returns a renderable array for the components of a set of entities.
+   *
+   * This only includes the components handled by the Display object, but
+   * excludes 'extra fields', that are typically rendered through specific,
+   * ad-hoc code in EntityViewBuilderInterface::buildContent() or in
+   * hook_entity_view() implementations.
+   *
+   * hook_entity_display_build_alter() is invoked on each entity, allowing 3rd
+   * party code to alter the render array.
+   *
+   * @param \Drupal\Core\Entity\ContentEntityInterface[] $entities
+   *   The entities being displayed.
+   *
+   * @return array
+   *   A renderable array for the entities, indexed by the same keys as the
+   *   $entities array parameter.
+   *
+   * @see hook_entity_display_build_alter()
+   */
+  public function buildMultiple(array $entities);
+
 }
diff --git a/core/lib/Drupal/Core/Entity/EntityViewBuilder.php b/core/lib/Drupal/Core/Entity/EntityViewBuilder.php
index e67657c4cdcf941a3f8ac15e0a84723de8e657ea..bffc73109f30415dbf321464d467e8679e80f79b 100644
--- a/core/lib/Drupal/Core/Entity/EntityViewBuilder.php
+++ b/core/lib/Drupal/Core/Entity/EntityViewBuilder.php
@@ -89,16 +89,18 @@ public static function createInstance(ContainerInterface $container, EntityTypeI
    * {@inheritdoc}
    */
   public function buildContent(array $entities, array $displays, $view_mode, $langcode = NULL) {
-    field_attach_prepare_view($this->entityTypeId, $entities, $displays, $langcode);
-
-    // Initialize the field item attributes for the fields set to be displayed.
-    foreach ($entities as $entity) {
-      // The entity can include fields that aren't displayed, and the display
-      // can include components that aren't fields, so we want to iterate the
-      // intersection of $entity->getProperties() and $display->getComponents().
-      // However, the entity can have many more fields than are displayed, so we
-      // avoid the cost of calling $entity->getProperties() by iterating the
-      // intersection as follows.
+    $entities_by_bundle = array();
+    foreach ($entities as $id => $entity) {
+      // Remove previously built content, if exists.
+      $entity->content = array(
+        '#view_mode' => $view_mode,
+      );
+      // Initialize the field item attributes for the fields being displayed.
+      // The entity can include fields that are not displayed, and the display
+      // can include components that are not fields, so we want to act on the
+      // intersection. However, the entity can have many more fields than are
+      // displayed, so we avoid the cost of calling $entity->getProperties()
+      // by iterating the intersection as follows.
       foreach ($displays[$entity->bundle()]->getComponents() as $name => $options) {
         if ($entity->hasField($name)) {
           foreach ($entity->get($name) as $item) {
@@ -106,16 +108,19 @@ public function buildContent(array $entities, array $displays, $view_mode, $lang
           }
         }
       }
+      // Group the entities by bundle.
+      $entities_by_bundle[$entity->bundle()][$id] = $entity;
     }
 
+    // Invoke hook_entity_prepare_view().
     module_invoke_all('entity_prepare_view', $this->entityTypeId, $entities, $displays, $view_mode);
 
-    foreach ($entities as $entity) {
-      // Remove previously built content, if exists.
-      $entity->content = array(
-        '#view_mode' => $view_mode,
-      );
-      $entity->content += field_attach_view($entity, $displays[$entity->bundle()], $langcode);
+    // Let the displays build their render arrays.
+    foreach ($entities_by_bundle as $bundle => $bundle_entities) {
+      $build = $displays[$bundle]->buildMultiple($bundle_entities);
+      foreach ($bundle_entities as $id => $entity) {
+        $entity->content += $build[$id];
+      }
     }
   }
 
@@ -231,6 +236,9 @@ public function viewMultiple(array $entities = array(), $view_mode = 'full', $la
       $this->alterBuild($build[$key], $entity, $display, $entity_view_mode, $langcode);
 
       // Assign the weights configured in the display.
+      // @todo: Once https://drupal.org/node/1875974 provides the missing API,
+      //   only do it for 'extra fields', since other components have been taken
+      //   care of in EntityViewDisplay::buildMultiple().
       foreach ($display->getComponents() as $name => $options) {
         if (isset($build[$key][$name])) {
           $build[$key][$name]['#weight'] = $options['weight'];
diff --git a/core/lib/Drupal/Core/Entity/EntityViewBuilderInterface.php b/core/lib/Drupal/Core/Entity/EntityViewBuilderInterface.php
index 6cd09609fce381bea5ea954e8930adbe948c61a6..14e4ba0cf54d72b47fe80ce1d3d60efef62fc85f 100644
--- a/core/lib/Drupal/Core/Entity/EntityViewBuilderInterface.php
+++ b/core/lib/Drupal/Core/Entity/EntityViewBuilderInterface.php
@@ -15,9 +15,9 @@ interface EntityViewBuilderInterface {
   /**
    * Build the structured $content property on the entity.
    *
-   * @param array $entities
-   *   The entities, implementing EntityInterface, whose content is being built.
-   * @param \Drupal\Core\Entity\EntityViewDisplayInterface[] $displays
+   * @param \Drupal\Core\Entity\EntityInterface[] $entities
+   *   The entities whose content is being built.
+   * @param \Drupal\Core\Entity\Display\EntityViewDisplayInterface[] $displays
    *   The array of entity view displays holding the display options
    *   configured for the entity components, keyed by bundle name.
    * @param string $view_mode
diff --git a/core/lib/Drupal/Core/Field/Annotation/FieldFormatter.php b/core/lib/Drupal/Core/Field/Annotation/FieldFormatter.php
index 1ef899eeea7fb9ba2bba5344cae79ffa89cd1de5..11f224622cc66d2ee62da4a03019f9fef99c13cf 100644
--- a/core/lib/Drupal/Core/Field/Annotation/FieldFormatter.php
+++ b/core/lib/Drupal/Core/Field/Annotation/FieldFormatter.php
@@ -12,9 +12,8 @@
 /**
  * Defines a FieldFormatter annotation object.
  *
- * Formatters handle the display of field values. Formatter hooks are typically
- * called by the Field Attach API field_attach_prepare_view() and
- * field_attach_view() functions.
+ * Formatters handle the display of field values. They are typically
+ * instantiated and invoked by an EntityDisplay object.
  *
  * Additional annotation keys for formatters can be defined in
  * hook_field_formatter_info_alter().
diff --git a/core/lib/Drupal/Core/Field/FormatterInterface.php b/core/lib/Drupal/Core/Field/FormatterInterface.php
index ef6776d96d331bacb89ed904cde0a31524a0bc5b..fa633727024325804af06dc2ba70289d287dc408 100644
--- a/core/lib/Drupal/Core/Field/FormatterInterface.php
+++ b/core/lib/Drupal/Core/Field/FormatterInterface.php
@@ -48,22 +48,20 @@ public function settingsSummary();
    * field that displays properties of the referenced entities such as name or
    * type.
    *
-   * This method operates on multiple entities. The $entities and $items
-   * parameters are arrays keyed by entity ID. For performance reasons,
-   * information for all involved entities should be loaded in a single query
-   * where possible.
+   * This method operates on multiple entities. The $entities_items parameter
+   * is an array keyed by entity ID. For performance reasons, information for
+   * all involved entities should be loaded in a single query where possible.
    *
-   * Changes or additions to field values are done by alterings the $items
-   * parameter by reference.
+   * Changes or additions to field values are done by directly altering the
+   * items.
    *
-   * @param array $entities_items
-   *   Array of field values (Drupal\Core\Field\FieldItemListInterface),
-   *   keyed by entity ID.
+   * @param \Drupal\Core\Field\FieldItemListInterface[] $entities_items
+   *   Array of field values, keyed by entity ID.
    */
   public function prepareView(array $entities_items);
 
   /**
-   * Builds a renderable array for one field on one entity instance.
+   * Builds a renderable array for a fully themed field.
    *
    * @param \Drupal\Core\Field\FieldItemListInterface $items
    *   The field values to be rendered.
@@ -81,7 +79,7 @@ public function view(FieldItemListInterface $items);
    *
    * @return array
    *   A renderable array for $items, as an array of child elements keyed by
-   *   numeric indexes starting from 0.
+   *   consecutive numeric indexes starting from 0.
    */
   public function viewElements(FieldItemListInterface $items);
 
diff --git a/core/modules/datetime/lib/Drupal/datetime/Tests/DateTimeFieldTest.php b/core/modules/datetime/lib/Drupal/datetime/Tests/DateTimeFieldTest.php
index c2ec06801bcde5a47e0d5af27d2b79c86d944fae..4aeec859ee27846a407069c90c940ac2b2764248 100644
--- a/core/modules/datetime/lib/Drupal/datetime/Tests/DateTimeFieldTest.php
+++ b/core/modules/datetime/lib/Drupal/datetime/Tests/DateTimeFieldTest.php
@@ -2,11 +2,12 @@
 
 /**
  * @file
- * Contains \Drupal\datetime\Tests\DatetimeFieldTest.
+ * Contains \Drupal\datetime\Tests\DateTimeFieldTest.
  */
 
 namespace Drupal\datetime\Tests;
 
+use Drupal\entity\Entity\EntityViewDisplay;
 use Drupal\simpletest\WebTestBase;
 use Drupal\Core\Datetime\DrupalDateTime;
 
@@ -455,10 +456,8 @@ protected function renderTestEntity($id, $view_mode = 'full', $reset = TRUE) {
       entity_get_controller('entity_test')->resetCache(array($id));
     }
     $entity = entity_load('entity_test', $id);
-    $display = entity_get_display('entity_test', $entity->bundle(), 'full');
-    field_attach_prepare_view('entity_test', array($entity->id() => $entity), array($entity->bundle() => $display), $view_mode);
-    $entity->content = field_attach_view($entity, $display, $view_mode);
-
+    $display = EntityViewDisplay::collectRenderDisplay($entity, $view_mode);
+    $entity->content = $display->build($entity);
     $output = drupal_render($entity->content);
     $this->drupalSetContent($output);
     $this->verbose($output);
diff --git a/core/modules/email/lib/Drupal/email/Tests/EmailFieldTest.php b/core/modules/email/lib/Drupal/email/Tests/EmailFieldTest.php
index a359150b32ceb722fba962190493ebe31a5b413c..6af964f802e871182c563e29b4e0007d9cb9b877 100644
--- a/core/modules/email/lib/Drupal/email/Tests/EmailFieldTest.php
+++ b/core/modules/email/lib/Drupal/email/Tests/EmailFieldTest.php
@@ -111,8 +111,8 @@ function testEmailField() {
     // Verify that a mailto link is displayed.
     $entity = entity_load('entity_test', $id);
     $display = entity_get_display($entity->getEntityTypeId(), $entity->bundle(), 'full');
-    $entity->content = field_attach_view($entity, $display);
-    $this->drupalSetContent(drupal_render($entity->content));
+    $content = $display->build($entity);
+    $this->drupalSetContent(drupal_render($content));
     $this->assertLinkByHref('mailto:test@example.com');
   }
 }
diff --git a/core/modules/entity/lib/Drupal/entity/Entity/EntityViewDisplay.php b/core/modules/entity/lib/Drupal/entity/Entity/EntityViewDisplay.php
index b34259b243e5404cbf15f99f23ef99c781b0b12a..5ab421e479c9d1b9aef7e31e2ad44d23117b6997 100644
--- a/core/modules/entity/lib/Drupal/entity/Entity/EntityViewDisplay.php
+++ b/core/modules/entity/lib/Drupal/entity/Entity/EntityViewDisplay.php
@@ -9,6 +9,7 @@
 
 use Drupal\Component\Utility\NestedArray;
 use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
+use Drupal\Core\Entity\ContentEntityInterface;
 use Drupal\entity\EntityDisplayBase;
 
 /**
@@ -197,4 +198,62 @@ public function getRenderer($field_name) {
     return $formatter;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function build(ContentEntityInterface $entity) {
+    $build = $this->buildMultiple(array($entity));
+    return $build[0];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildMultiple(array $entities) {
+    $build = array();
+    foreach ($entities as $key => $entity) {
+      $build[$key] = array();
+    }
+
+    // Run field formatters.
+    foreach ($this->getFieldDefinitions() as $field_name => $definition) {
+      if ($formatter = $this->getRenderer($field_name)) {
+        // Group items across all entities and pass them to the formatter's
+        // prepareView() method.
+        $grouped_items = array();
+        foreach ($entities as $id => $entity) {
+          $items = $entity->get($field_name);
+          $items->filterEmptyItems();
+          $grouped_items[$id] = $items;
+        }
+        $formatter->prepareView($grouped_items);
+
+        // Then let the formatter build the output for each entity.
+        foreach ($entities as $key => $entity) {
+          $items = $entity->get($field_name);
+          $build[$key] += $formatter->view($items);
+        }
+      }
+    }
+
+    foreach ($entities as $key => $entity) {
+      // Assign the configured weights.
+      foreach ($this->getComponents() as $name => $options) {
+        if (isset($build[$key][$name])) {
+          $build[$key][$name]['#weight'] = $options['weight'];
+        }
+      }
+
+      // Let other modules alter the renderable array.
+      $context = array(
+        'entity' => $entity,
+        'view_mode' => $this->originalMode,
+        'display' => $this,
+      );
+      \Drupal::moduleHandler()->alter('entity_display_build', $build[$key], $context);
+    }
+
+    return $build;
+  }
+
 }
diff --git a/core/modules/field/field.api.php b/core/modules/field/field.api.php
index a85300f79e543f9c9b987f4cc0831f72d5eddcff..e50152bb0a8be8a6d4f4856e23c295009d0c7d8c 100644
--- a/core/modules/field/field.api.php
+++ b/core/modules/field/field.api.php
@@ -19,7 +19,7 @@
  * should expose them using this hook. The user-defined settings (weight,
  * visible) are automatically applied on rendered forms and displayed entities
  * in a #pre_render callback added by field_attach_form() and
- * field_attach_view().
+ * EntityViewBuilder::viewMultiple().
  *
  * @see hook_field_extra_fields_alter()
  *
@@ -357,46 +357,6 @@ function hook_field_attach_extract_form_values(\Drupal\Core\Entity\EntityInterfa
   }
 }
 
-/**
- * Perform alterations on field_attach_view() or field_view_field().
- *
- * This hook is invoked after the field module has performed the operation.
- *
- * @param $output
- *   The structured content array tree for all of the entity's fields.
- * @param $context
- *   An associative array containing:
- *   - entity: The entity with fields to render.
- *   - view_mode: View mode; for example, 'full' or 'teaser'.
- *   - display_options: Either a view mode string or an array of display
- *     options. If this hook is being invoked from field_attach_view(), the
- *     'display_options' element is set to the view mode string. If this hook
- *     is being invoked from field_view_field(), this element is set to the
- *     $display_options argument and the view_mode element is set to '_custom'.
- *     See field_view_field() for more information on what its $display_options
- *     argument contains.
- *   - langcode: The language code used for rendering.
- *
- * @deprecated as of Drupal 8.0. Use the entity system instead.
- */
-function hook_field_attach_view_alter(&$output, $context) {
-  // Append RDF term mappings on displayed taxonomy links.
-  foreach (element_children($output) as $field_name) {
-    $element = &$output[$field_name];
-    if ($element['#field_type'] == 'entity_reference' && $element['#formatter'] == 'entity_reference_label') {
-      foreach ($element['#items'] as $delta => $item) {
-        $term = $item->entity;
-        if (!empty($term->rdf_mapping['rdftype'])) {
-          $element[$delta]['#options']['attributes']['typeof'] = $term->rdf_mapping['rdftype'];
-        }
-        if (!empty($term->rdf_mapping['name']['predicates'])) {
-          $element[$delta]['#options']['attributes']['property'] = $term->rdf_mapping['name']['predicates'];
-        }
-      }
-    }
-  }
-}
-
 /**
  * @} End of "addtogroup field_attach".
  */
diff --git a/core/modules/field/field.attach.inc b/core/modules/field/field.attach.inc
index d471223e106f1796111144821c42bb9953237196..59c6deb6b3363a4b838fec553d1ad5ee98833967 100644
--- a/core/modules/field/field.attach.inc
+++ b/core/modules/field/field.attach.inc
@@ -7,7 +7,6 @@
 
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Field\FieldDefinitionInterface;
-use Drupal\entity\Entity\EntityFormDisplay;
 
 /**
  * @defgroup field_attach Field Attach API
@@ -47,12 +46,6 @@
  * exposes a single bundle (all entities of this type have the same collection
  * of fields). This is the case for the 'user' entity type.
  *
- * Most Field Attach API functions define a corresponding hook function that
- * allows any module to act on Field Attach operations for any entity after the
- * operation is complete, and access or modify all the field, form, or display
- * data for that entity and operation. For example, field_attach_view() invokes
- * hook_field_attach_view_alter().
- *
  * @link field_language Field language API @endlink provides information about
  * the structure of field objects.
  *
@@ -119,96 +112,6 @@ function field_invoke_method($method, $target_function, EntityInterface $entity,
   return $return;
 }
 
-/**
- * Invokes a method across fields on multiple entities.
- *
- * @param string $method
- *   The name of the method to invoke.
- * @param callable $target_function
- *   A function that receives a FieldDefinitionInterface object and a bundle
- *   name and returns the object on which the method should be invoked.
- * @param \Drupal\Core\Entity\EntityInterface[] $entities
- *   An array of entities, keyed by entity ID.
- * @param mixed $a
- *   (optional) A parameter for the invoked method. Defaults to NULL.
- * @param mixed $b
- *   (optional) A parameter for the invoked method. Defaults to NULL.
- * @param $options
- *   (optional) An associative array of additional options, with the following
- *   keys:
- *   - field_name: The name of the field whose operation should be invoked. By
- *     default, the operation is invoked on all the fields in the entity's
- *     bundle.
- *
- * @return array
- *   An array of returned values keyed by entity ID.
- *
- * @see field_invoke_method()
- */
-function field_invoke_method_multiple($method, $target_function, array $entities, &$a = NULL, &$b = NULL, array $options = array()) {
-  $grouped_items = array();
-  $grouped_targets = array();
-  $return = array();
-
-  // Go through the entities and collect the instances on which the method
-  // should be called.
-  foreach ($entities as $entity) {
-    $entity_type = $entity->getEntityTypeId();
-    $bundle = $entity->bundle();
-    $id = $entity->id();
-
-    // Determine the list of fields to iterate on.
-    $field_definitions = _field_invoke_get_field_definitions($entity_type, $bundle, $options);
-
-    foreach ($field_definitions as $field_definition) {
-      $field_name = $field_definition->getName();
-      $group_key = "$bundle:$field_name";
-
-      // Let the closure determine the target object on which the method should
-      // be called.
-      if (empty($grouped_targets[$group_key])) {
-        $target = call_user_func($target_function, $field_definition, $bundle);
-        if (method_exists($target, $method)) {
-          $grouped_targets[$group_key] = $target;
-        }
-        else {
-          $grouped_targets[$group_key] = FALSE;
-        }
-      }
-
-      // If there is a target, group the field items.
-      if ($grouped_targets[$group_key]) {
-        $items = $entity->get($field_name);
-        $items->filterEmptyItems();
-        $grouped_items[$group_key][$id] = $items;
-      }
-    }
-    // Initialize the return value for each entity.
-    $return[$id] = array();
-  }
-
-  // For each field, invoke the method and collect results.
-  foreach ($grouped_items as $key => $entities_items) {
-    $results = $grouped_targets[$key]->$method($entities_items, $a, $b);
-
-    if (isset($results)) {
-      // Collect results by entity.
-      // For hooks with array results, we merge results together.
-      // For hooks with scalar results, we collect results in an array.
-      foreach ($results as $id => $result) {
-        if (is_array($result)) {
-          $return[$id] = array_merge($return[$id], $result);
-        }
-        else {
-          $return[$id][] = $result;
-        }
-      }
-    }
-  }
-
-  return $return;
-}
-
 /**
  * Retrieves a list of field definitions to operate on.
  *
diff --git a/core/modules/field/field.deprecated.inc b/core/modules/field/field.deprecated.inc
index 1e63781743b1f9832dedfe730aa8b6ac6b37af91..6bdc8b2e037ceca5505007067a521288156564ab 100644
--- a/core/modules/field/field.deprecated.inc
+++ b/core/modules/field/field.deprecated.inc
@@ -387,111 +387,3 @@ function field_attach_extract_form_values(EntityInterface $entity, $form, &$form
     $function($entity, $form, $form_state);
   }
 }
-
-/**
- * Prepares field data prior to display.
- *
- * This function lets field types and formatters load additional data needed for
- * display that is not automatically loaded during entity loading. It accepts an
- * array of entities to allow query optimization when displaying lists of
- * entities.
- *
- * field_attach_prepare_view() and field_attach_view() are two halves of the
- * same operation. It is safe to call field_attach_prepare_view() multiple times
- * on the same entity before calling field_attach_view() on it, but calling any
- * Field API operation on an entity between passing that entity to these two
- * functions may yield incorrect results.
- *
- * @param $entity_type
- *   The type of entities in $entities; e.g. 'node' or 'user'.
- * @param array $entities
- *   An array of entities, keyed by entity ID.
- * @param array $displays
- *   An array of entity display objects, keyed by bundle name.
- * @param $langcode
- *   (Optional) The language the field values are to be shown in. If no language
- *   is provided the current language is used.
- *
- * @deprecated as of Drupal 8.0. Use the entity system instead.
- */
-function field_attach_prepare_view($entity_type, array $entities, array $displays, $langcode = NULL) {
-  // To ensure hooks are only run once per entity, only process items without
-  // the _field_view_prepared flag.
-  // @todo: resolve this more generally for both entity and field level hooks.
-  $prepare = array();
-  foreach ($entities as $id => $entity) {
-    if (empty($entity->_field_view_prepared)) {
-      // Add this entity to the items to be prepared.
-      $prepare[$id] = $entity;
-
-      // Mark this item as prepared.
-      $entity->_field_view_prepared = TRUE;
-    }
-  }
-
-  // Then let the formatters do their own specific massaging. For each
-  // instance, call the prepareView() method on the formatter object handed by
-  // the entity display.
-  $target_function = function (FieldDefinitionInterface $field_definition, $bundle) use ($displays) {
-    if (isset($displays[$bundle])) {
-      return $displays[$bundle]->getRenderer($field_definition->getName());
-    }
-  };
-  $null = NULL;
-  field_invoke_method_multiple('prepareView', $target_function, $prepare, $null, $null);
-}
-
-/**
- * Returns a renderable array for the fields on an entity.
- *
- * Each field is displayed according to the display options specified in the
- * $display parameter for the given view mode.
- *
- * field_attach_prepare_view() and field_attach_view() are two halves of the
- * same operation. It is safe to call field_attach_prepare_view() multiple times
- * on the same entity before calling field_attach_view() on it, but calling any
- * Field API operation on an entity between passing that entity to these two
- * functions may yield incorrect results.
- *
- * @param \Drupal\Core\Entity\EntityInterface $entity
- *   The entity with fields to render.
- * @param \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display
- *   The entity display object.
- * @param $langcode
- *   The language the field values are to be shown in. If no language is
- *   provided the current language is used.
- * @param array $options
- *   An associative array of additional options. See field_invoke_method() for
- *   details.
- *
- * @return array
- *   A renderable array for the field values.
- *
- * @deprecated as of Drupal 8.0. Use the entity system instead.
- */
-function field_attach_view(EntityInterface $entity, EntityViewDisplayInterface $display, $langcode = NULL, array $options = array()) {
-  // For each field, call the view() method on the formatter object handed
-  // by the entity display.
-  $target_function = function (FieldDefinitionInterface $field_definition) use ($display) {
-    return $display->getRenderer($field_definition->getName());
-  };
-  $null = NULL;
-  $output = field_invoke_method('view', $target_function, $entity, $null, $null, $options);
-
-  // Let other modules alter the renderable array.
-  $view_mode = $display->originalMode;
-  $context = array(
-    'entity' => $entity,
-    'view_mode' => $view_mode,
-    'display_options' => $view_mode,
-    'langcode' => $langcode,
-  );
-  drupal_alter('field_attach_view', $output, $context);
-
-  // Reset the _field_view_prepared flag set in field_attach_prepare_view(),
-  // in case the same entity is displayed with different settings later in
-  // the request.
-  unset($entity->_field_view_prepared);
-
-  return $output;
-}
diff --git a/core/modules/field/field.module b/core/modules/field/field.module
index 883814d2a0c2a990629c70c246f24789d9054370..6a8b941125447bc85e32b34cf043f41a03e657ba 100644
--- a/core/modules/field/field.module
+++ b/core/modules/field/field.module
@@ -5,7 +5,6 @@
  */
 
 use Drupal\Core\Entity\ContentEntityInterface;
-use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Template\Attribute;
 use Drupal\entity\Entity\EntityViewDisplay;
 
@@ -325,7 +324,7 @@ function _field_filter_xss_display_allowed_tags() {
 /**
  * Returns a renderable array for a single field value.
  *
- * @param \Drupal\Core\Entity\EntityInterface $entity
+ * @param \Drupal\Core\Entity\ContentEntityInterface $entity
  *   The entity containing the field to display. Must at least contain the ID
  *   key and the field data to display.
  * @param $field_name
@@ -342,10 +341,10 @@ function _field_filter_xss_display_allowed_tags() {
  * @return
  *   A renderable array for the field value.
  */
-function field_view_value(EntityInterface $entity, $field_name, $item, $display = array(), $langcode = NULL) {
+function field_view_value(ContentEntityInterface $entity, $field_name, $item, $display = array(), $langcode = NULL) {
   $output = array();
 
-  if ($field = field_info_field($entity->getEntityTypeId(), $field_name)) {
+  if ($entity->hasField($field_name)) {
     // Clone the entity since we are going to modify field values.
     $clone = clone $entity;
 
@@ -376,8 +375,8 @@ function field_view_value(EntityInterface $entity, $field_name, $item, $display
  * isolated field.
  * - Do not use inside node (or any other entity) templates; use
  *   render($content[FIELD_NAME]) instead.
- * - Do not use to display all fields in an entity; use
- *   field_attach_prepare_view() and field_attach_view() instead.
+ * - Do not use to display all fields in an entity; use EntityDisplay::build()
+ *   instead.
  * - The field_view_value() function can be used to output a single formatted
  *   field value, without label or wrapping field markup.
  *
@@ -424,49 +423,31 @@ function field_view_field(ContentEntityInterface $entity, $field_name, $display_
   if (!$entity->hasField($field_name)) {
     return $output;
   }
-  $field_definition = $entity->get($field_name)->getFieldDefinition();
 
-  // Get the formatter object.
+  // Get the display object.
   if (is_string($display_options)) {
     $view_mode = $display_options;
-    $formatter = EntityViewDisplay::collectRenderDisplay($entity, $view_mode)->getRenderer($field_name);
+    $display = EntityViewDisplay::collectRenderDisplay($entity, $view_mode);
+    foreach ($entity as $name => $items) {
+      if ($name != $field_name) {
+        $display->removeComponent($name);
+      }
+    }
   }
   else {
     $view_mode = '_custom';
-    // hook_field_attach_display_alter() needs to receive the 'prepared'
-    // $display_options, so we cannot let preparation happen internally.
-    $formatter_manager = Drupal::service('plugin.manager.field.formatter');
-    $display_options = $formatter_manager->prepareConfiguration($field_definition->getType(), $display_options);
-    $formatter = $formatter_manager->getInstance(array(
-      'field_definition' => $field_definition,
-      'view_mode' => $view_mode,
-      'prepare' => FALSE,
-      'configuration' => $display_options,
+    $display = entity_create('entity_view_display', array(
+      'targetEntityType' => $entity->getEntityTypeId(),
+      'bundle' => $entity->bundle(),
+      'mode' => $view_mode,
+      'status' => TRUE,
     ));
+    $display->setComponent($field_name, $display_options);
   }
 
-  if ($formatter) {
-    // Apply language fallback.
-    $entity = \Drupal::entityManager()->getTranslationFromContext($entity, $langcode);
-    $items = $entity->get($field_name);
-
-    // Run the formatter.
-    $formatter->prepareView(array($entity->id() => $items));
-    $result = $formatter->view($items);
-
-    // Invoke hook_field_attach_view_alter() to let other modules alter the
-    // renderable array, as in a full field_attach_view() execution.
-    $context = array(
-      'entity' => $entity,
-      'view_mode' => $view_mode,
-      'display_options' => $display_options,
-      'langcode' => $entity->language()->id,
-    );
-    drupal_alter('field_attach_view', $result, $context);
-
-    if (isset($result[$field_name])) {
-      $output = $result[$field_name];
-    }
+  $build = $display->build($entity);
+  if (isset($build[$field_name])) {
+    $output = $build[$field_name];
   }
 
   return $output;
diff --git a/core/modules/field/lib/Drupal/field/Tests/DisplayApiTest.php b/core/modules/field/lib/Drupal/field/Tests/DisplayApiTest.php
index 750eee6be04c732948be4a3cc47f66ce61a3cf08..00ebc40f5b0a8f4504ec8cbf7ff55358d4488f21 100644
--- a/core/modules/field/lib/Drupal/field/Tests/DisplayApiTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/DisplayApiTest.php
@@ -142,8 +142,8 @@ function testFieldViewField() {
     $this->content = drupal_render($output);
     $setting = $display['settings']['test_formatter_setting_multiple'];
     $this->assertNoText($this->label, 'Label was not displayed.');
-    $this->assertText('field_test_field_attach_view_alter', 'Alter fired, display passed.');
-    $this->assertText('field language is ' . Language::LANGCODE_NOT_SPECIFIED, 'Language is placed onto the context.');
+    $this->assertText('field_test_entity_display_build_alter', 'Alter fired, display passed.');
+    $this->assertText('entity language is ' . Language::LANGCODE_NOT_SPECIFIED, 'Language is placed onto the context.');
     $array = array();
     foreach ($this->values as $delta => $value) {
       $array[] = $delta . ':' . $value['value'];
@@ -163,7 +163,7 @@ function testFieldViewField() {
     $this->content = $view;
     $setting = $display['settings']['test_formatter_setting_additional'];
     $this->assertNoText($this->label, 'Label was not displayed.');
-    $this->assertNoText('field_test_field_attach_view_alter', 'Alter not fired.');
+    $this->assertNoText('field_test_entity_display_build_alter', 'Alter not fired.');
     foreach ($this->values as $delta => $value) {
       $this->assertText($setting . '|' . $value['value'] . '|' . ($value['value'] + 1), format_string('Value @delta was displayed with expected setting.', array('@delta' => $delta)));
     }
diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldAttachOtherTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldAttachOtherTest.php
index ba6dd72a00c674e7980c212a730ed685f2220c64..b4ce690ca74331ba5a8f4c127e85ed3f80c45d3c 100644
--- a/core/modules/field/lib/Drupal/field/Tests/FieldAttachOtherTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/FieldAttachOtherTest.php
@@ -42,9 +42,9 @@ public function setUp() {
   }
 
   /**
-   * Test field_attach_view() and field_attach_prepare_view().
+   * Test rendering fields with EntityDisplay build().
    */
-  function testFieldAttachView() {
+  function testEntityDisplayBuild() {
     $this->createFieldWithInstance('_2');
 
     $entity_type = 'entity_test';
@@ -59,7 +59,6 @@ function testFieldAttachView() {
     // Simple formatter, label displayed.
     $entity = clone($entity_init);
     $display = entity_get_display($entity_type, $entity->bundle(), 'full');
-    $displays = array($entity->bundle() => $display);
 
     $formatter_setting = $this->randomName();
     $display_options = array(
@@ -82,18 +81,14 @@ function testFieldAttachView() {
     $display->setComponent($this->field_2->getName(), $display_options_2);
 
     // View all fields.
-    field_attach_prepare_view($entity_type, array($entity->id() => $entity), $displays);
-    $content = field_attach_view($entity, $display);
-    $output = drupal_render($content);
-    $this->content = $output;
+    $content = $display->build($entity);
+    $this->content = drupal_render($content);
     $this->assertRaw($this->instance->getLabel(), "First field's label is displayed.");
     foreach ($values as $delta => $value) {
-      $this->content = $output;
       $this->assertRaw("$formatter_setting|{$value['value']}", "Value $delta is displayed, formatter settings are applied.");
     }
     $this->assertRaw($this->instance_2->getLabel(), "Second field's label is displayed.");
     foreach ($values_2 as $delta => $value) {
-      $this->content = $output;
       $this->assertRaw("$formatter_setting_2|{$value['value']}", "Value $delta is displayed, formatter settings are applied.");
     }
 
@@ -101,19 +96,15 @@ function testFieldAttachView() {
     $entity = clone($entity_init);
     $display_options['label'] = 'hidden';
     $display->setComponent($this->field->getName(), $display_options);
-    field_attach_prepare_view($entity_type, array($entity->id() => $entity), $displays);
-    $entity->content = field_attach_view($entity, $display);
-    $output = drupal_render($entity->content);
-    $this->content = $output;
+    $content = $display->build($entity);
+    $this->content = drupal_render($content);
     $this->assertNoRaw($this->instance->getLabel(), "Hidden label: label is not displayed.");
 
     // Field hidden.
     $entity = clone($entity_init);
     $display->removeComponent($this->field->getName());
-    field_attach_prepare_view($entity_type, array($entity->id() => $entity), $displays);
-    $entity->content = field_attach_view($entity, $display);
-    $output = drupal_render($entity->content);
-    $this->content = $output;
+    $content = $display->build($entity);
+    $this->content = drupal_render($content);
     $this->assertNoRaw($this->instance->getLabel(), "Hidden field: label is not displayed.");
     foreach ($values as $delta => $value) {
       $this->assertNoRaw("$formatter_setting|{$value['value']}", "Hidden field: value $delta is not displayed.");
@@ -129,14 +120,12 @@ function testFieldAttachView() {
         'test_formatter_setting_multiple' => $formatter_setting,
       ),
     ));
-    field_attach_prepare_view($entity_type, array($entity->id() => $entity), $displays);
-    $entity->content = field_attach_view($entity, $display);
-    $output = drupal_render($entity->content);
+    $content = $display->build($entity);
+    $this->content = drupal_render($content);
     $expected_output = $formatter_setting;
     foreach ($values as $delta => $value) {
       $expected_output .= "|$delta:{$value['value']}";
     }
-    $this->content = $output;
     $this->assertRaw($expected_output, "Multiple formatter: all values are displayed, formatter settings are applied.");
 
     // Test a formatter that uses hook_field_formatter_prepare_view().
@@ -149,10 +138,8 @@ function testFieldAttachView() {
         'test_formatter_setting_additional' => $formatter_setting,
       ),
     ));
-    field_attach_prepare_view($entity_type, array($entity->id() => $entity), $displays);
-    $entity->content = field_attach_view($entity, $display);
-    $output = drupal_render($entity->content);
-    $this->content = $output;
+    $content = $display->build($entity);
+    $this->content = drupal_render($content);
     foreach ($values as $delta => $value) {
       $expected = $formatter_setting . '|' . $value['value'] . '|' . ($value['value'] + 1);
       $this->assertRaw($expected, "Value $delta is displayed, formatter settings are applied.");
@@ -163,58 +150,27 @@ function testFieldAttachView() {
   }
 
   /**
-   * Tests the 'multiple entity' behavior of field_attach_prepare_view().
+   * Tests rendering fields with EntityDisplay::buildMultiple().
    */
-  function testFieldAttachPrepareViewMultiple() {
-    $entity_type = 'entity_test';
-
-    // Set the instance to be hidden.
+  function testEntityDisplayViewMultiple() {
+    // Use a formatter that has a prepareView() step.
     $display = entity_get_display('entity_test', 'entity_test', 'full')
-      ->removeComponent($this->field->getName());
-
-    // Set up a second instance on another bundle, with a formatter that uses
-    // hook_field_formatter_prepare_view().
-    entity_test_create_bundle('test_bundle_2');
-    $formatter_setting = $this->randomName();
-    $instance_definition = $this->instance_definition;
-    $instance_definition['bundle'] = 'test_bundle_2';
-    $this->instance2 = entity_create('field_instance', $instance_definition);
-    $this->instance2->save();
-
-    $display_2 = entity_get_display('entity_test', 'test_bundle_2', 'full')
-      ->setComponent($this->field->getName(), array(
+      ->setComponent($this->field_name, array(
         'type' => 'field_test_with_prepare_view',
-        'settings' => array(
-          'test_formatter_setting_additional' => $formatter_setting,
-        ),
       ));
 
-    $displays = array('entity_test' => $display, 'test_bundle_2' => $display_2);
-
-    // Create one entity in each bundle.
-    $entity1_init = entity_create('entity_test', array('id' => 1, 'type' => 'entity_test'));
-    $values1 = $this->_generateTestFieldValues($this->field->getCardinality());
-    $entity1_init->{$this->field_name}->setValue($values1);
-
-    $entity2_init = entity_create('entity_test', array('id' => 2, 'type' => 'test_bundle_2'));
-    $values2 = $this->_generateTestFieldValues($this->field->getCardinality());
-    $entity2_init->{$this->field_name}->setValue($values2);
-
-    // Run prepare_view, and check that the entities come out as expected.
-    $entity1 = clone($entity1_init);
-    $entity2 = clone($entity2_init);
-    $entities = array($entity1->id() => $entity1, $entity2->id() => $entity2);
-    field_attach_prepare_view($entity_type, $entities, $displays);
-    $this->assertFalse(isset($entity1->{$this->field_name}->additional_formatter_value), 'Entity 1 did not run through the prepare_view hook.');
-    $this->assertTrue(isset($entity2->{$this->field_name}->additional_formatter_value), 'Entity 2 ran through the prepare_view hook.');
-
-    // Same thing, reversed order.
-    $entity1 = clone($entity1_init);
-    $entity2 = clone($entity2_init);
-    $entities = array($entity1->id() => $entity1, $entity2->id() => $entity2);
-    field_attach_prepare_view($entity_type, $entities, $displays);
-    $this->assertFalse(isset($entity1->{$this->field_name}->additional_formatter_value), 'Entity 1 did not run through the prepare_view hook.');
-    $this->assertTrue(isset($entity2->{$this->field_name}->additional_formatter_value), 'Entity 2 ran through the prepare_view hook.');
+    // Create two entities.
+    $entity1 = entity_create('entity_test', array('id' => 1, 'type' => 'entity_test'));
+    $entity1->{$this->field_name}->setValue($this->_generateTestFieldValues(1));
+    $entity2 = entity_create('entity_test', array('id' => 2, 'type' => 'test_bundle'));
+    $entity2->{$this->field_name}->setValue($this->_generateTestFieldValues(1));
+
+    // Run buildMultiple(), and check that the entities come out as expected.
+    $display->buildMultiple(array($entity1, $entity2));
+    $item1 = $entity1->{$this->field_name}[0];
+    $this->assertEqual($item1->additional_formatter_value, $item1->value + 1, 'Entity 1 ran through the prepareView() formatter method.');
+    $item2 = $entity2->{$this->field_name}[0];
+    $this->assertEqual($item2->additional_formatter_value, $item2->value + 1, 'Entity 2 ran through the prepareView() formatter method.');
   }
 
   /**
diff --git a/core/modules/field/tests/modules/field_test/field_test.module b/core/modules/field/tests/modules/field_test/field_test.module
index 8215416b7873b055a2299a1ad5c59b80bbd89f18..a524bb9f0abf98a4510eb0a473e9649ba1715e35 100644
--- a/core/modules/field/tests/modules/field_test/field_test.module
+++ b/core/modules/field/tests/modules/field_test/field_test.module
@@ -112,15 +112,16 @@ function field_test_field_entity_create(FieldInterface $field) {
 }
 
 /**
- * Implements hook_field_attach_view_alter().
+ * Implements hook_entity_display_build_alter().
  */
-function field_test_field_attach_view_alter(&$output, $context) {
-  if (!empty($context['display_options']['settings']['alter'])) {
-    $output['test_field'][] = array('#markup' => 'field_test_field_attach_view_alter');
+function field_test_entity_display_build_alter(&$output, $context) {
+  $display_options = $context['display']->getComponent('test_field');
+  if (isset($display_options['settings']['alter'])) {
+    $output['test_field'][] = array('#markup' => 'field_test_entity_display_build_alter');
   }
 
   if (isset($output['test_field'])) {
-    $output['test_field'][] = array('#markup' => 'field language is ' . $context['langcode']);
+    $output['test_field'][] = array('#markup' => 'entity language is ' . $context['entity']->language()->id);
   }
 }
 
diff --git a/core/modules/link/lib/Drupal/link/Tests/LinkFieldTest.php b/core/modules/link/lib/Drupal/link/Tests/LinkFieldTest.php
index bf61616dc2b783ec0ba52990db29032e450b30c7..fa86ecbc8e89e3cf25935c5f3c35b9149536b06f 100644
--- a/core/modules/link/lib/Drupal/link/Tests/LinkFieldTest.php
+++ b/core/modules/link/lib/Drupal/link/Tests/LinkFieldTest.php
@@ -516,10 +516,8 @@ protected function renderTestEntity($id, $view_mode = 'full', $reset = TRUE) {
     }
     $entity = entity_load('entity_test', $id);
     $display = entity_get_display($entity->getEntityTypeId(), $entity->bundle(), $view_mode);
-    field_attach_prepare_view('entity_test', array($entity->id() => $entity), array($entity->bundle() => $display));
-    $entity->content = field_attach_view($entity, $display);
-
-    $output = drupal_render($entity->content);
+    $content = $display->build($entity);
+    $output = drupal_render($content);
     $this->drupalSetContent($output);
     $this->verbose($output);
   }
diff --git a/core/modules/node/node.api.php b/core/modules/node/node.api.php
index ffcd635211739acd26b57e697822d2c0ad609f28..ab7811e64940672b439961a94dc52de6fdfe7def 100644
--- a/core/modules/node/node.api.php
+++ b/core/modules/node/node.api.php
@@ -61,9 +61,8 @@
  *   - hook_node_load() (all)
  * - Viewing a single node (calling node_view() - note that the input to
  *   node_view() is a loaded node, so the Loading steps above are already done):
- *   - field_attach_prepare_view()
  *   - hook_entity_prepare_view() (all)
- *   - field_attach_view()
+ *   - hook_entity_display_build_alter() (all)
  *   - hook_node_view() (all)
  *   - hook_entity_view() (all)
  *   - hook_node_view_alter() (all)
@@ -71,9 +70,8 @@
  * - Viewing multiple nodes (calling node_view_multiple() - note that the input
  *   to node_view_multiple() is a set of loaded nodes, so the Loading steps
  *   above are already done):
- *   - field_attach_prepare_view()
  *   - hook_entity_prepare_view() (all)
- *   - field_attach_view()
+ *   - hook_entity_display_build_alter() (all)
  *   - hook_node_view() (all)
  *   - hook_entity_view() (all)
  *   - hook_node_view_alter() (all)
diff --git a/core/modules/system/entity.api.php b/core/modules/system/entity.api.php
index 928d292bed6bca479752ce022af271c7233ab239..852f7f9e7779ec2f505a29a190ce41447f7caae2 100644
--- a/core/modules/system/entity.api.php
+++ b/core/modules/system/entity.api.php
@@ -514,7 +514,7 @@ function hook_entity_view_alter(&$build, Drupal\Core\Entity\EntityInterface $ent
  *   The type of entities being viewed (i.e. node, user, comment).
  * @param array $entities
  *   The entities keyed by entity ID.
- * @param \Drupal\Core\Entity\EntityViewDisplayInterface[] $displays
+ * @param \Drupal\Core\Entity\Display\EntityViewDisplayInterface[] $displays
  *   The array of entity view displays holding the display options configured
  *   for the entity components, keyed by bundle name.
  * @param string $view_mode
@@ -583,6 +583,35 @@ function hook_entity_view_display_alter(\Drupal\Core\Entity\Display\EntityViewDi
   }
 }
 
+/**
+ * Alter the render array generated by an EntityDisplay for an entity.
+ *
+ * @param array $build
+ *   The renderable array generated by the EntityDisplay.
+ * @param array $context
+ *   An associative array containing:
+ *   - entity: The entity being rendered.
+ *   - view_mode: The view mode; for example, 'full' or 'teaser'.
+ *   - display: The EntityDisplay holding the display options.
+ */
+function hook_entity_display_build_alter(&$build, $context) {
+  // Append RDF term mappings on displayed taxonomy links.
+  foreach (element_children($build) as $field_name) {
+    $element = &$build[$field_name];
+    if ($element['#field_type'] == 'entity_reference' && $element['#formatter'] == 'entity_reference_label') {
+      foreach ($element['#items'] as $delta => $item) {
+        $term = $item->entity;
+        if (!empty($term->rdf_mapping['rdftype'])) {
+          $element[$delta]['#options']['attributes']['typeof'] = $term->rdf_mapping['rdftype'];
+        }
+        if (!empty($term->rdf_mapping['name']['predicates'])) {
+          $element[$delta]['#options']['attributes']['property'] = $term->rdf_mapping['name']['predicates'];
+        }
+      }
+    }
+  }
+}
+
 /**
  * Acts on an entity object about to be shown on an entity form.
  *
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldMultipleVocabularyTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldMultipleVocabularyTest.php
index 9a2aa4396a2f9915604567d20a6bca7cc2eec5ab..098286468ddcf8b48f876d9cc6b93ec1edd76537 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldMultipleVocabularyTest.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldMultipleVocabularyTest.php
@@ -100,11 +100,9 @@ function testTaxonomyTermFieldMultipleVocabularies() {
 
     // Render the entity.
     $entity = entity_load('entity_test', $id);
-    $entities = array($id => $entity);
     $display = entity_get_display($entity->getEntityTypeId(), $entity->bundle(), 'full');
-    field_attach_prepare_view('entity_test', $entities, array($entity->bundle() => $display));
-    $entity->content = field_attach_view($entity, $display);
-    $this->content = drupal_render($entity->content);
+    $content = $display->build($entity);
+    $this->drupalSetContent(drupal_render($content));
     $this->assertText($term1->label(), 'Term 1 name is displayed.');
     $this->assertText($term2->label(), 'Term 2 name is displayed.');
 
@@ -113,12 +111,9 @@ function testTaxonomyTermFieldMultipleVocabularies() {
 
     // Re-render the content.
     $entity = entity_load('entity_test', $id);
-    $entities = array($id => $entity);
     $display = entity_get_display($entity->getEntityTypeId(), $entity->bundle(), 'full');
-    field_attach_prepare_view('entity_test', $entities, array($entity->bundle() => $display));
-    $entity->content = field_attach_view($entity, $display);
-    $this->plainTextContent = FALSE;
-    $this->content = drupal_render($entity->content);
+    $content = $display->build($entity);
+    $this->drupalSetContent(drupal_render($content));
 
     // Term 1 should still be displayed; term 2 should not be.
     $this->assertText($term1->label(), 'Term 1 name is displayed.');
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldTest.php
index 13e4fd3e5df018edc5b111d41a09679643e0d82c..ce24d95e7aea665016b6944ec53ada925e7b63d2 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldTest.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldTest.php
@@ -117,11 +117,9 @@ function testTaxonomyTermFieldWidgets() {
 
     // Display the object.
     $entity = entity_load('entity_test', $id);
-    $entities = array($id => $entity);
     $display = entity_get_display($entity->getEntityTypeId(), $entity->bundle(), 'full');
-    field_attach_prepare_view('entity_test', $entities, array($entity->bundle() => $display));
-    $entity->content = field_attach_view($entity, $display);
-    $this->content = drupal_render($entity->content);
+    $content = $display->build($entity);
+    $this->drupalSetContent(drupal_render($content));
     $this->assertText($term->label(), 'Term label is displayed.');
 
     // Delete the vocabulary and verify that the widget is gone.
diff --git a/core/modules/text/lib/Drupal/text/Tests/Formatter/TextPlainUnitTest.php b/core/modules/text/lib/Drupal/text/Tests/Formatter/TextPlainUnitTest.php
index 82b20437092204a56ec10fe15fa4c487306db7a9..2890f27bea2174225ea72bb46049457133023818 100644
--- a/core/modules/text/lib/Drupal/text/Tests/Formatter/TextPlainUnitTest.php
+++ b/core/modules/text/lib/Drupal/text/Tests/Formatter/TextPlainUnitTest.php
@@ -7,9 +7,9 @@
 
 namespace Drupal\text\Tests\Formatter;
 
-use Drupal\Core\Entity\EntityInterface;
-use Drupal\Core\Language\Language;
+use Drupal\Core\Entity\ContentEntityInterface;
 use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
+use Drupal\Core\Language\Language;
 use Drupal\simpletest\DrupalUnitTestBase;
 
 /**
@@ -116,13 +116,13 @@ protected function createEntity($values = array()) {
   /**
    * Renders fields of a given entity with a given display.
    *
-   * @param \Drupal\Core\Entity\EntityInterface $entity
+   * @param \Drupal\Core\Entity\ContentEntityInterface $entity
    *   The entity object with attached fields to render.
    * @param \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display
    *   The display to render the fields in.
    */
-  protected function renderEntityFields(EntityInterface $entity, EntityViewDisplayInterface $display) {
-    $content = field_attach_view($entity, $display);
+  protected function renderEntityFields(ContentEntityInterface $entity, EntityViewDisplayInterface $display) {
+    $content = $display->build($entity);
     $this->content = drupal_render($content);
     return $this->content;
   }
diff --git a/core/modules/text/lib/Drupal/text/Tests/TextFieldTest.php b/core/modules/text/lib/Drupal/text/Tests/TextFieldTest.php
index 8ba14cab7a67a9ed5151ecabfc15b879de406b91..e68a752fca096774c3cf1149812478a24decf69e 100644
--- a/core/modules/text/lib/Drupal/text/Tests/TextFieldTest.php
+++ b/core/modules/text/lib/Drupal/text/Tests/TextFieldTest.php
@@ -139,8 +139,8 @@ function _testTextfieldWidgets($field_type, $widget_type) {
     // Display the entity.
     $entity = entity_load('entity_test', $id);
     $display = entity_get_display($entity->getEntityTypeId(), $entity->bundle(), 'full');
-    $entity->content = field_attach_view($entity, $display);
-    $this->drupalSetContent(drupal_render($entity->content));
+    $content = $display->build($entity);
+    $this->drupalSetContent(drupal_render($content));
     $this->assertText($value, 'Filtered tags are not displayed');
   }
 
@@ -212,8 +212,8 @@ function _testTextfieldWidgetsFormatted($field_type, $widget_type) {
     // Display the entity.
     $entity = entity_load('entity_test', $id);
     $display = entity_get_display($entity->getEntityTypeId(), $entity->bundle(), 'full');
-    $entity->content = field_attach_view($entity, $display);
-    $this->content = drupal_render($entity->content);
+    $content = $display->build($entity);
+    $this->drupalSetContent(drupal_render($content));
     $this->assertNoRaw($value, 'HTML tags are not displayed.');
     $this->assertRaw(check_plain($value), 'Escaped HTML is displayed correctly.');
 
@@ -254,8 +254,8 @@ function _testTextfieldWidgetsFormatted($field_type, $widget_type) {
     $this->container->get('entity.manager')->getStorageController('entity_test')->resetCache(array($id));
     $entity = entity_load('entity_test', $id);
     $display = entity_get_display($entity->getEntityTypeId(), $entity->bundle(), 'full');
-    $entity->content = field_attach_view($entity, $display);
-    $this->content = drupal_render($entity->content);
+    $content = $display->build($entity);
+    $this->drupalSetContent(drupal_render($content));
     $this->assertRaw($value, 'Value is displayed unfiltered');
   }
 }