Android四大组件:Activity详解(一)基础概念与生命周期

Activity生命周期与启动模式(一):基础概念与生命周期

本文是Android四大组件系列的第一篇,主要介绍Activity的基本概念、生命周期以及实际应用场景。

一、Activity简介

Activity是Android应用程序的核心组件之一,它提供了一个用户界面,让用户可以与应用程序进行交互。从用户体验的角度来看,Activity就像是应用程序的"窗口"或"页面"。一个Android应用通常由多个Activity组成,它们之间可以相互跳转,共同构成了应用的用户界面流程。

1.1 Activity的作用

  • 提供用户界面:Activity是用户与应用交互的主要入口
  • 管理用户输入:处理屏幕触摸、键盘输入等用户操作
  • 处理应用逻辑:响应用户操作,执行相应的业务逻辑
  • 协调应用组件:与其他组件(如Service、BroadcastReceiver等)进行交互

1.2 Activity的基本使用

要创建一个Activity,需要完成以下步骤:

  1. 创建一个类继承自Activity或其子类(如AppCompatActivity
  2. 实现必要的生命周期方法,如onCreate()
  3. AndroidManifest.xml中声明该Activity
// 1. 创建Activity类
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 设置布局文件
        setContentView(R.layout.activity_main);
        
        // 初始化视图、设置监听器等
        Button btnStart = findViewById(R.id.btn_start);
        btnStart.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 启动另一个Activity
                Intent intent = new Intent(MainActivity.this, SecondActivity.class);
                startActivity(intent);
            }
        });
    }
}
<!-- 2. 在AndroidManifest.xml中声明Activity -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <application>
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".SecondActivity" />
    </application>
</manifest>

二、Activity生命周期

2.1 生命周期概述

Activity的生命周期是指从创建到销毁的整个过程,Android系统通过一系列回调方法来管理Activity的生命周期。了解这些生命周期方法对于开发高质量的Android应用至关重要。

主要的生命周期方法包括:

  • onCreate():Activity创建时调用
  • onStart():Activity变为可见时调用
  • onResume():Activity获取焦点,可与用户交互时调用
  • onPause():Activity失去焦点,但仍部分可见时调用
  • onStop():Activity完全不可见时调用
  • onRestart():Activity从停止状态重新变为可见前调用
  • onDestroy():Activity被销毁前调用

2.2 生命周期方法详解

onCreate()
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Log.d("LifeCycle", "onCreate called");
    
    // 初始化操作:获取Intent数据、初始化视图、绑定数据等
    if (savedInstanceState != null) {
        // 恢复之前保存的状态
        String savedText = savedInstanceState.getString("saved_text");
        // 使用恢复的数据
    }
}

适合做的事情

  • 设置布局(setContentView)
  • 初始化视图组件
  • 绑定数据
  • 创建长期运行的组件(如线程)
  • 恢复保存的状态

注意事项

  • 这里的操作应尽量轻量级,避免耗时操作
  • 不要在这里请求运行时权限,应在视图完全显示后请求
onStart()
@Override
protected void onStart() {
    super.onStart();
    Log.d("LifeCycle", "onStart called");
    
    // Activity变为可见,但用户还不能与之交互
}

适合做的事情

  • 注册需要在Activity可见时监听的广播接收器
  • 启动只在Activity可见时需要运行的服务
onResume()
@Override
protected void onResume() {
    super.onResume();
    Log.d("LifeCycle", "onResume called");
    
    // Activity获取焦点,用户可以与之交互
    // 启动需要在前台运行的功能,如动画、相机预览等
}

适合做的事情

  • 启动需要用户交互的功能(如相机、传感器、动画)
  • 恢复在onPause()中暂停的操作
  • 初始化在其他Activity可能修改的组件
onPause()
@Override
protected void onPause() {
    // 暂停或释放在onResume中启动的资源
    // 保存关键数据,但要快速执行(不到1秒)
    Log.d("LifeCycle", "onPause called");
    super.onPause();
}

适合做的事情

  • 暂停消耗CPU的操作
  • 暂停媒体播放
  • 释放系统资源(如相机、传感器)
  • 保存未保存的数据(但操作要快)

注意事项

  • 这个方法执行时间很短,不适合做耗时操作
  • 不要在这里保存大量数据到数据库或网络
onStop()
@Override
protected void onStop() {
    // Activity完全不可见,可以执行较重的关闭操作
    Log.d("LifeCycle", "onStop called");
    super.onStop();
}

