Files
english/.opencode/skills/mobile-development/references/mobile-best-practices.md
2026-04-12 01:06:31 +07:00

12 KiB

Mobile Development Best Practices

Cross-platform best practices for modern mobile development (2024-2025).

Mobile-First Design Principles

Core Principles

  1. Content First: Remove chrome, focus on content
  2. Progressive Disclosure: Hide complexity behind layers
  3. Thumb-Friendly: Primary actions within reach
  4. Performance Budget: <2s launch, <1s screen load
  5. Offline-First: Design for unreliable networks

Touch Targets

  • iOS: 44x44px minimum (HIG guideline)
  • Android: 48x48px minimum (Material Design)
  • Optimal: 44-57px for important actions
  • Spacing: 8px minimum between targets

Typography

  • iOS: San Francisco (system font)
  • Android: Roboto (Material)
  • Minimum: 16px body text (accessibility)
  • Line height: 1.5x for readability

Performance Optimization

Launch Time Optimization

Targets:

  • Cold start: <2s
  • Warm start: <1s
  • Hot start: <0.5s

Techniques:

  • Defer non-critical initialization
  • Lazy load dependencies
  • Preload critical data only
  • Show UI before data ready

Memory Management

Targets:

  • Typical screen: <100MB
  • Peak usage: <200MB

Techniques:

  • Image pagination/virtualization
  • Release resources in background
  • Profile with Instruments/Profiler
  • Avoid retain cycles/memory leaks

React Native Example:

// Use FlatList instead of ScrollView for long lists
<FlatList
  data={items}
  renderItem={({ item }) => <ItemCard item={item} />}
  keyExtractor={(item) => item.id}
  initialNumToRender={10}
  maxToRenderPerBatch={10}
  windowSize={5}
/>

Network Optimization

Techniques:

  • Batch API requests
  • Cache aggressively
  • Compress images (WebP, AVIF)
  • Use CDN for static assets
  • Implement request deduplication

Example Strategy:

User opens screen
├─ Show cached data immediately (stale-while-revalidate)
├─ Fetch fresh data in background
└─ Update UI when fresh data arrives

Battery Optimization

Techniques:

  • Batch network requests
  • Reduce GPS accuracy when possible
  • Use push instead of polling
  • Respect Doze Mode (Android)
  • Background App Refresh (iOS)

Targets:

  • Active use: <5% per hour
  • Background: <1% per hour

Offline-First Architecture

Local Storage Options

React Native:

  • AsyncStorage (small data, <6MB)
  • Realm (complex objects, relationships)
  • SQLite (relational data)
  • MMKV (fastest key-value)

Flutter:

  • SharedPreferences (small data)
  • Hive (NoSQL, fast)
  • Drift (SQLite wrapper)
  • ObjectBox (object database)

iOS:

  • UserDefaults (small data)
  • Core Data (complex objects)
  • SwiftData (modern replacement)
  • Realm

Android:

  • SharedPreferences (small data)
  • Room (SQLite ORM)
  • Realm
  • DataStore (Preferences + Proto)

Data Synchronization Strategies

1. Write-Through Cache

User makes change
├─ Update local database immediately
├─ Update UI optimistically
├─ Queue sync operation
└─ Sync to server in background

2. Hybrid Sync (Push + Pull)

Push Sync (Real-time)
├─ WebSocket connection for critical updates
└─ Immediate notification of changes

Pull Sync (Periodic)
├─ Periodic polling for non-critical data
├─ Pull on app foreground
└─ Incremental sync (only changes since last sync)

3. Conflict Resolution

  • Last-write-wins: Use timestamps
  • Operational transformation: Merge changes
  • CRDT: Conflict-free replicated data
  • Manual resolution: User chooses

Example: Offline-First Comments

