深入分析 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

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

相关推荐
kk爱闹2 小时前
【挑战14天学完python和pytorch】- day01
android·pytorch·python
每次的天空3 小时前
Android-自定义View的实战学习总结
android·学习·kotlin·音视频
恋猫de小郭4 小时前
Flutter Widget Preview 功能已合并到 master,提前在体验毛坯的预览支持
android·flutter·ios
断剑重铸之日5 小时前
Android自定义相机开发(类似OCR扫描相机)
android
随心最为安5 小时前
Android Library Maven 发布完整流程指南
android
岁月玲珑5 小时前
【使用Android Studio调试手机app时候手机老掉线问题】
android·ide·android studio
还鮟9 小时前
CTF Web的数组巧用
android
小蜜蜂嗡嗡10 小时前
Android Studio flutter项目运行、打包时间太长
android·flutter·android studio
aqi0010 小时前
FFmpeg开发笔记(七十一)使用国产的QPlayer2实现双播放器观看视频
android·ffmpeg·音视频·流媒体
zhangphil12 小时前
Android理解onTrimMemory中ComponentCallbacks2的内存警戒水位线值
android