适合做的事情

  • 执行CPU密集型关闭操作
  • 保存用户数据到持久化存储
  • 解注册广播接收器
  • 释放资源
onRestart()
@Override
protected void onRestart() {
    super.onRestart();
    Log.d("LifeCycle", "onRestart called");
    
    // Activity从停止状态重新变为可见前调用
    // 之后会调用onStart()
}

适合做的事情

  • 准备Activity重新变为可见所需的特殊处理
onDestroy()
@Override
protected void onDestroy() {
    // 释放所有资源,防止内存泄漏
    Log.d("LifeCycle", "onDestroy called");
    super.onDestroy();
}

适合做的事情

  • 释放所有资源
  • 关闭数据库连接
  • 注销监听器
  • 销毁长期运行的后台任务

2.3 生命周期的完整示例

下面是一个完整的Activity生命周期示例,包含所有生命周期方法的实现和日志记录:

public class LifecycleDemoActivity extends AppCompatActivity {
    private static final String TAG = "LifecycleDemoActivity";
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_lifecycle_demo);
        Log.d(TAG, "onCreate called");
        
        Button nextButton = findViewById(R.id.btn_next);
        nextButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 启动另一个Activity
                Intent intent = new Intent(LifecycleDemoActivity.this, SecondActivity.class);
                startActivity(intent);
            }
        });
    }
    
    @Override
    protected void onStart() {
        super.onStart();
        Log.d(TAG, "onStart called");
    }
    
    @Override
    protected void onResume() {
        super.onResume();
        Log.d(TAG, "onResume called");
    }
    
    @Override
    protected void onPause() {
        Log.d(TAG, "onPause called");
        super.onPause();
    }
    
    @Override
    protected void onStop() {
        Log.d(TAG, "onStop called");
        super.onStop();
    }
    
    @Override
    protected void onRestart() {
        super.onRestart();
        Log.d(TAG, "onRestart called");
    }
    
    @Override
    protected void onDestroy() {
        Log.d(TAG, "onDestroy called");
        super.onDestroy();
    }
    
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        // 保存Activity状态
        outState.putString("saved_text", "Some text to save");
        Log.d(TAG, "onSaveInstanceState called");
        super.onSaveInstanceState(outState);
    }
    
    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        // 恢复Activity状态
        String savedText = savedInstanceState.getString("saved_text");
        Log.d(TAG, "onRestoreInstanceState called: " + savedText);
    }
}

三、Activity状态保存与恢复

在Android系统中,当配置发生变化(如屏幕旋转)或系统内存不足时,Activity可能会被销毁并重新创建。为了提供良好的用户体验,我们需要保存和恢复Activity的状态。

3.1 onSaveInstanceState() 与 onRestoreInstanceState()

@Override
protected void onSaveInstanceState(Bundle outState) {
    // 保存视图状态
    EditText editText = findViewById(R.id.edit_text);
    outState.putString("input_text", editText.getText().toString());
    
    // 保存自定义数据
    outState.putInt("counter", mCounter);
    outState.putParcelable("user_data", mUserData);
    
    Log.d(TAG, "onSaveInstanceState called");
    super.onSaveInstanceState(outState);
}

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    
    // 恢复视图状态
    String inputText = savedInstanceState.getString("input_text");
    EditText editText = findViewById(R.id.edit_text);
    editText.setText(inputText);
    
    // 恢复自定义数据
    mCounter = savedInstanceState.getInt("counter");
    mUserData = savedInstanceState.getParcelable("user_data");
    
    Log.d(TAG, "onRestoreInstanceState called");
}

3.2 ViewModel的使用

Android Jetpack提供了ViewModel组件,它可以在配置变化时保存数据,避免重复加载:

// 定义ViewModel
public class MainViewModel extends ViewModel {
    private MutableLiveData<Integer> counter = new MutableLiveData<>();
    
    public MainViewModel() {
        counter.setValue(0);
    }
    
    public LiveData<Integer> getCounter() {
        return counter;
    }
    
    public void incrementCounter() {
        counter.setValue(counter.getValue() + 1);
    }
    
    @Override
    protected void onCleared() {
        super.onCleared();
        // 清理资源
    }
}

// 在Activity中使用ViewModel
public class MainActivity extends AppCompatActivity {
    private MainViewModel viewModel;
    private TextView counterText;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        // 获取ViewModel实例
        viewModel = new ViewModelProvider(this).get(MainViewModel.class);
        