// React Native + TypeScript
class CommentService {
  async postComment(text: string, postId: string) {
    const tempId = generateTempId();
    const comment = {
      id: tempId,
      text,
      postId,
      synced: false,
      timestamp: Date.now()
    };

    // 1. Save locally immediately
    await db.comments.insert(comment);

    // 2. Update UI (optimistic)
    eventBus.emit('comment:added', comment);

    // 3. Sync to server in background
    try {
      const serverComment = await api.postComment(text, postId);
      // Replace temp ID with server ID
      await db.comments.update(tempId, {
        id: serverComment.id,
        synced: true
      });
    } catch (error) {
      // Mark as pending sync, retry later
      await db.comments.update(tempId, {
        syncError: error.message
      });
      syncQueue.add({ type: 'comment', id: tempId });
    }
  }
}

Mobile Analytics & Monitoring

Analytics Platforms (2024-2025)

Firebase Analytics (Recommended)

  • Free tier generous
  • Mobile-specific events
  • Integrated with Crashlytics
  • AI-powered insights
  • Supports all platforms

Sentry

  • Error tracking + performance
  • Cross-platform support
  • Source map upload
  • Release tracking
  • Custom breadcrumbs

Amplitude

  • Product analytics
  • User behavior tracking
  • Cohort analysis
  • A/B testing integration

Essential Events to Track

User Journey:

  • App opened
  • Screen viewed
  • Feature used
  • Conversion events
  • User retention

Performance:

  • App launch time
  • Screen load time
  • API latency
  • Crash-free rate
  • ANR rate (Android)

Business:

  • Purchases
  • Subscriptions
  • Ad impressions
  • Feature adoption
  • Referrals

Crashlytics Integration

React Native:

import crashlytics from '@react-native-firebase/crashlytics';

// Log events
crashlytics().log('User tapped purchase button');

// Set user attributes
crashlytics().setUserId(user.id);

// Log non-fatal errors
try {
  await riskyOperation();
} catch (error) {
  crashlytics().recordError(error);
}

Flutter:

import 'package:firebase_crashlytics/firebase_crashlytics.dart';

// Log events
FirebaseCrashlytics.instance.log('User tapped purchase');

// Set user ID
FirebaseCrashlytics.instance.setUserIdentifier(userId);

// Record errors
await FirebaseCrashlytics.instance.recordError(
  error,
  stackTrace,
  reason: 'API call failed',
);

Push Notifications Best Practices

Platforms

  • iOS: APNs (Apple Push Notification service)
  • Android: FCM (Firebase Cloud Messaging)
  • Cross-platform: OneSignal, Firebase, AWS SNS

Best Practices

1. Permission Request Strategy

❌ Bad: Request permission on app launch
✅ Good: Request after user sees value

Flow:
1. User interacts with feature
2. Show custom modal explaining benefits
3. Request system permission
4. Handle denial gracefully

2. Personalization

  • Segment users by behavior
  • Send at optimal times (time zones)
  • Personalize content
  • A/B test messaging

3. Frequency

  • Avoid notification spam
  • Respect user preferences
  • Implement quiet hours
  • Group related notifications

4. Deep Linking

// React Native
import messaging from '@react-native-firebase/messaging';

messaging().onNotificationOpenedApp(remoteMessage => {
  const { screen, params } = remoteMessage.data;
  navigation.navigate(screen, params);
});

Impact:

  • 25% revenue increase with proper personalization
  • 88% opt-in rate with pre-permission modal (vs 40% without)

Authentication & Authorization

Modern Auth Stack (2024-2025)

Standard Pattern:

OAuth 2.0 (Authorization)
├─ JWT (Stateless auth tokens)
├─ Refresh tokens (Long-term access)
└─ Biometric (Convenient re-auth)

Implementation

Biometric Authentication (iOS)

import LocalAuthentication

let context = LAContext()
var error: NSError?

if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
    context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics,
                          localizedReason: "Unlock your account") { success, error in
        if success {
            // Authenticated
        }
    }
}

Biometric Authentication (Android)

import androidx.biometric.BiometricPrompt

