Android性能优化系列之apk瘦身

平时我们在开发App时,都会设置一个启动页SplashActivity,然后2或3秒后,并且SplashActivity里面可以去做一些MainActivity的数据的预加载,然后需要通过意图传到MainActivity。

优点:启动速度有所加快

缺点:最终还是要进入首页,在进入首页的时候,首页复杂的View渲染以及必须在UI线程执行的业务逻辑,仍然拖慢了启动速度。启动页简单执行快,首页复杂执行慢,前轻后重。

思路:能否在启动页的展示的同时,首页的View就能够被加载,首页的业务逻辑就能够被执行?

优化方向:

把SplashActivity改成SplashFragment,应用程序的入口仍然是MainActivity,在MainActivity中先展示SplashFragment,当SplashFragment显示完毕后再将它remove,同时在SplashFragment的2S的友好时间内进行网络数据缓存,在窗口加载完毕后,我们加载activity_main的布局,考虑到这个布局有可能比较复杂,耽误View的解析时间,采用ViewStub的形式进行懒加载。这样一开始只要加载SplashFragment所展示的布局就Ok了。

代码:

MainActivity .Java

public class MainActivity extends FragmentActivity { private MyHandler mHandler=new MyHandler(this); public static final String TAG="MainActivity"; private ProgressBar mNetLoadingBar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.d(TAG,"onCreate"); setContentView(R.layout.activity_main); final SplashFragment splashFragment = new SplashFragment(); final ViewStub mainLayout = (ViewStub) findViewById(R.id.content_viewstub); //1、一上来首先显示启动页面 FragmentManager supportFragmentManager = getSupportFragmentManager(); if (supportFragmentManager != null) { FragmentTransaction fragmentTransaction = supportFragmentManager.beginTransaction(); if (fragmentTransaction != null) { fragmentTransaction.replace(R.id.container, splashFragment); fragmentTransaction.commit(); } } //2、如果主页有网络等耗时操作,可以现在就开始 new Thread(new Runnable() { @Override public void run() { //耗时3500 SystemClock.sleep(3000); mHandler.sendEmptyMessage(0); } }).start(); //3、渲染完毕后,立刻加载主页布局 getWindow().getDecorView().post(new Runnable() { @Override public void run() { Log.d(TAG," getWindow().getDecorView().post"); View mainView = mainLayout.inflate(); initView(mainView); } }); //4、 启动页有动画,延迟一下,播放完动画,执行remove getWindow().getDecorView().post(new Runnable() { @Override public void run() { mHandler.postDelayed(new DelayRunnableImpl(MainActivity.this, splashFragment), 2000); } }); } @Override protected void onResume() { super.onResume(); Log.d(TAG,"onResume"); } /** * 初始化主页View */ private void initView(View pMainView) { if (pMainView != null) { mNetLoadingBar = (ProgressBar) pMainView.findViewById(R.id.progressbar); mNetLoadingBar.setVisibility(View.VISIBLE); } } private static class MyHandler extends Handler { private WeakReference<MainActivity> wRef; private MyHandler(MainActivity pActivity) { this.wRef = new WeakReference<MainActivity>(pActivity); } @Override public void handleMessage(Message msg) { MainActivity mainActivity = wRef.get(); if (mainActivity != null) { mainActivity.mNetLoadingBar.setVisibility(View.GONE); } } } private class DelayRunnableImpl implements Runnable { WeakReference<Context> contextWref; WeakReference<Fragment> fragmentWref; private DelayRunnableImpl(Context pContext, Fragment pFragment) { this.contextWref = new WeakReference<>(pContext); this.fragmentWref = new WeakReference<>(pFragment); } @Override public void run() { FragmentActivity context = (FragmentActivity) contextWref.get(); if (context != null) { FragmentManager supportFragmentManager = context.getSupportFragmentManager(); if (supportFragmentManager != null) { FragmentTransaction fragmentTransaction = supportFragmentManager.beginTransaction(); SplashFragment fragment = (SplashFragment) fragmentWref.get(); if (fragment != null) { fragmentTransaction.remove(fragment); fragmentTransaction.commit(); } } } } } @Override protected void onDestroy() { super.onDestroy(); if (mHandler != null) { mHandler.removeCallbacksAndMessages(null); } } }

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 15

  • 16

  • 17

  • 18

  • 19

  • 20

  • 21

  • 22

  • 23

  • 24

  • 25

  • 26

  • 27

  • 28

  • 29

  • 30

  • 31

  • 32

  • 33

  • 34

  • 35

  • 36

  • 37

  • 38

  • 39

  • 40

  • 41

  • 42

  • 43

  • 44

  • 45

  • 46

  • 47

  • 48

  • 49

  • 50

  • 51

  • 52

  • 53

  • 54

  • 55

  • 56

  • 57

  • 58

  • 59

  • 60

  • 61

  • 62

  • 63

  • 64

  • 65

  • 66

  • 67

  • 68

  • 69

  • 70

  • 71

  • 72

  • 73

  • 74

  • 75

  • 76

  • 77

  • 78

  • 79

  • 80

  • 81

  • 82

  • 83

  • 84

  • 85

  • 86

  • 87

  • 88

  • 89

  • 90

  • 91

  • 92

  • 93

  • 94

  • 95

  • 96

  • 97

  • 98

  • 99

  • 100

  • 101

  • 102

  • 103

  • 104

  • 105

  • 106

  • 107

  • 108

  • 109

  • 110

  • 111

  • 112

  • 113

  • 114

  • 115

  • 116

  • 117

  • 118

  • 119

  • 120

  • 121

  • 122

  • 123

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 15

