深入分析 Android Activity (十一)

文章目录

    • [深入分析 Android Activity (十一)](#深入分析 Android Activity (十一))
    • [1. Activity 的内存管理和优化](#1. Activity 的内存管理和优化)
      • [1.1 内存泄漏的常见原因](#1.1 内存泄漏的常见原因)
      • [1.2 避免内存泄漏的方法](#1.2 避免内存泄漏的方法)
      • [1.3 内存泄漏检测工具](#1.3 内存泄漏检测工具)
    • [2. Activity 的配置变更处理](#2. Activity 的配置变更处理)
      • [2.1 处理配置变更](#2.1 处理配置变更)
      • [2.2 保存和恢复状态](#2.2 保存和恢复状态)
      • [2.3 使用 ViewModel](#2.3 使用 ViewModel)
    • [3. Activity 的测试](#3. Activity 的测试)
      • [3.1 单元测试](#3.1 单元测试)
      • [3.2 UI 测试](#3.2 UI 测试)
    • [4. Activity 与 Fragment 的关系](#4. Activity 与 Fragment 的关系)
      • [4.1 添加 Fragment](#4.1 添加 Fragment)
      • [4.2 处理 Fragment 生命周期](#4.2 处理 Fragment 生命周期)
      • [4.3 Fragment 之间的通信](#4.3 Fragment 之间的通信)
    • 总结

深入分析 Android Activity (十一)

1. Activity 的内存管理和优化

内存管理是 Android 开发中非常重要的一部分。内存泄漏会导致应用崩溃和性能问题,因此需要在开发过程中注意内存管理和优化。

1.1 内存泄漏的常见原因

  • 静态引用:静态变量持有 Activity 的引用会导致内存泄漏。
  • 未取消的监听器:忘记注销注册的监听器或回调会导致内存泄漏。
  • Handler 内存泄漏:匿名内部类 Handler 引用外部类实例,会导致外部类无法被回收。
  • 长时间运行的线程:线程持有 Activity 的引用,在 Activity 销毁后线程未终止,会导致内存泄漏。

1.2 避免内存泄漏的方法

  • 使用弱引用 :使用 WeakReference 持有 Activity 的引用。
  • 及时取消监听器和回调 :在 onDestroy 或其他适当时机取消监听器和回调。
  • 静态内部类:使用静态内部类避免持有外部类的引用。
  • 使用 Application Context:在适当场景下使用 Application Context 而非 Activity Context。
java 复制代码
// 使用 WeakReference 避免内存泄漏
private static class MyHandler extends Handler {
    private final WeakReference<MyActivity> mActivity;

    public MyHandler(MyActivity activity) {
        mActivity = new WeakReference<>(activity);
    }

    @Override
    public void handleMessage(Message msg) {
        MyActivity activity = mActivity.get();
        if (activity != null) {
            // Handle message
        }
    }
}

1.3 内存泄漏检测工具

  • LeakCanary:一个内存泄漏检测工具,可以帮助检测内存泄漏。
java 复制代码
// 在 Application 类中初始化 LeakCanary
public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        if (LeakCanary.isInAnalyzerProcess(this)) {
            return;
        }
        LeakCanary.install(this);
    }
}

2. Activity 的配置变更处理

配置变更(如屏幕旋转、语言切换)会导致 Activity 被销毁和重建,需要妥善处理以保存和恢复数据。

2.1 处理配置变更

可以在 AndroidManifest.xml 中通过 android:configChanges 属性指定处理配置变更。

xml 复制代码
<activity android:name=".MyActivity"
    android:configChanges="orientation|screenSize|keyboardHidden"/>

在 Activity 中重写 onConfigurationChanged 方法。

java 复制代码
@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        // Handle orientation change to landscape
    } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
        // Handle orientation change to portrait
    }
}

2.2 保存和恢复状态

在配置变更时,可以通过 onSaveInstanceStateonRestoreInstanceState 方法保存和恢复数据。

java 复制代码
@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putString("key", "value");
}

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    if (savedInstanceState != null) {
        String value = savedInstanceState.getString("key");
    }
}

2.3 使用 ViewModel

可以使用 ViewModel 在配置变更期间保存 UI 相关数据。

java 复制代码
public class MyViewModel extends ViewModel {
    private MutableLiveData<String> data;

    public LiveData<String> getData() {
        if (data == null) {
            data = new MutableLiveData<>();
            loadData();
        }
        return data;
    }

    private void loadData() {
        // Load data asynchronously
    }
}

// 在 Activity 中使用 ViewModel
MyViewModel viewModel = new ViewModelProvider(this).get(MyViewModel.class);
viewModel.getData().observe(this, new Observer<String>() {
    @Override
    public void onChanged(String s) {
        // Update UI
    }
});

3. Activity 的测试

测试是确保应用质量的重要步骤,包括单元测试和 UI 测试。

3.1 单元测试

可以使用 JUnit 进行单元测试。

java 复制代码
// 使用 JUnit 测试 Activity 中的方法
@RunWith(AndroidJUnit4.class)
public class MyActivityTest {

    @Test
    public void testActivityMethod() {
        Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
        assertEquals("com.example.myapp", appContext.getPackageName());
    }
}

3.2 UI 测试

可以使用 Espresso 进行 UI 测试。

java 复制代码
// 使用 Espresso 进行 UI 测试
@RunWith(AndroidJUnit4.class)
public class MyActivityUITest {

    @Rule
    public ActivityScenarioRule<MyActivity> activityScenarioRule = new ActivityScenarioRule<>(MyActivity.class);

    @Test
    public void testButtonClick() {
        onView(withId(R.id.my_button)).perform(click());
        onView(withId(R.id.my_text_view)).check(matches(withText("Button clicked")));
    }
}

4. Activity 与 Fragment 的关系

Fragment 是在 Activity 中的可重用组件,用于实现灵活的 UI 设计。

4.1 添加 Fragment

可以在 XML 布局文件中添加 Fragment,也可以在代码中动态添加。

xml 复制代码
<!-- 在 XML 布局文件中添加 Fragment -->
<fragment
    android:id="@+id/my_fragment"
    android:name="com.example.MyFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>
java 复制代码
// 在代码中动态添加 Fragment
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
MyFragment fragment = new MyFragment();
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit();

4.2 处理 Fragment 生命周期

Fragment 的生命周期与 Activity 类似,但有自己独特的生命周期方法。

java 复制代码
public class MyFragment extends Fragment {

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        // Fragment 被添加到 Activity 时调用
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Fragment 初始化时调用
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        // 为 Fragment 创建视图时调用
        return inflater.inflate(R.layout.fragment_my, container, false);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        // Activity 的 onCreate 方法返回时调用
    }

    @Override
    public void onStart() {
        super.onStart();
        // Fragment 可见时调用
    }

    @Override
    public void onResume() {
        super.onResume();
        // Fragment 交互时调用
    }

    @Override
    public void onPause() {
        super.onPause();
        // Fragment 不可见时调用
    }

    @Override
    public void onStop() {
        super.onStop();
        // Fragment 停止时调用
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        // Fragment 视图被销毁时调用
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        // Fragment 被销毁时调用
    }

    @Override
    public void onDetach() {
        super.onDetach();
        // Fragment 从 Activity 中分离时调用
    }
}

4.3 Fragment 之间的通信

可以使用接口在 Fragment 之间进行通信。

java 复制代码
// 定义接口
public interface OnFragmentInteractionListener {
    void onFragmentInteraction(String data);
}

// 在 Fragment 中实现接口
public class MyFragment extends Fragment {
    private OnFragmentInteractionListener mListener;

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof OnFragmentInteractionListener) {
            mListener = (OnFragmentInteractionListener) context;
        } else {
            throw new RuntimeException(context.toString() + " must implement OnFragmentInteractionListener");
        }
    }

    public void someMethod() {
        if (mListener != null) {
            mListener.onFragmentInteraction("Some data");
        }
    }
}

// 在 Activity 中实现接口
public class MyActivity extends AppCompatActivity implements OnFragmentInteractionListener {
    @Override
    public void onFragmentInteraction(String data) {
        // Handle the data from the fragment
    }
}

总结

通过对 Android Activity 的深入理解和灵活应用,可以实现丰富的用户体验和高效的应用程序。理解其生命周期、权限管理、数据传递、动画效果、导航和返回栈管理、资源管理、配置变更处理、视图层次结构、性能优化、内存管理、测试、Service 交互、BroadcastReceiver

|----------------------------------|
| 欢迎点赞|关注|收藏|评论,您的肯定是我创作的动力 |

相关推荐
小趴菜82274 小时前
安卓接入Kwai广告源
android·kotlin
2501_916013745 小时前
iOS 混淆与 App Store 审核兼容性 避免被拒的策略与实战流程(iOS 混淆、ipa 加固、上架合规)
android·ios·小程序·https·uni-app·iphone·webview
程序员江同学6 小时前
Kotlin 技术月报 | 2025 年 9 月
android·kotlin
码农的小菜园6 小时前
探究ContentProvider(一)
android
时光少年8 小时前
Compose AnnotatedString实现Html样式解析
android·前端
hnlgzb8 小时前
安卓中,kotlin如何写app界面?
android·开发语言·kotlin
jzlhll1239 小时前
deepseek kotlin flow快生产者和慢消费者解决策略
android·kotlin
火柴就是我9 小时前
Android 事件分发之动态的决定某个View来处理事件
android
一直向钱9 小时前
FileProvider 配置必须针对 Android 7.0+(API 24+)做兼容
android
zh_xuan9 小时前
Android 消息循环机制
android