val promptInfo = BiometricPrompt.PromptInfo.Builder()
    .setTitle("Biometric login")
    .setSubtitle("Log in using your biometric credential")
    .setNegativeButtonText("Use account password")
    .build()

val biometricPrompt = BiometricPrompt(this, executor,
    object : BiometricPrompt.AuthenticationCallback() {
        override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
            // Authenticated
        }
    })

biometricPrompt.authenticate(promptInfo)

Secure Token Storage

iOS: Keychain

import Security

func saveToken(_ token: String, for key: String) {
    let data = token.data(using: .utf8)!
    let query: [String: Any] = [
        kSecClass as String: kSecClassGenericPassword,
        kSecAttrAccount as String: key,
        kSecValueData as String: data,
        kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlockedThisDeviceOnly
    ]
    SecItemAdd(query as CFDictionary, nil)
}

Android: EncryptedSharedPreferences

import androidx.security.crypto.EncryptedSharedPreferences
import androidx.security.crypto.MasterKey

val masterKey = MasterKey.Builder(context)
    .setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
    .build()

val sharedPreferences = EncryptedSharedPreferences.create(
    context,
    "secure_prefs",
    masterKey,
    EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
    EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)

sharedPreferences.edit().putString("auth_token", token).apply()

React Native: react-native-keychain

import * as Keychain from 'react-native-keychain';

// Save credentials
await Keychain.setGenericPassword('username', token, {
  accessControl: Keychain.ACCESS_CONTROL.BIOMETRY_CURRENT_SET,
  accessible: Keychain.ACCESSIBLE.WHEN_UNLOCKED_THIS_DEVICE_ONLY,
});

// Retrieve credentials
const credentials = await Keychain.getGenericPassword();
const token = credentials.password;

App Store Deployment

App Store (iOS)

Requirements (2024-2025):

  • Xcode 15+ with iOS 17 SDK (minimum)
  • Xcode 16+ with iOS 18 SDK (recommended for 2025)
  • Privacy manifest required
  • Account deletion in-app mandatory

Release Process:

  1. Archive in Xcode
  2. Upload to App Store Connect
  3. Submit for review
  4. Phased release (7-day rollout)

Review Time:

  • Average: 1-2 days
  • Expedited: 1-2 hours (emergencies only)

Rejection Reasons:

  • Crashes (50%)
  • Privacy violations (25%)
  • Incomplete information (15%)
  • Guideline violations (10%)

Google Play (Android)

Requirements (2024-2025):

  • Target Android 14 (API 34) now
  • Target Android 15 (API 35) by Aug 31, 2025
  • Privacy policy required
  • Data safety form required

Release Process:

  1. Build signed AAB (Android App Bundle)
  2. Upload to Play Console
  3. Submit to production track
  4. Staged rollout (10% → 50% → 100%)

Review Time:

  • Average: 1-3 days
  • Updates: 1-2 days

Staged Rollout Strategy

Week 1:

  • 10% of users
  • Monitor crash-free rate
  • Watch for critical bugs

Week 2:

  • 50% of users
  • Validate performance metrics
  • Check user feedback

Week 3:

  • 100% of users
  • Full release if metrics healthy

Rollback Triggers:

  • Crash-free rate drops >5%
  • Critical bug discovered
  • Major user complaints

Cross-Platform Comparison

Flutter vs React Native (2024-2025)

Metric React Native Flutter
Adoption 35% 46%
Performance 80-90% 85-95%
App Size 40-50MB 15-20MB
Dev Speed Fast Very Fast
Commercial 12.57% 5.24%
Developers 20:1 ratio 1 ratio
Best For JS teams Performance

Architecture Comparison

MVVM (Small Apps):

View
 ↓
ViewModel (business logic)
 ↓
Model (data)

Clean Architecture (Large Apps):

Presentation (UI)
 ↓
Domain (business logic, use cases)
 ↓
Data (repositories, APIs, DB)

Resources

Performance:

Analytics:

Security:

Testing: