Android性能优化之Splash页面设计

原创 2016年08月31日 13:54:43

目前SplashActivity的设计

目前市场上的应用在启动时基本上都会先启动一个SplashActivity,作为一个欢迎界面,为什么这样设计呢?
个人总结有三个优点:

1、可以给用户更好的体验

比如:可以由后台动态的改变欢迎的图片,或者显欢迎xxx回来,新浪微博的就是这种交互。

2、可以缩减App的启动时间

由上一篇博文中知道app启动的耗时主要是在Application初始化中和MainActivity的界面绘制前,由于MainActivity的业务和布局复杂度肯定比只显示一张图片的界面高,所以,加入一个显示一张图片的Splash页可以优化应用的启动。

3、可以在应用启动时做更多的事

一般来说SplashActivity一般会设计成停留2到4s不等,或者根据数据的加载程度来动态的设置Splash界面的停留时间,既然停留那么久,那么当然可以在这个界面背后做一些事以备MainActivity的快速显示,比如:数据的预加载、sp的初始化、网络请求等。

当然你可能有些疑问,那这样初始化放在Application中也可以啊?也用异步操作数据也是一样啊?

答案是不一样!正如上篇所说的,Application初始化时并不会加载界面,而是在它创建完和初始化完成后,开始创建Activity时才开始绘制Theme中的background和绘制布局,所以用一个轻量的Splash页给它设置一张背景欢迎图,这样就立马能显示界面了,而在这个界面中还可以做其它的初始化操作,这样在视觉上即达到了app的快速启动,又添加了体验和做数据的初始化。

相反如果过多的放在Application中,则在点击app图标启动时会感觉延迟,必须要把Application中的东西都做完才进入Activity的配置和绘制中。

目前大多数应用的Splash页设计的不足之处

目前大多应用的Splash页设计都是利用一个Activity,取名叫SplashActivity,然后在这个SplashActivity中加入一个背景图,然后再new Handler().postDelayed()几秒中,再startActivity跳入主界面,这样设计看起来非常不错,既可以在SplashActivity初始化、预加载数据,还可以提高应用的启动速度。

不过这确实提高了应用的启动速度,毕竟我们比较快的看到了第一帧——SplashActivity,不过在SplashActivity之后,还需要调到MainActivity啊,虽然MainActivity中的一些数据可以在SplashActivity做预取,不过这中间需要有Intent的传递过程,而且MainActivity中布局还没加载进来,所以还是需要再加载和绘制布局界面,然后才能填入数据,所以这样看来,在跳转到MainActivity中,还是需要做界面的绘制和数据的加载(包括Intent的数据传递)。


性能优且体验棒的Splash页的设计

从上面这个设计图来看,其中有些操作能不能去除呢?既能达到app启动速度的提高,也能对数据的预加载还能减去Splash和MainActivity之间不必要的数据传递和View的分开绘制。

答案是能的,既然SplashActivity和MainActivity分开进行操作还是不完美,那么可以考虑把它们合为一起,即:一开始还是显示MainActivity,SplashActivity变为SplashFragment,然后放一个FrameLayout作为根布局去显示SplashFragment界面,这样在SplashFragment显示时候利用显示的2~4s间的空隙时间做网络请求去加载数据,这样待SplashFragment显示完后再remove,这样将看到的是有内容的MainActivity,就不必再去等待网络请求去返回数据了。
当然,这种方式是把load Splash View和ContentView合二为一了一起加载,这可能会影响应用的启动时间,这时我们可以用ViewStub延迟加载MainActivity中某些View从而减去这个影响。

应用场景:现在一个app打开时就要上网请求数据,大家知道这样用户体验是非常不好的,每次打开app都要等待数秒,这样的app实际上是不合格。

修改思路:我在上网请求的时候同时展示Splash页面,市场上大多数app也是这样做的。比如:京东,默默,等等。他在展示Splash页面的时候就在初始化一些数据,提高用户体验。

修改如下


我只在MainActivity的布局里面放了一个视图容器,然后用MainFragment填充。

大家知道在MainFragment生命周期onCreateViwe里面要返回一个视图,这时我们就建立一个视图容器,把Splash页面和上网请求数据后的成功视图一起加进去,再返回给MainFragment,这样就实现了在上网请求数据的时候显示Splash页面,加载成功后显示成功视图。

public abstract class LoadingPager extends FrameLayout {

    private Context mContext;
    public static int CURRENTVIEW = Constants.SUCCESS;
    private View mSplashView;
    private View mSuccessView;

    public LoadingPager(Context context) {
        super(context);

        mContext = context;
        initCommonView();
    }

    private void initCommonView() {
        mSplashView = View.inflate(mContext, R.layout.fragment_splash, null);
        addView(mSplashView);

        refreshViewByState();
    }

    /**
     * 刷新界面
     */
    public void refreshViewByState() {
        if (CURRENTVIEW == Constants.SPLASHView) {
            mSplashView.setVisibility(View.VISIBLE);
        } else {
            mSplashView.setVisibility(View.GONE);
        }

        if (CURRENTVIEW == Constants.SUCCESS && mSuccessView == null) {
            mSuccessView = initSuccessView();
            addView(mSuccessView);
        }

        if (mSuccessView != null) {
            if (CURRENTVIEW == Constants.SUCCESS) {
                mSuccessView.setVisibility(View.VISIBLE);
            } else {
                mSuccessView.setVisibility(View.GONE);
            }
        }
    }