        counterText = findViewById(R.id.counter_text);
        Button incrementButton = findViewById(R.id.increment_button);
        
        // 观察LiveData变化
        viewModel.getCounter().observe(this, new Observer<Integer>() {
            @Override
            public void onChanged(Integer count) {
                counterText.setText(String.valueOf(count));
            }
        });
        
        incrementButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                viewModel.incrementCounter();
            }
        });
    }
}

四、实战案例:Activity生命周期监控

在实际开发中,了解Activity的生命周期状态对于调试和性能优化非常重要。下面我们将实现一个Activity生命周期监控工具。

4.1 创建生命周期监控基类

public abstract class BaseActivity extends AppCompatActivity {
    private static final String TAG = "ActivityLifecycle";
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, getClass().getSimpleName() + " - onCreate");
    }
    
    @Override
    protected void onStart() {
        super.onStart();
        Log.d(TAG, getClass().getSimpleName() + " - onStart");
    }
    
    @Override
    protected void onResume() {
        super.onResume();
        Log.d(TAG, getClass().getSimpleName() + " - onResume");
    }
    
    @Override
    protected void onPause() {
        Log.d(TAG, getClass().getSimpleName() + " - onPause");
        super.onPause();
    }
    
    @Override
    protected void onStop() {
        Log.d(TAG, getClass().getSimpleName() + " - onStop");
        super.onStop();
    }
    
    @Override
    protected void onRestart() {
        super.onRestart();
        Log.d(TAG, getClass().getSimpleName() + " - onRestart");
    }
    
    @Override
    protected void onDestroy() {
        Log.d(TAG, getClass().getSimpleName() + " - onDestroy");
        super.onDestroy();
    }
}

4.2 使用Lifecycle组件监控生命周期

Android Jetpack提供了Lifecycle组件,可以更方便地监控Activity的生命周期:

public class MyLifecycleObserver implements LifecycleObserver {
    private static final String TAG = "MyLifecycleObserver";
    
    @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
    public void onCreate() {
        Log.d(TAG, "ON_CREATE");
    }
    
    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    public void onStart() {
        Log.d(TAG, "ON_START");
    }
    
    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    public void onResume() {
        Log.d(TAG, "ON_RESUME");
    }
    
    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    public void onPause() {
        Log.d(TAG, "ON_PAUSE");
    }
    
    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    public void onStop() {
        Log.d(TAG, "ON_STOP");
    }
    
    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    public void onDestroy() {
        Log.d(TAG, "ON_DESTROY");
    }
}

// 在Activity中使用
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        // 添加生命周期观察者
        getLifecycle().addObserver(new MyLifecycleObserver());
    }
}

4.3 调试技巧:使用Fragment监控Activity生命周期

可以创建一个无UI的Fragment来监控Activity的生命周期,这在复杂应用中特别有用:

public class LifecycleLoggerFragment extends Fragment {
    private static final String TAG = "LifecycleLogger";
    private String activityName;
    
    public static LifecycleLoggerFragment newInstance(String activityName) {
        LifecycleLoggerFragment fragment = new LifecycleLoggerFragment();
        Bundle args = new Bundle();
        args.putString("activity_name", activityName);
        fragment.setArguments(args);
        return fragment;
    }
    
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true); // 在配置变化时保留实例
        activityName = getArguments().getString("activity_name");
    }
    
    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        Log.d(TAG, activityName + " - onAttach");
    }
    
    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        Log.d(TAG, activityName + " - onActivityCreated");
    }
    
    // 其他生命周期方法...
}

// 在Activity中使用
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        // 添加生命周期监控Fragment
        if (savedInstanceState == null) {
            getSupportFragmentManager()
                .beginTransaction()
                .add(LifecycleLoggerFragment.newInstance(getClass().getSimpleName()), "logger")
                .commit();
        }
    }
}

五、常见面试题解析

5.1 Activity生命周期相关面试题

问题1:描述Activity的完整生命周期

答案:Activity的完整生命周期包括以下阶段:

  1. 完整生命周期:从onCreate()到onDestroy(),这期间Activity被创建、显示、隐藏直至销毁。
  2. 可见生命周期:从onStart()到onStop(),这期间Activity对用户可见,但可能没有焦点。
  3. 前台生命周期:从onResume()到onPause(),这期间Activity在前台并与用户交互。

问题2:为什么要在onPause()中保存数据而不是onStop()?

