Frame Rate en aplicaciones móviles — qué es, fps y cómo mejorar

Autor: IT Sectr Publicado: 2026-03-31 Tiempo de lectura: 10 min

Frame Rate es la cantidad de cuadros que un sistema gráfico muestra por segundo. En aplicaciones móviles, la frecuencia de cuadros determina directamente la fluidez de las animaciones, el desplazamiento y las transiciones entre pantallas. Según Android Developers, 2025, el Frame Rate objetivo es de 60 fps para pantallas estándar y 120 fps para dispositivos con alta frecuencia de actualización. La desviación del valor objetivo provoca tartamudeos visuales y degrada la experiencia del usuario.

Puntos clave

  • Frame Rate es la cantidad de cuadros por segundo (fps) que determina la fluidez de la interfaz.
  • El Frame Rate objetivo estándar es 60 fps, correspondiente a 16.6 ms por cuadro.
  • Los dispositivos con pantallas de 120 Hz requieren 120 fps (8.3 ms por cuadro).
  • Los cuadros perdidos causan Jank — tartamudeo notable en las animaciones.
  • Perfilar el Frame Rate es el primer paso hacia la optimización del rendimiento de la interfaz.

Qué es Frame Rate

Frame Rate (frecuencia de cuadros) es una métrica medida en cuadros por segundo (fps) que indica cuántas veces por segundo una aplicación actualiza la imagen en la pantalla. El ojo humano percibe el movimiento como fluido a partir de 24 fps (cine), pero la interfaz interactiva requiere al menos 60 fps para que los toques y las animaciones se sientan instantáneos. Cada cuadro es un ciclo completo: procesamiento de la entrada del usuario, cálculo del Layout, renderizado de la jerarquía de vistas y salida a la pantalla. Si alguna de estas etapas supera el presupuesto de tiempo asignado (16.6 ms a 60 fps), el cuadro se salta y el usuario ve un tartamudeo.

Es importante distinguir entre el Frame Rate de la aplicación y la frecuencia de actualización de la pantalla (Refresh Rate). La frecuencia de actualización es una característica del hardware: cuántas veces por segundo la pantalla actualiza físicamente la imagen (60, 90, 120 o 144 Hz). El Frame Rate es cuántos cuadros por segundo logra renderizar la aplicación. Si la aplicación produce 60 fps en una pantalla de 120 Hz, cada segundo cuadro se duplicará — la imagen seguirá siendo fluida pero no tan receptiva como podría ser. Según Google I/O 2023, los buques insignia modernos pueden mantener 120 fps en escenarios simples de interfaz, pero bajo carga pesada (juegos, listas complejas) la frecuencia baja a 40–60 fps.

Cómo funciona el renderizado de cuadros

El renderizado de cuadros en una aplicación móvil pasa por un pipeline de varias etapas. En Android, el pipeline incluye: procesamiento de entrada (Input), animación (Animation), medición y disposición (Layout), dibujo (Draw), sincronización con GPU y salida a pantalla (Swap). Cada etapa se ejecuta en la CPU o GPU, y el tiempo total de todas las etapas no debe superar el presupuesto del cuadro. Para 60 fps el presupuesto es de 16.6 ms, para 120 fps — 8.3 ms. Choreographer (Android) y CADisplayLink (iOS) sincronizan el renderizado con el intervalo de blanking vertical de la pantalla (VSync), garantizando que el cuadro se muestre solo en el momento de actualización de la pantalla, evitando el tearing.

En iOS, el pipeline es similar: Run Loop procesa eventos, Core Animation calcula capas, Render Server (un proceso separado) renderiza y envía el cuadro a la GPU. La diferencia en iOS es el proceso dedicado Render Server, que aísla el renderizado de la aplicación principal. Si la aplicación bloquea el hilo principal, Render Server aún puede dibujar el último cuadro conocido, pero las animaciones se detendrán. Si Render Server no puede seguir el ritmo — la GPU se queda inactiva y el Frame Rate baja. Según Apple WWDC 2022, las causas más comunes de bajo Frame Rate en iOS son el anidamiento excesivo de CALayer, shadowPath pesado y el renderizado fuera de pantalla.

Seguimiento de cuadros mediante Choreographer

El código en Kotlin se suscribe a Choreographer.FrameCallback y registra el tiempo real entre cuadros. Si el intervalo supera los 16.6 ms, se registra un cuadro perdido.

kotlin
class FrameRateMonitor {

    private var lastFrameTime = 0L
    private val frameCallback =
        Choreographer.FrameCallback { frameTimeNanos ->
            if (lastFrameTime != 0L) {
                val deltaMs = (frameTimeNanos - lastFrameTime) / 1_000_000f
                if (deltaMs > 16.6f) {
                    Log.w("FrameRate",
                        "Skipped frame: $deltaMs ms")
                }
            }
            lastFrameTime = frameTimeNanos
            Choreographer.getInstance()
                .postFrameCallback(this)
        }

    fun start() {
        Choreographer.getInstance()
            .postFrameCallback(frameCallback)
    }
}

Frecuencia de actualización de pantalla y Frame Rate

Refresh Rate (frecuencia de actualización) es una característica de hardware de la pantalla que determina cuántas veces por segundo el monitor redibuja físicamente la imagen. Las pantallas estándar tienen 60 Hz, los buques insignia modernos tienen 90, 120 o 144 Hz. El Frame Rate de la aplicación puede ser menor, igual o mayor que la frecuencia de actualización (en este último caso, los cuadros sobrantes se descartan). El escenario ideal es cuando Frame Rate coincide con Refresh Rate: cada ciclo de hardware recibe un nuevo cuadro de la aplicación y el movimiento es máximo de fluido. Si Frame Rate es menor, la pantalla repite el último cuadro, lo que se percibe como micro-tartamudeos.

Android e iOS admiten el cambio dinámico de frecuencia de actualización. Android 12+ usa Smart Refresh Rate: durante el desplazamiento el sistema eleva la frecuencia a 120 Hz, en contenido estático la baja a 60 Hz para ahorrar batería. iOS ProMotion (iPhone 13 Pro y posteriores) funciona de manera similar — la frecuencia varía de 10 a 120 Hz según el contenido. El desarrollador debe verificar si el dispositivo admite alta frecuencia y adaptar el presupuesto de tiempo por cuadro. Si la aplicación no puede renderizar un cuadro en 8.3 ms (para 120 Hz), es mejor forzar 60 Hz — esto garantizará un Frame Rate estable sin cuadros perdidos.

Tipo de pantallaRefresh RatePresupuesto por cuadroDispositivos
Estándar60 Hz16.6 msLa mayoría Android/iOS
Alta90 Hz11.1 msOnePlus, Pixel 6+
Insignia120 Hz8.3 msiPhone Pro, Galaxy S22+
Juegos144 Hz6.9 msROG Phone, Nubia RedMagic

Herramientas de medición de Frame Rate

Tanto las herramientas integradas de las plataformas como los perfiladores de terceros están disponibles para medir el Frame Rate en aplicaciones móviles. En Android, la herramienta principal es GPU Profiling (Developer Options → Profile GPU Rendering), que muestra una línea de tiempo de cada cuadro desglosada por etapas (Draw, Prepare, Process, Execute). Un análisis más detallado lo proporciona Android Studio Profiler — registra un perfil completo de renderizado indicando las Vistas específicas que causan redibujados. En iOS, se utiliza Instruments con la plantilla Core Animation — muestra FPS, tiempo de renderizado de capas y la cantidad de renders fuera de pantalla.

Para la monitorización de Frame Rate en producción, se utiliza Firebase Performance (Android) — recopila Frame Rate en segundo plano y lo agrega por dispositivo, versión del SO y sesión. En iOS, MetricKit proporciona datos similares a través de MXAnimatoryMetric. Para juegos y aplicaciones Flutter, se utilizan FrameTimingCallback (Flutter) y Unity Profiler. Es importante medir no el Frame Rate promedio sino los percentiles: P50, P90 y P99. Una aplicación puede mostrar un promedio de 55 fps pero tener un P99 de 30 fps — esto significa que el 1% del tiempo los usuarios ven tartamudeos severos, suficiente para reseñas negativas.

Medición de Frame Rate en Flutter

El ejemplo en Dart muestra cómo suscribirse a FrameTimingCallback en Flutter y registrar la cantidad de cuadros perdidos. El callback se dispara después de cada cuadro completado.

dart
import 'package:flutter/scheduler.dart';

class FrameRateLogger {
    int totalFrames = 0;
    int missedFrames = 0;

    void start() {
        SchedulerBinding.instance
            .addTimingsCallback(_onReportTimings);
    }

    void _onReportTimings(List<FrameTiming> timings) {
        for (final timing in timings) {
            totalFrames++;
            if (timing.totalSpan()
                > Duration(milliseconds: 16)) {
                missedFrames++;
            }
        }
        debugPrint("FPS: \${totalFrames - missedFrames}");
    }
}

Optimización de la frecuencia de cuadros

La optimización del Frame Rate comienza con la identificación de cuellos de botella en el pipeline de renderizado. En la etapa de Layout, los principales problemas son el anidamiento excesivo de la jerarquía de vistas, el uso de layouts relativos (RelativeLayout con muchas reglas) y las llamadas frecuentes a requestLayout. La solución es usar ConstraintLayout o una jerarquía plana, evitando anidamientos de más de 5–6 niveles. En la etapa de Draw — overdraw: cuando un píxel se dibuja varias veces por cuadro. Por ejemplo, un fondo de Activity blanco debajo de un fragmento semitransparente, debajo del cual hay otra capa — cada píxel se dibuja tres veces. La herramienta Debug GPU Overdraw muestra las zonas problemáticas con indicación de color. Se recomienda mantener el overdraw en 2x o menos.

En iOS, los principales problemas son cornerRadius y masksToBounds pesados — causan renderizado fuera de pantalla, donde Core Animation crea un búfer temporal, dibuja en él y luego copia el resultado a la pantalla. El renderizado fuera de pantalla se detecta fácilmente en Instruments Core Animation: si la línea Renderer está en rojo — hay problemas. La solución es usar UIImageView con imágenes precortadas en lugar de cornerRadius, evitar groupOpacity y shouldRasterize a menos que sea absolutamente necesario. Para ambas plataformas, es crítico minimizar la cantidad de llamadas a invalidate() y setNeedsDisplay() — cada una de estas llamadas desencadena un ciclo completo de redibujado de la vista.

Optimización de jerarquía en Android

El código demuestra cómo reemplazar el anidamiento profundo de RelativeLayout por una estructura plana con ConstraintLayout. Reducir el nivel de anidamiento de 4 a 1 reduce el tiempo de Layout en un 30–50%.

kotlin
// Ejemplo: estructura plana mediante ConstraintLayout
class OptimizedView(context: Context) :
    ConstraintLayout(context) {

    private val binding =
        ItemProfileBinding.inflate(
            LayoutInflater.from(context)
        )

    fun bind(user: User) {
        binding.avatar.setImageURI(user.avatarUrl)
        binding.nameText.text = user.name
        // vinculando datos sin redibujar todo el contenedor
    }
}

Frecuencias adaptativas y Dynamic Frame Rate

Las aplicaciones móviles modernas utilizan cada vez más el Frame Rate adaptativo — un sistema que ajusta dinámicamente la frecuencia objetivo según el escenario actual. El desplazamiento rápido requiere 120 fps para fluidez, mientras que una pantalla estática necesita solo 60 fps o incluso 30 fps para video. En Android, la adaptación se implementa mediante Choreographer.setFrameInterval (API 33+) y Window.setFrameRate. El desarrollador puede especificar una frecuencia preferida: setPreferredRefreshRate en SurfaceView o setFrameRate en Window. iOS gestiona automáticamente la frecuencia mediante ProMotion, pero el desarrollador puede establecer explícitamente preferredFramesPerSecond para CADisplayLink.

El Dynamic Frame Rate es especialmente importante para juegos y aplicaciones con animaciones. Según Google, reducir el Frame Rate de 120 a 60 Hz en una pantalla estática ahorra hasta un 30–40% de energía de la GPU. Para lograr el mejor equilibrio entre fluidez y consumo de energía, se recomienda: medir el Frame Rate real en diferentes escenarios, establecer los fps objetivo según la escena (juego — 60, menú — 30, video — 24), y cambiar los modos mediante componentes Lifecycle-aware para que la aplicación no malgaste recursos renderizando 120 fps en segundo plano cuando está minimizada.

Configuración del Frame Rate preferido

El código en Swift establece preferredFramesPerSecond para CADisplayLink en iOS. Durante el desplazamiento la frecuencia aumenta a 120 Hz, al detenerse disminuye a 60 Hz.

swift
class AdaptiveFrameRateManager {

    private var displayLink: CADisplayLink?

    func startWithHighRate() {
        displayLink = CADisplayLink(
            target: self,
            selector: #selector(step)
        )
        if #available(iOS 15.0, *) {
            displayLink?.preferredFrameRateRange =
                CAFrameRateRange(
                    minimum: 60,
                    maximum: 120,
                    preferred: 120
                )
        }
        displayLink?.add(to: .current,
            forMode: .common)
    }

    @objc
    private func step() {
        // actualización de animación
    }
}

Preguntas frecuentes

¿Qué Frame Rate se considera bueno para una aplicación móvil?

Para aplicaciones móviles, el Frame Rate objetivo es de 60 fps (16.6 ms por cuadro). Para dispositivos con pantallas de 120 Hz, es deseable 120 fps. Los valores por debajo de 30 fps degradan notablemente la experiencia del usuario.

¿En qué se diferencia Frame Rate de la frecuencia de actualización de la pantalla?

Frame Rate es cuántos cuadros por segundo renderiza la aplicación. Refresh Rate es cuántas veces por segundo la pantalla actualiza físicamente la imagen. Cuando Frame Rate es inferior a Refresh Rate, la pantalla duplica el último cuadro.

¿Cómo medir el Frame Rate en Android?

Use GPU Profiling en Developer Options, Android Studio Profiler o Firebase Performance. Para medición programática — Choreographer.FrameCallback con cálculo del intervalo entre cuadros.

¿Qué es overdraw y cómo afecta al Frame Rate?

Overdraw es dibujar un mismo píxel varias veces por cuadro. Cada capa adicional aumenta el tiempo de la fase Draw y reduce el Frame Rate. El overdraw óptimo es 2x, el crítico es 4x o más.

¿Cómo ahorra batería el Dynamic Frame Rate?

En contenido estático, Dynamic Frame Rate reduce la frecuencia a 30–60 Hz, disminuyendo la carga de la GPU en un 30–40%. Durante el desplazamiento, la frecuencia aumenta a 90–120 Hz para mantener la fluidez.

Resumen

  • Frame Rate es la cantidad de cuadros por segundo que determina la fluidez de la interfaz y las animaciones.
  • El Frame Rate objetivo es 60 fps (16.6 ms por cuadro) para pantallas estándar, 120 fps (8.3 ms) para alta frecuencia de actualización.
  • Los cuadros perdidos causan Jank — tartamudeo visible que degrada la experiencia del usuario.
  • Las principales causas de bajo Frame Rate son el anidamiento excesivo de vistas, overdraw y renderizado fuera de pantalla.
  • Choreographer (Android) y CADisplayLink (iOS) sincronizan el renderizado con VSync.
  • El Frame Rate adaptativo equilibra la fluidez y el consumo de energía, reduciendo la carga de la GPU hasta en un 40%.
  • Perfilar el Frame Rate es el primer paso para optimizar el rendimiento de una aplicación móvil.

Desarrollaremos una aplicación móvil llave en mano

IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.

Discutir el proyecto

Lea también