    /**
     * 触发加载
     */
    public void triggerLoadData() {
        MyApplication.getThreadPool().execute(new LoadTask());
    }

    public class LoadTask implements Runnable {

        @Override
        public void run() {
            CURRENTVIEW = initData();

            MyApplication.getMainThreadHandler().post(new Runnable() {
                @Override
                public void run() {
                    refreshViewByState();
                }
            });
        }
    }

    protected abstract int initData();

    public abstract View initSuccessView();
}

initData();就是来实现上网请求数据的,所以要放在子线程中。
initSuccessView();就是显示加载成功后的视图。

然后在MainFragment返回loadingPager就行了

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        mLoadingPager = new LoadingPager(mContext) {
            @Override
            protected int initData() {
                //TODO 上网请求可以下载的app,并返回成功后的视图
                SystemClock.sleep(2000);
                return Constants.SUCCESS;
            }

            @Override
            public View initSuccessView() {
                View view = View.inflate(mContext, R.layout.fragment_main, null);
                TextView splash = (TextView) view.findViewById(R.id.splash);
                TextView download = (TextView) view.findViewById(R.id.download);
                TextView uninstallApp = (TextView) view.findViewById(R.id.uninstallapp);
                ViewPager appListViewPager = (ViewPager) view.findViewById(R.id.app_list_viewpager);
                OnClickListener onClickListener = new OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        Intent intent;
                        switch (v.getId()) {
                            case R.id.splash:
                                ToastUtil.showToast(mContext, "界面已刷新", 0);
                                break;

                            case R.id.download:
                                intent = new Intent(mContext, DownloadActivity.class);
                                startActivity(intent);
                                break;

                            case R.id.uninstallapp:
                                intent = new Intent(mContext, UninstallActivity.class);
                                startActivity(intent);
                                break;
                        }
                    }
                };
                splash.setOnClickListener(onClickListener);
                download.setOnClickListener(onClickListener);
                uninstallApp.setOnClickListener(onClickListener);
                return view;
            }
        };
        mLoadingPager.triggerLoadData();
        return mLoadingPager;
    }

这里面有很多多余的代码,只看在最后一行,整个onCreateView里面返回mLoadingPager视图,别忘加要触发一下加载成功视图mLoadingPager.triggerLoadData();在initData();里面进行耗时操作并返回成功视图,在initSuccess()View;里面写你绑定你成功后的视图。这样就实现了,在网络请求的时候一直显示Splash页面,直至数据加载完成后显示成功视图。

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

Android性能优化之Splash页应该这样设计

目前SplashActivity的设计目前市场上的应用在启动时基本上都会先启动一个SplashActivity,作为一个欢迎界面,为什么这样设计呢? 个人总结有三个优点:1、可以给用户更好的体验比如...

性能优化一-app启动速度及splash设计

App启动方式: 1冷启动:启动应用时后台没有该应用的进程,系统会重新创建一个该应用的进程分配与该应用,这种启动方式叫做冷启动  特点:因为系统会重新创建一个进程分配给应用,所以会创建并初始化ap...

提升应用的启动速度 和 splash页面的设计

我叫小马,我在坚持写一些东西,希望互相学习.我的博客是http://blog.csdn.NET/maqianli23 本博客地址:http://blog.csdn.net/maqianli23/...

android提高应用启动速度_splash页面瞬间响应_避免APP启动闪白屏

转自:http://blog.csdn.net/jason0539 Application和Activity中的onCreate都进行了优化,基本没有耗时操作,但是启动应用之后还是会闪现一下白色...

android开发之提高应用启动速度_splash页面瞬间响应_避免APP启动闪白屏

Application和Activity中的onCreate都进行了优化,基本没有耗时操作,但是启动应用之后还是会闪现一下白色背景,然后才进入Splash页面,对比了一下QQ、微信、微博等客户端,点击...

android开发:正确的开发一个Splash页面

虽然是一个小小的splash页面,可能有人说在里面写个线程一段时间结束就好了哈。 为啥我要写一篇文章介绍一下呢?如下解释:我在之前看到的一些splash页面的代码看到了很多有问题的写法。运行的不完美...

Android进阶之路 - Splash、Welcome欢迎页面的初始使用

欢迎页面在我们每个App中都是必不可少的,实现的方法也非常之多,下面为大家带来的是会用Handler的延迟操作实现的欢迎页面 。注释:SplashActivity 指的是我们的欢迎页面,这个layou...

Android阶段学习笔记 8.1-8.6 之 手机安全卫士 Splash页面

Splash界面检测更新,初始化数据,界面动画

Android 启动页面制作(Splash Screen)

制作启动页面的思路是这样:启动一个activity作为Splash Screen,延迟一定时间后再跳转到主要activity。 下面是Splash Screen的布局文件:...

Android引导页Splash设计

Android_Splash引导页就是在应用第一次安装时用来介绍应用的部分功能的动画页面,让用户大致的了解这个应用有啥功能。当用户首次安装时会有引导页面,用户下次启动的时候,就会直接进入主页面。 Sp...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android性能优化之Splash页面设计
举报原因:
原因补充:

(最多只允许输入30个字)