答案

  • onPause()方法一定会被调用,而在极端情况下(如内存不足),系统可能会直接杀死Activity而不调用onStop()和onDestroy()。
  • 但需注意onPause()执行时间很短(不到1秒),所以只适合做轻量级的保存操作,复杂的持久化操作应放在onStop()中。

问题3:屏幕旋转时Activity的生命周期变化是什么?如何保持数据?

答案

  • 屏幕旋转时,默认情况下Activity会被销毁并重新创建,生命周期流程为:onPause() -> onStop() -> onDestroy() -> onCreate() -> onStart() -> onResume()
  • 保持数据的方法有:
    1. 使用onSaveInstanceState()和onRestoreInstanceState()保存和恢复数据
    2. 使用ViewModel组件,它在配置变化时不会被销毁
    3. 在AndroidManifest中设置android:configChanges=“orientation|screenSize”,阻止Activity重建
    4. 使用Fragment的setRetainInstance(true)

问题4:onSaveInstanceState()和onRestoreInstanceState()调用时机是什么?

答案

  • onSaveInstanceState()在Activity可能被销毁前调用,通常在onStop()之前,但不一定在onPause()之后。
  • onRestoreInstanceState()在onCreate()之后调用,但只有在有状态需要恢复时才会被调用。
  • onCreate()方法也可以从savedInstanceState参数恢复状态,区别是onRestoreInstanceState()一定有非空的Bundle参数。

问题5:如何避免Activity重建时的闪烁问题?

答案

  1. 在主题中设置windowDisablePreview属性
  2. 使用android:configChanges="orientation|screenSize"阻止重建
  3. 优化布局加载速度,减少onCreate()中的耗时操作
  4. 使用Transition框架实现平滑过渡

5.2 实际开发中的生命周期问题

问题1:如何处理Activity被系统回收后的数据恢复问题?

答案

  1. 使用onSaveInstanceState()保存关键数据
  2. 使用ViewModel存储UI相关数据
  3. 对于大量数据,考虑使用持久化存储(如Room数据库)
  4. 使用单例或Application级别的缓存
  5. 实现Parcelable接口优化序列化性能

问题2:如何解决Activity内存泄漏问题?

答案

  1. 避免在Activity中使用静态变量引用Activity或Context
  2. 正确处理内部类和匿名类,使用弱引用或静态内部类+弱引用
  3. 在onDestroy()中取消异步任务和注销监听器
  4. 使用LeakCanary等工具检测内存泄漏
  5. 避免在生命周期方法外持有View引用

六、开源项目实战分析

6.1 分析LeakCanary中的Activity生命周期监控

LeakCanary是一个内存泄漏检测库,它通过监控Activity的生命周期来检测潜在的内存泄漏。

// LeakCanary中的ActivityLifecycleCallbacks实现(简化版)
public class ActivityLifecycleMonitor implements Application.ActivityLifecycleCallbacks {
    @Override
    public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
        // 记录Activity创建
    }
    
    @Override
    public void onActivityDestroyed(Activity activity) {
        // 当Activity销毁时,检查是否存在内存泄漏
        // 通过弱引用和引用队列检测Activity是否被正确回收
        watchForLeak(activity);
    }
    
    private void watchForLeak(Activity activity) {
        // 创建弱引用并关联引用队列
        // 延迟检查Activity是否被回收
        // 如果没有被回收,触发堆转储并分析泄漏路径
    }
    
    // 其他生命周期回调方法...
}

6.2 分析Glide中的生命周期管理

Glide是一个流行的图片加载库,它会根据Activity/Fragment的生命周期自动管理图片加载任务。

// Glide中的生命周期监听(简化版)
public class RequestManager implements LifecycleListener {
    
    public RequestManager(Lifecycle lifecycle) {
        // 注册生命周期监听
        lifecycle.addListener(this);
    }
    
    @Override
    public void onStart() {
        // 恢复暂停的请求
        resumeRequests();
    }
    
    @Override
    public void onStop() {
        // 暂停请求,释放资源
        pauseRequests();
    }
    
    @Override
    public void onDestroy() {
        // 清理资源,取消请求
        clearRequests();
    }
}

总结

本文详细介绍了Activity的基本概念和生命周期,包括各个生命周期方法的调用时机和适合执行的操作。我们还学习了如何保存和恢复Activity状态,以及使用ViewModel等现代组件简化状态管理。通过实战案例和开源项目分析,我们了解了如何在实际开发中应用这些知识。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

键盘小码哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值