  • 16

  • 17

  • 18

  • 19

  • 20

  • 21

  • 22

  • 23

  • 24

  • 25

  • 26

  • 27

  • 28

  • 29

  • 30

  • 31

  • 32

  • 33

  • 34

  • 35

  • 36

  • 37

  • 38

  • 39

  • 40

  • 41

  • 42

  • 43

  • 44

  • 45

  • 46

  • 47

  • 48

  • 49

  • 50

  • 51

  • 52

  • 53

  • 54

  • 55

  • 56

  • 57

  • 58

  • 59

  • 60

  • 61

  • 62

  • 63

  • 64

  • 65

  • 66

  • 67

  • 68

  • 69

  • 70

  • 71

  • 72

  • 73

  • 74

  • 75

  • 76

  • 77

  • 78

  • 79

  • 80

  • 81

  • 82

  • 83

  • 84

  • 85

  • 86

  • 87

  • 88

  • 89

  • 90

  • 91

  • 92

  • 93

  • 94

  • 95

  • 96

  • 97

  • 98

  • 99

  • 100

  • 101

  • 102

  • 103

  • 104

  • 105

  • 106

  • 107

  • 108

  • 109

  • 110

  • 111

  • 112

  • 113

  • 114

  • 115

  • 116

  • 117

  • 118

  • 119

  • 120

  • 121

  • 122

  • 123

SplashFragment .java

public class SplashFragment extends Fragment { public SplashFragment() { } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View ret = inflater.inflate(R.layout.fragment_splash, container, false); initView(ret); return ret; } private void initView(View ret) { if (ret != null) { ImageView imageView = (ImageView) ret.findViewById(R.id.laucher_logo); playAnimator(imageView); } } private void playAnimator(ImageView pView) { if (pView != null) { PropertyValuesHolder pvhA = PropertyValuesHolder.ofFloat("alpha", 1f, 0.7f, 0.1f); // PropertyValuesHolder pvhR= PropertyValuesHolder.ofFloat("rotationX", 0.0F, 360.0F); ObjectAnimator.ofPropertyValuesHolder(pView, pvhA).setDuration(2000).start(); } } }

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 15

  • 16

  • 17

  • 18

  • 19

  • 20

  • 21

  • 22

  • 23

  • 24

  • 25

  • 26

  • 27

  • 28

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 15

  • 16

  • 17

  • 18

  • 19

  • 20

  • 21

  • 22

  • 23

  • 24

  • 25

  • 26

  • 27

  • 28

activity_mian.xml

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="zhangwan.wj.com.myshare.activity.MainActivity"> <ViewStub android:id="@+id/content_viewstub" android:layout="@layout/main_layout" android:layout_width="match_parent" android:layout_height="match_parent"/> <FrameLayout android:id="@+id/container" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </RelativeLayout>

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 15

  • 16

  • 17

  • 18

  • 19

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 15

  • 16

  • 17

  • 18

  • 19

fragment.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="zhangwan.wj.com.myshare.fragment.SplashFragment"> <ImageView android:id="@+id/laucher_logo" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/launch" /> </FrameLayout>

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

采用以上方式后,可以发现启动速度得到很大的改观。

启动优化一些思路


1、避免启动页UI的过度绘制,减少UI重复绘制时间,打开设置中的GPU过度绘制开关,界面整体呈现浅色,特别复杂的界面,红色区域也不应该超过全屏幕的四分之一;

2、主线程中的所有SharedPreference能否在非UI线程中进行,SharedPreferences的apply函数需要注意,因为Commit函数会阻塞IO,这个函数虽然执行很快,但是系统会有另外一个线程来负责写操作,当apply频率高的时候,该线程就会比较占用CPU资源。类似的还有统计埋点等,在主线程埋点但异步线程提交,频率高的情况也会出现这样的问题。

3、对于首次启动的黑屏问题,对于“黑屏”是否可以设计一个.9图片替换掉,间接减少用户等待时间。

4、对于网络错误界面,友好提示界面,使用ViewStub的方式,减少UI一次性绘制的压力。

5、通过下面这种方式进行懒加载

getWindow().getDecorView().post(new Runnable() { @Override public void run() { myHandler.post(mLoadingRunnable); } });

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

6、Multidex的使用,也是拖慢启动速度的元凶,必须要做优化

总结

最后为了帮助大家深刻理解Android相关知识点的原理以及面试相关知识,这里放上相关的我搜集整理的14套腾讯、字节跳动、阿里、百度等2021最新面试真题解析,我把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包知识脉络 + 诸多细节。

2020面试真题解析
腾讯面试真题解析

阿里巴巴面试真题解析

字节跳动面试真题解析
网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!
界面,使用ViewStub的方式,减少UI一次性绘制的压力。

5、通过下面这种方式进行懒加载

getWindow().getDecorView().post(new Runnable() { @Override public void run() { myHandler.post(mLoadingRunnable); } });

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

[外链图片转存中…(img-dFJZJz9B-1714549894757)]

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

6、Multidex的使用,也是拖慢启动速度的元凶,必须要做优化

总结

最后为了帮助大家深刻理解Android相关知识点的原理以及面试相关知识,这里放上相关的我搜集整理的14套腾讯、字节跳动、阿里、百度等2021最新面试真题解析,我把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包知识脉络 + 诸多细节。

[外链图片转存中…(img-sISaQhsQ-1714549894759)]
[外链图片转存中…(img-VFtLbqYh-1714549894764)]

[外链图片转存中…(img-zfgIKt3o-1714549894766)]

[外链图片转存中…(img-zzWZK0DU-1714549894768)]
网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值