平时我们在开发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(实际上比预期多花了不少精力),包知识脉络 + 诸多细节。
网上学习 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学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可获取!