【Bugly安卓开发干货】Android APP 快速 Pad 化实现

本文介绍了如何将一个大型Android手机应用快速转换为Pad版本,探讨了在转换过程中遇到的问题及解决方案。文章详细阐述了Activity替换为Fragment的难点,如TitleBar处理、Fragment间独立操作、多进程Activity的处理,并提出了使用LocalActivityManager实现每个Tab独立管理的架构方案。通过这样的架构,实现了快速Pad化的同时,保留了原有Activity的行为和多进程特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Bugly 技术干货系列内容主要涉及移动开发方向,是由 Bugly 邀请腾讯内部各位技术大咖,通过日常工作经验的总结以及感悟撰写而成,内容均属原创,转载请标明出处。

如何能在最快的时间内,实现一个最新版本 android app 的 pad 化呢?从拿到一个大型手机 app 代码开始开发到第一个其全新 pad 版本的发布,我们用了不到3个月时间给出了一份满意的答案。

项目背景

采用最新版本手机 APP(之后称为 MyApp)代码,实现其 Pad 化,为平板和大屏手机用户提供更好的体验。为实现 MyApp 的 Pad 化工作,需要我们首先来了解一下 MyApp 项目经典页面的构成以及 Pad 化后的页面结构的变化。

1.MyApp 页面经典构成

现在主流手机 APP 主页通常采用标签栏加标签内容方式显示。而通过主页进入的二级页面全部采用全屏方式展示。比如手机 QQ,微信,支付宝等等都是采用 Tab 栏方式为主,进入一个具体功能后,全屏打开。我们项目也是如此。下面看一下 MyApp 项目手机端的页面构成图。

腾讯Bugly
Bugly安卓开发

左侧是一个 Tab 栏(区域1)加 Tab Content(区域2)构成的页面,右侧是在 TabContent 中点击具体功能后进入的一个功能详情页面(全屏区域3)。
查看代码,发现除 TabContent 区域2,从主页开始到其他全屏显示的页面全部采用 Android Activity 组件实现。经统计得出大概有几百个 Activity。这些 Activity还包含比如Web进程,peak 进程(图片选择查看)等其他非主进程 Activity。

1.MyApp pad 化的设计图

了解了手机 MyApp 页面构成后,还要来看 Pad 化后 UI 结构的变化,通过对比来探索 Pad 化最佳的实现方案。下面是我们的 PAD 版本页面结构图。
这里写图片描述

由于 Pad 平板的空间要远大于手机空间,所以,在主页中 Pad 所展示的内容要比手机更多。通过观察设计图发现,整个页面分为了3块区域,与手机端页面的1,2,3区域一一对应。Tab 栏被移到了左侧1区,Tab Content 被移到了中间2区,而在2区打开的 Details 页面则要求在3区展示,而不再是像手机 APP 一样全屏展示。

手机 APP Pad 化道路的探索过程

通过了解 MyApp 项目经典页面构成和 pad 版页面结构的变化,以及快速Pad 化的原则,我们开始了对手机 APP pad 化实现方案的漫漫探索。
首先想到的是,既然手机APP页面主要是由Activity构成,那么我们能不能把 Activity 缩小,让多个 Activity 在同一屏幕显示呢,很快我们的方案1出来了。

方案1,如果把设计图的整个页面称为主 Activity,主 Activity 全屏显示不变,在主 Activiy 中打开的新 Activity (称为A)缩小显示在设计图3区,我们就可以实现 Pad 设计的要求。那么我们具体实现步骤为:
1,A类 Activity 继承 Base Activity
2,修改 Base Activity 的 window 的起始坐标x和宽度 width,让其刚好位于3区。
3,A类 Activity 背景改为透明
4,让在A类 Activity 继续打开的 Activity,重复1,2,3,4步骤。

但是很快就发现了问题。
1. 在当前 Tab 打开 Activity A,切换 Tab 后 A Activity 仍然显示。
2. 每个 Tab 打开的 Activity,都处于同一个 Activity 栈中,按打开先后顺序添加,点击返回键也是顺序退出的。这样每个 Tab 中打开的Activity 都混在一起了,而不是彼此独立。导致 back 键出现问题。

既然直接显示 Actvity 有问题,想想反正都是显示UI布局,能不能把 A 类 Activity 的根布局拉出来挂载在主 Activity 右侧?从而我们推导出了方案2。

方案2:在主 Activity 启动 A 类 Activity 时,获取 A 的根布局,添加到主 Activity 在右侧3区预留的一个空布局中。具体实现步骤为:
1,重写主 Activity 的 startActivity 方法。
2,使用 LocalActivityManager 启动 A 类 Aactivity 返回 window 对象。
3,通过 Window 对象 window.getDecorView()返回打开 Activity 的布局并 Add 到主 Actvity 上。
4,重写主 Activity 的 Back 逻辑,在点击返回键时 remove 掉挂载的 decorView。

但是在 Demo 上一测试,就发现了很多问题,
1. 用 mat 查看到 A 类 Activity 是怎么也释放不掉的,因为 LocalActivityManager 已经抓住了 A 类 Activity 的 parent。
2. 直接拿出 A 类 Activity 的 decorView,已经让A类 Activity 丧失了 Activity 的一切特性,包括生命周期,返回逻辑,ActivityResult,以及启动其他 Activity 等功能。会导致之前正常运行的A类 Activity 出现大量问题。

既然直接拿到根视图没有用,那该怎么做才好呢?怎么做才能使 A 类 Activity 的页面挂载在主 Activity 右侧,又能保证 A 的生命周期和 Activity 行为呢?经过大家一番思考讨论后,能不能利用插件的思想,把 A 类 Activity 中的生命周期方法以及继承自 Activity 类的方法都拿出来了,在适当时候自己调用呢?这样就保证了原来 A 中的代码不会出现问题,不需要修改 A 中的任何代码。但是用什么做容器(代理)比较好了?之后我们想到了用 Fragment,,因为 Fragment 可以作为所属 Activity 的一个块存在于任何位置,并且 Fragment 有自己的生命周期,并受所属 Activity 的生命周期影响,它就像一个子 Activity 一样。简直是绝佳容器。而且 Fragment 比较轻量,本身由 Activity 来管理(而不像 Activity 由 Android 系统服务管理),在不同的布局结构中重用 Fragment 可以优化屏幕空间和用户体验。
注意,下面所说的把 Activity 转换为 Fragment 并不是直接把 Activity 变为 Fragment,这会付出巨大代价,而是以一个空的 Fragment 为容器来承载 Activity。

终于方案3顺利出炉。

方案3,把 Activity 转换为 Fragment,使用 Fragment 模拟 Activity 的方法。然后把 Fragment 直接添加到主 Activity 的右侧布局中。实现的具

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值