1.应用启动的两种方式
- 冷启动:当直接从桌面上直接启动,同时后台没有该进程的缓存,这个时候系统就需要,重新创建一个新的进程并且分配各种资源。
- 热启动:该app后台有该进程的缓存,这时候启动的进程就属于热启动。
热启动不需要重新分配进程,直接走的就是app的Activity,这样就速度快很多
2.如何测量一个应用的启动时间
在命令行窗口使用命令行来启动app,同时进行时间测量。单位:毫秒
adb shell am start -W [PackageName]/[PackageName.MainActivity]
接着命令行窗口会返回下面两个数据:
ThisTime: 指当前指定的MainActivity的启动时间
TotalTime: 整个应用的启动时间,Application+Activity的使用的时间。
3.应用启动的流程
Application从构造方法开始—>attachBaseContext()—>onCreate()
Activity构造方法—>onCreate()<设置显示界面布局,设置主题、背景等等属性>—>onStart()—>onResume()<显示里面的view(测量、布局、绘制,显示到界面上)>
4.减少应用的启动时间的耗时
- 不要在Application的构造方法、attachBaseContext()、onCreate()里面进行初始化耗时操作。
- MainActivity,由于用户只关心最后的显示的这一帧,在写自定义控件的时候布局的层次要尽量减小。不要在onCreate、onStart、onResume当中做耗时操作。
- 对于SharedPreference的初始化。
因为他初始化的时候是需要将数据全部读取出来放到内存当中。
优化1:可以尽可能减少sp文件数量(IO需要时间);2.像这样的初始化最好放到线程里面;3.大的数据缓存到数据库里面。
app启动的耗时主要是在:Application初始化(没多大办法改善重点在MainActivity界面的绘制上) + MainActivity的界面加载绘制时间。
viewStub的设计就是为了防止MainActivity的启动加载资源太耗时了。延迟进行加载,不影响启动,用户友好。
代码实现
- MainActivity:
package com.example.aaa;
import java.lang.ref.WeakReference;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTransaction;
import android.view.View;
import android.view.ViewStub;
import android.widget.ProgressBar;
public class MainActivity extends FragmentActivity {
private Handler mHandler = new Handler();
private ViewStub viewStub;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final SplashFragment splashFragment = new SplashFragment();
final FragmentTransaction transaction = getSupportFragmentManager()
.beginTransaction();
transaction.replace(R.id.frame, splashFragment);
transaction.commit();
viewStub = (ViewStub) findViewById(R.id.content_viewstub);
// 1.等整个界面加载完毕后,立马再加载真正的布局进来
getWindow().getDecorView().post(new Runnable() {
@Override
public void run() {
mHandler.post(new Runnable() {
@Override
public void run() {
viewStub.inflate();
}
});
}
});
// 2.延迟一段时间做动画,然后把splashfragment移除
getWindow().getDecorView().post(new Runnable() {
@Override
public void run() {
mHandler.postDelayed(new DelayRunnable(MainActivity.this,
splashFragment), 2500);
}
});
//3.同时异步预加载数据。
//....
}
static class DelayRunnable implements Runnable {
private WeakReference<Context> contextRef;
private WeakReference<SplashFragment> fragmentRef;
public DelayRunnable(Context context, SplashFragment splashFragment) {
contextRef = new WeakReference<Context>(context);
fragmentRef = new WeakReference<SplashFragment>(splashFragment);
}
@Override
public void run() {
FragmentActivity context = (FragmentActivity) contextRef.get();
if (context != null) {
SplashFragment splashFragment = fragmentRef.get();
if (splashFragment == null)
return;
final FragmentTransaction transaction = context
.getSupportFragmentManager().beginTransaction();
transaction.remove(splashFragment);
transaction.commit();
}
}
}
@Override
protected void onDestroy() {
super.onDestroy();
mHandler.removeCallbacksAndMessages(null);
}
}
- SplashFragment:
package com.example.aaa;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class SplashFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
// TODO Auto-generated method stub
return inflater.inflate(R.layout.fragment_splash, container, false);
}
}
布局文件
- activity_main:
<RelativeLayout 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=".MainActivity" >
<ViewStub
android:id="@+id/content_viewstub"
android:layout="@layout/main_viewstub"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<FrameLayout
android:id="@+id/frame"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</FrameLayout>
</RelativeLayout>
- fragment_splash:
<RelativeLayout 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="com.example.applicationstartoptimizedemo.MainActivity" >
<FrameLayout
android:id="@+id/frame"
android:background="@drawable/splash12"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</FrameLayout>
</RelativeLayout>
- main_viewstub:
<RelativeLayout 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="com.example.applicationstartoptimizedemo.MainActivity" >
<ImageView
android:id="@+id/iv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitStart"
android:src="@drawable/content" />
</RelativeLayout>