0
点赞
收藏
分享

微信扫一扫

Android Activity 使用详解:从基础到高级实践

Activity 作为 Android 应用的核心组件之一,承载了用户界面的展示和交互功能。本文将全面深入地探讨 Activity 的使用方法,涵盖生命周期管理、启动模式、数据传递、状态保存等关键知识点,并结合实际代码示例进行讲解。

一、Activity 基础概念

1.1 什么是 Activity?

Activity 是 Android 四大组件之一,它代表一个单一的屏幕界面,类似于桌面应用程序中的窗口。每个 Activity 都提供一个用户界面,用户可以通过这个界面与应用进行交互。

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

1.2 Activity 的基本结构

一个标准的 Activity 通常包含以下要素:

  • 继承自 AppCompatActivity 或 Activity
  • onCreate() 方法用于初始化
  • setContentView() 设置布局文件
  • 在 AndroidManifest.xml 中注册

二、Activity 生命周期详解

理解 Activity 生命周期是开发稳定应用的关键。以下是完整的生命周期方法:

2.1 完整生命周期方法

public class LifecycleDemoActivity extends AppCompatActivity {
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_lifecycle);
        Log.d("Lifecycle", "onCreate");
    }

    @Override
    protected void onStart() {
        super.onStart();
        Log.d("Lifecycle", "onStart");
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.d("Lifecycle", "onResume");
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.d("Lifecycle", "onPause");
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.d("Lifecycle", "onStop");
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        Log.d("Lifecycle", "onRestart");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d("Lifecycle", "onDestroy");
    }
}

2.2 生命周期状态转换图

启动Activity → onCreate → onStart → onResume → 运行状态
运行状态 → 按下Home键 → onPause → onStop → 停止状态
停止状态 → 返回应用 → onRestart → onStart → onResume → 运行状态
运行状态 → 按下返回键 → onPause → onStop → onDestroy → 销毁状态

2.3 实际应用场景

  • onCreate():初始化UI、绑定数据、创建线程或AsyncTask
  • onResume():启动动画、注册广播接收器、恢复暂停的操作
  • onPause():保存数据、停止动画、注销广播接收器
  • onDestroy():释放资源、取消网络请求

三、Activity 的启动与传参

3.1 显式启动 Activity

// 启动标准Activity
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
startActivity(intent);

// 启动带返回结果的Activity
Intent intent = new Intent(MainActivity.this, PickContactActivity.class);
startActivityForResult(intent, REQUEST_CODE_PICK_CONTACT);

3.2 隐式启动 Activity

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://www.example.com"));
startActivity(intent);

在 AndroidManifest.xml 中配置 intent-filter:

<activity android:name=".BrowserActivity">
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:scheme="http" />
    </intent-filter>
</activity>

3.3 数据传递方式

3.3.1 使用 Intent 传递基本数据

// 发送数据
Intent intent = new Intent(this, DetailActivity.class);
intent.putExtra("USER_ID", 123);
intent.putExtra("USER_NAME", "John Doe");
startActivity(intent);

// 接收数据
int userId = getIntent().getIntExtra("USER_ID", 0);
String userName = getIntent().getStringExtra("USER_NAME");

3.3.2 使用 Bundle 传递复杂数据

// 发送数据
Bundle bundle = new Bundle();
bundle.putSerializable("USER", userObject);
intent.putExtras(bundle);

// 接收数据
Bundle bundle = getIntent().getExtras();
if (bundle != null) {
    User user = (User) bundle.getSerializable("USER");
}

3.3.3 使用 Parcelable 传递对象

public class User implements Parcelable {
    private String name;
    private int age;

    // 实现Parcelable接口的方法
    protected User(Parcel in) {
        name = in.readString();
        age = in.readInt();
    }

    public static final Creator<User> CREATOR = new Creator<User>() {
        @Override
        public User createFromParcel(Parcel in) {
            return new User(in);
        }

        @Override
        public User[] newArray(int size) {
            return new User[size];
        }
    };

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(name);
        dest.writeInt(age);
    }
}

// 使用
User user = new User("John", 25);
intent.putExtra("USER", user);

3.4 处理返回结果

// 启动Activity时
startActivityForResult(intent, REQUEST_CODE);

// 在源Activity中重写onActivityResult
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == REQUEST_CODE) {
        if (resultCode == RESULT_OK) {
            String result = data.getStringExtra("RESULT");
            // 处理返回结果
        }
    }
}

// 在目标Activity中设置返回结果
Intent resultIntent = new Intent();
resultIntent.putExtra("RESULT", "Some result data");
setResult(RESULT_OK, resultIntent);
finish();

四、Activity 启动模式详解

Activity 的启动模式决定了 Activity 的实例如何与任务栈交互。

4.1 四种启动模式

4.1.1 standard(标准模式)

默认模式,每次启动都会创建新的实例。

<activity android:name=".StandardActivity" 
          android:launchMode="standard" />

4.1.2 singleTop(栈顶复用)

如果 Activity 已经在栈顶,则不会创建新实例,而是调用 onNewIntent()

<activity android:name=".SingleTopActivity" 
          android:launchMode="singleTop" />

4.1.3 singleTask(栈内复用)

系统会检查是否存在该 Activity 的任务栈,如果存在则直接复用,并清除其上所有 Activity。

<activity android:name=".SingleTaskActivity" 
          android:launchMode="singleTask" />

4.1.4 singleInstance(单实例模式)

单独位于一个任务栈中,且该任务栈只包含这一个 Activity。

<activity android:name=".SingleInstanceActivity" 
          android:launchMode="singleInstance" />

4.2 Intent Flags 控制启动行为

除了在 manifest 中设置,还可以通过 Intent Flags 动态控制:

Intent intent = new Intent(this, SomeActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // 类似singleTask
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); // 类似singleTop
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); // 清除栈顶Activity
startActivity(intent);

4.3 任务栈(Task Affinity)

通过 taskAffinity 属性可以指定 Activity 的任务栈:

<activity android:name=".TaskAffinityActivity"
          android:taskAffinity="com.example.customtask" />

五、Activity 状态保存与恢复

5.1 临时状态保存

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putString("KEY", "Value");
    outState.putInt("COUNT", count);
}

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    String value = savedInstanceState.getString("KEY");
    int count = savedInstanceState.getInt("COUNT");
}

5.2 永久数据保存

对于需要持久化的数据,应该使用 SharedPreferences、数据库或文件存储:

@Override
protected void onPause() {
    super.onPause();
    SharedPreferences prefs = getPreferences(MODE_PRIVATE);
    SharedPreferences.Editor editor = prefs.edit();
    editor.putString("AUTO_SAVE", autoSaveData);
    editor.apply();
}

@Override
protected void onResume() {
    super.onResume();
    SharedPreferences prefs = getPreferences(MODE_PRIVATE);
    String autoSaveData = prefs.getString("AUTO_SAVE", "");
}

六、Activity 高级主题

6.1 透明 Activity

创建透明背景的 Activity:

<style name="Theme.Transparent" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="android:windowIsTranslucent">true</item>
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:windowContentOverlay">@null</item>
    <item name="android:windowNoTitle">true</item>
</style>

在 AndroidManifest.xml 中应用主题:

<activity android:name=".TransparentActivity"
          android:theme="@style/Theme.Transparent" />

6.2 Activity 转场动画

6.2.1 传统方式

// 启动Activity时
startActivity(intent);
overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_left);

// 结束Activity时
finish();
overridePendingTransition(R.anim.slide_in_left, R.anim.slide_out_right);

6.2.2 使用 ActivityOptions (API 21+)

// 共享元素转场
ActivityOptions options = ActivityOptions
    .makeSceneTransitionAnimation(this, view, "transitionName");
startActivity(intent, options.toBundle());

6.3 多窗口模式支持

Android 7.0 引入了多窗口模式,需要适配:

<activity android:name=".MultiWindowActivity"
          android:resizeableActivity="true"
          android:supportsPictureInPicture="true"
          android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation" />

处理配置变化:

@Override
public void onMultiWindowModeChanged(boolean isInMultiWindowMode) {
    super.onMultiWindowModeChanged(isInMultiWindowMode);
    // 调整UI布局
}

@Override
public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
    super.onPictureInPictureModeChanged(isInPictureInPictureMode);
    // 调整UI布局
}

七、常见问题与最佳实践

7.1 内存泄漏预防

  • 避免在 Activity 中持有静态引用
  • 及时注销广播接收器、监听器等
  • 使用 WeakReference 持有 Context 引用
  • 避免在非UI线程持有 Activity 引用

7.2 性能优化建议

  • 减少 onCreate() 中的耗时操作
  • 使用 ViewStub 延迟加载不常用的布局
  • 合理使用 ViewModel 保存 UI 数据
  • 考虑使用 Fragment 代替多个 Activity

7.3 常见问题解决

问题1:Activity 被意外销毁后重建导致数据丢失

解决方案:

  • 使用 onSaveInstanceState() 保存临时状态
  • 对于重要数据,使用 ViewModel + SavedStateHandle
  • 实现 Parcelable 或 Serializable 接口保存复杂对象

问题2:启动模式不生效

解决方案:

  • 检查 AndroidManifest.xml 中的 launchMode 设置
  • 检查是否有 Intent Flags 覆盖了启动模式
  • 使用 adb shell dumpsys activity activities 命令查看任务栈

八、实战案例:实现一个登录流程

public class LoginActivity extends AppCompatActivity {
    
    private EditText etUsername, etPassword;
    private Button btnLogin;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
        
        etUsername = findViewById(R.id.et_username);
        etPassword = findViewById(R.id.et_password);
        btnLogin = findViewById(R.id.btn_login);
        
        btnLogin.setOnClickListener(v -> {
            String username = etUsername.getText().toString();
            String password = etPassword.getText().toString();
            
            if (validateInput(username, password)) {
                attemptLogin(username, password);
            }
        });
    }
    
    private boolean validateInput(String username, String password) {
        // 验证输入有效性
        return !username.isEmpty() && !password.isEmpty();
    }
    
    private void attemptLogin(String username, String password) {
        // 显示加载进度条
        showProgress(true);
        
        // 模拟网络请求
        new Handler().postDelayed(() -> {
            showProgress(false);
            
            if (loginSuccess(username, password)) {
                Intent intent = new Intent(LoginActivity.this, MainActivity.class);
                intent.putExtra("USERNAME", username);
                startActivity(intent);
                finish();
            } else {
                showError("Invalid credentials");
            }
        }, 2000);
    }
    
    private boolean loginSuccess(String username, String password) {
        // 简单的模拟验证
        return "admin".equals(username) && "123456".equals(password);
    }
    
    private void showProgress(boolean show) {
        // 显示/隐藏进度条
    }
    
    private void showError(String message) {
        Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
    }
}

结语

Activity 作为 Android 开发的基石,掌握其使用方法和原理对于构建高质量应用至关重要。本文从基础到高级全面介绍了 Activity 的各个方面,希望读者能够通过实践加深理解。随着 Android 开发的演进,虽然出现了 Compose 等新的 UI 框架,但 Activity 仍然是应用架构中不可或缺的一部分。在实际开发中,建议结合 ViewModel、LiveData 等架构组件,构建更加健壮和可维护的应用。

举报

相关推荐

0 条评论