一般情况下,app在首次启动时需要加载大量布局跟数据,我公司项目首次启动需要加载一个Activity里面有7个Fragment…加上各种数据,经常导致启动时会有白屏现象,为了完美解决各种现象也花了一些功夫,这里记录一下.
1:点击App启动时第一个白屏
这个白屏是因为主题背景设置导致的,解决也比较简单,就是设置App主题背景图片为自己App 加载的图片即可,这里注意要把加载Activity跟布局的背景去掉,不然主题的背景会被覆盖!
<!-- Application theme. -->
<style name="AppTheme" parent="AppBaseTheme">
<item name="android:windowNoTitle">true</item>
<item
<!-- 自定义背景 -->name="android:windowBackground">@color/white</item>
<!-- All customizations that are NOT specific to a particular API-level can go here. -->
</style>
然后在清单文件设置主题就可以!
2:splash 界面过后,跳转主界面时间过长,出现白屏;
这种情况就是主界面布局复杂,加载时间长导致的或者主界面加载过程有耗时操作;这里不讨论耗时操作的影响,有点经验都不会放到主线程;
复杂的布局改怎么处理?总不能不加载吧…
这里使用延时加载子布局方法
以前我们的思路是先加载splash界面,一定时间后再跳转到主界面,这个思路有2个缺点
第一: 加载splash界面时不能加载网络数据(加载了也要做缓存,因为这个界面很快就要被回收),浪费了中间的宝贵时间
第二:加载splash界面时不能预加载复杂的主界面,导致跳转到主界面后卡顿,白屏!
这里的思路是将 splash界面图片直接放在主界面,用延时加载布局方法先加载图片后再加载复杂布局;
下面上代码
import java.lang.ref.WeakReference;
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.ViewStub;
public class MainActivity extends FragmentActivity {
private Handler mHandler = new Handler();
private SplashFragment splashFragment;
private ViewStub viewStub;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
splashFragment = new SplashFragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.frame, splashFragment);
transaction.commit();
// mHandler.postDelayed(new Runnable() {
// @Override
// public void run() {
// mProgressBar.setVisibility(View.GONE);
// iv.setVisibility(View.VISIBLE);
// }
// }, 2500);
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加载进来
viewStub.inflate();
}
} );
}
});
//2.判断当窗体加载完毕的时候执行,延迟一段时间做动画。
getWindow().getDecorView().post(new Runnable() {
@Override
public void run() {
// 开启延迟加载,也可以不用延迟可以立马执行(我这里延迟是为了实现fragment里面的动画效果的耗时)
mHandler.postDelayed(new DelayRunnable(MainActivity.this, splashFragment) ,2000);
// mHandler.post(new DelayRunnable());
}
});
//3.同时进行异步加载数据
}
@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
}
static class DelayRunnable implements Runnable{
private WeakReference<Context> contextRef;
private WeakReference<SplashFragment> fragmentRef;
public DelayRunnable(Context context, SplashFragment f) {
contextRef = new WeakReference<Context>(context);
fragmentRef = new WeakReference<SplashFragment>(f);
}
@Override
public void run() {
// 移除fragment
if(contextRef!=null){
SplashFragment splashFragment = fragmentRef.get();
if(splashFragment==null){
return;
}
FragmentActivity activity = (FragmentActivity) contextRef.get();
FragmentTransaction transaction = activity.getSupportFragmentManager().beginTransaction();
transaction.remove(splashFragment);
transaction.commit();
}
}
}
}
简单的Fragmemt
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class SplashFragment extends Fragment {
@Override
@Nullable
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
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="com.example.applicationstartoptimizedemo.MainActivity" >
<ViewStub
android:id="@+id/content_viewstub"
android:layout="@layout/activity_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>
activity_main_viewstub
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ProgressBar
android:id="@+id/progressBar1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" />
<ImageView
android:id="@+id/iv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitStart"
android:src="@drawable/content" />
</FrameLayout>
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>
主要就是用到 ViewStub 延时加载就机制.