精华内容
下载资源
问答
  • 大家都知道,传统的手机状态栏非黑即白,经常让整个app显得不是那么的好看,如何让状态栏的颜色跟你整个界面的颜色能够融为一体,这是我们一直想要的,现在给大家展示一下: 由图可见,第一张是没有使用沉浸...

    http://www.cnblogs.com/ai394495243/p/5063842.html

    大家都知道,传统的手机状态栏非黑即白,经常让整个app显得不是那么的好看,如何让状态栏的颜色跟你整个界面的颜色能够融为一体,这是我们一直想要的,现在给大家展示一下:

    由图可见,第一张是没有使用沉浸式状态栏,显示的颜色为白色,由的手机显示的是黑色,第二张图,是实用了沉浸式状态栏,整体的视觉效果比第一张要好。

    那么如何使用沉浸式状态栏呢?首先我们要明白,沉浸式状态栏呢是在android 4.4,也就是api在19以上才使用的。

    我们先简单的说一个,如果我们整体的app颜色色调是一样的,我们可以直接在style里面直接设置:

    复制代码
    1.在color里面定义几个颜色
    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <color name="colorPrimary">#3F51B5</color>
        <color name="colorPrimaryDark">#303F9F</color>
        <color name="colorAccent">#FF4081</color>
    </resources>
    2.在style里面引用
    <resources>
        <!-- Base application theme. -->
        <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
            <!-- Customize your theme here. -->
           <!--导航栏的颜色-->
            <item name="colorPrimary">@color/colorPrimary</item>
            <!--状态栏的颜色-->
            <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        </style>
    </resources>
    3.在Androidmanifest里面直接定义主题  android:theme="@style/AppTheme"
    复制代码

    这个时候出来的效果时这样的:(想必大家已经看出效果了)

    那么我们又该在代码中如何去实现呢?上一篇,我简单给大家说一下toolbar的使用,下面我所写的在toolbar的基础上来添加的。(考虑到可能每个页面的颜色不一样,我们没法在使用主题的方式,我们则需要另换思路

    我们可以在baseActivity写一下几个方法:

    复制代码
    abstract public class BaseActivity extends AppCompatActivity implements IBaseView {
    
        private static final int ERROR_LAYOUT_ID = 0;
        protected Toolbar mToolBar;
    
        protected Drawable mStatusBarDrawable = UIUtil.getDrawable(R.drawable.drawable_login);
    
        protected int mToolBarTextColorResId = UIUtil.getColor(R.color.title_text_color_darker);
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
            super.onCreate(savedInstanceState);
            DialogUtils.dismissProcessDialog();
            if (isRegisterEventBus()) {
                EventBus.getDefault().register(this);
            }
    
            if (ERROR_LAYOUT_ID != getLayoutId()) {
                setContentView(getLayoutId());
    //是否改变状态栏的颜色
    if (isChangeStatusBarColor()) { setStatusBarColor(); setSystemBarTintDrawable(mStatusBarDrawable); // StatusBarCompat.compat(this, mStatusBarColorResId); } } mToolBar = (Toolbar) findViewById(R.id.tool_bar); if (null != mToolBar) { configToolBar(mToolBar); if (hasParentActivity()) { getSupportActionBar().setDisplayHomeAsUpEnabled(true); } } mProgressBarIndeterminate = (ProgressBarIndeterminate) findViewById(R.id.progress_bar_indeterminate); if (null != getLoadingTargetView()) { mChangeViewController = new ChangeViewController(getLoadingTargetView()); } initView(); initData(); } /** * 设置状态栏背景色 */ protected abstract void setStatusBarColor(); /** * 是否修改状态栏的背景色 * * @return */ protected abstract boolean isChangeStatusBarColor(); /** * 配置ToolBar 包括背景色字体颜色等 * 每个页面的属性可能不同 子类复写该方法 * * @param toolBar */ protected void configToolBar(Toolbar toolBar){ setSupportActionBar(toolBar); mToolBar.setBackgroundDrawable(mStatusBarDrawable); mToolBar.setTitleTextColor(mToolBarTextColorResId); } /** * 初始化相关数据 */ public abstract void initData(); /** * 初始化布局内的控件 */ public abstract void initView(); /** * 获取当前界面的布局ID * * @return 当前界面的布局ID */ abstract public int getLayoutId(); /** * use SystemBarTintManager * * @param tintDrawable */ protected void setSystemBarTintDrawable(Drawable tintDrawable) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { SystemBarTintManager mTintManager = new SystemBarTintManager(this); if (tintDrawable != null) { mTintManager.setStatusBarTintEnabled(true); mTintManager.setTintDrawable(tintDrawable); } else { mTintManager.setStatusBarTintEnabled(false); mTintManager.setTintDrawable(null); } } } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { //重写ToolBar返回按钮的行为,防止重新打开父Activity重走生命周期方法 case android.R.id.home: finish(); return true; } return super.onOptionsItemSelected(item); } }
    复制代码

    然后我们在需要的activity里面继承baseactivity 实现他的方法,

    复制代码
    @Override
        protected void setStatusBarColor() {
    //这里时你状态栏所要改变的颜色,这里用的是deawable
            mStatusBarDrawable = UIUtil.getDrawable(R.drawable.drawable_home);//这是在value下自建一个xml文件,专门用来每个页面状态栏所需要的颜色
        }
    
        @Override
        protected boolean isChangeStatusBarColor() {
    //这个是是否改变状态栏的一个状态
            return true;
        }
    复制代码

    这里,基本上怎么使用沉浸式状态栏几本上说完了,但是我们要注意,4.4和5.0以上还是有一定的区别的,

    因为4.4原生态android上是没有的,而5.0以后android 原生态上是有的,4.4之后加入windowTranslucentStatus的属性之后,也就是我们可以用到状态栏的区域了,而5.0提供了setStatusBarColor去设置状态栏颜色,但是这个方法不能在主题中设置windowTranslucentStatus属性。我们在style里面就不再设置windowTranslucentStatus属性。

    详细的介绍可以看http://blog.csdn.net/lmj623565791/article/details/48649563

    展开全文
  • 或者是页面加载出来了,但是比较慢,页面显示不完整,标签栏一直在转圈,页面长期处于不可交互的状态,这也是一种很不好的体验。如何评价一个页面打开得快不快,可以用两个指标描述,一个是ready的时间,另一个是...
  • 或者是页面加载出来了,但是比较慢,页面显示不完整,标签栏一直在转圈,页面长期处于不可交互的状态,这也是一种很不好的体验。 如何评价一个页面打开得快不快,可以用两个指标描述,一个是ready的...

    页面的打开速度对网站的优化有极大的意义,如果打开一个页面一直处于白屏状态,比如TTFB超过5秒,可能大部分人都会把它关掉。或者是页面加载出来了,但是比较慢,页面显示不完整,标签栏一直在转圈,页面长期处于不可交互的状态,这也是一种很不好的体验。


    如何评价一个页面打开得快不快,可以用两个指标描述,一个是ready的时间,另一个是load的时间。这个可以从Chrome的控制台看到,如打开stackoverflow.com网站的首页:


    一共是加载490KB,ready时间是7.36s,load时间是17.35s。再来看下打开谷歌的情况:


    虽然两个页面的内容差别比较大,但是从时间来看的话,很明显谷歌的速度要明显优于stackoverflow,谷歌的ready时间只有2.22s,也就是说2.22秒之后带个页面就是布局完整可交互的了,而stackoverflow打开的时候较长时间处于空白状态,可交互时间达要到7.36s。


    从load时间来看的话,两者差别不太,都比较长,可能因为它们是境外的服务器。finish时间比load时间长,是因为load完后又去动态加载了其它的js。


    为什么stackoverflow的ready时间要这么长呢?下面分点介绍优化的策略


    01减少渲染堵塞


    (1)避免head标签JS堵塞

    所有放在head标签里的css和js都会堵塞渲染。如果这些CSS和JS需要加载和解析很久的话,那么页面就空白了。看stackoverflow的html结构:

    <head>
        <title>Stack Overflow</title>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
    </head>

    它把jquery放到了head标签里,这个jquery加载了3s:

    相比之下,html文件只加载了0.83s,所以这个js文件至少使页面停留了3s的空白状态。


    它的解析花了20ms不到:


    这个解析时间还是可以忽略,相对于加载时间而言。并且我们注意到即使把jquery给删了,stackoverflow的页面还是可以完整显示的,样式无异,这个可以复制它的源代码到本地然后删掉head里面的script标签打开页面观察。也就是话,把js放头部是没太大必要的。最关键的是它用的是谷歌的cdn,这样就导致了大陆的小伙伴们无法在正常的环境下看stackoverflow,一打开整个页面一两分钟都保持空白态。


    有两种解决办法,第一种是把script放到body后面,这也是很多网站采取的方法。第二种是给script加defer的属性,defer是html5新增的属性。一旦script是defer延迟的,那么这个script将会异步加载,但不会马上执行,会在readystatechange变为Interactive后按顺序依次执行,用以下demo做说明:

    <!DOCType html>
    <html>
    <head>
        <meta charset="utf-8">
        <script src="defer.js" defer></script> 
    </head>
    <body>
        <script>
            document.onreadystatechange = function(){
                console.log(document.readyState);
            };
        </script>
        <script>
            window.onload = function(){
                console.log("window is loaded");
            };
            window.addEventListener("DOMContentLoaded", function(){
                console.log("dom is ready");
            });
        </script>
        <img src="test.jpg" alt="">
        <script src="normal.js"></script>
        <script>
            console.log("dom almost built");
        </script>
    
    </body>
    </html>

    defer.js的内容为:

    console.log("I'm defered");for(var i = 0; i < 10000000; i++){
        new Date();
    }
    console.log("defer script end");

    中间让它执行一段较长的时间(约3秒),normal.js内容类似,打印的log:

    可以看到,正常的script最先执行,然后紧接着的内联script依次执行,说明正常script是串行执行的,不过它们可以是并行加载,例如stackoverflow写在head标签里面的这两个正常的script是并行加载的:

    回到上面,第四行readystatechange变成interactive,然后开始执行defer的script,执行完后依次触发ready和load事件。


    也就是说,defer的脚本会正常加载,但是延后执行,在interactive后执行,所以不会block页面渲染。因此放在head标签的script可以加一个defer,但是加上defer的脚本发生了重大的变化,不能够影响渲染DOM的过程,只能是在渲染完了,例如绑的click事件在整个页面没渲染好之前不能生效。并且很多人要把它写在head里面,是为了在页面中间的script能调用到这些库,影响DOM的渲染,加上defer就违背本意了。但是把script写在head标签始终是不推荐的,所以在页面中间的script要么使用原生的API,要么把一些用到的函数写成head标签里面的内联script。


    head标签里面的defer脚本跟放在body后面的脚本有什么区别呢,区别在于defer的脚本会马上加载,一旦页面interactive了便可以马上执行,而放body后面是document快interactive的时候才去加载。我们知道,浏览器同时加载资源数是有限的,例如Chrome对同一个域名的资源,每次最多同时只能建立6个TCP连接(读者可以试试)。所以写在head标签里面的外链脚本会影响页面图片的加载,特别是当脚本很多时。因此,如果页面的交互比图片的展示更重要,那么把script写在head标签加上defer是可取的,如果页面的展示更为重要,那么应该把脚本放在body后面。


    另外,defer可能会有兼容性问题,在老的浏览器上某些行为表现可能会不一致。


    同样地,head标签里面的CSS资源也会block页面渲染。


    (2)减少head标签里的CSS资源

    由于CSS必须要放在head标签里面,如果放在body里面,一旦加载好之后,又会对layout好的dom进行重排,样式可能又会发生闪烁。但是一旦放在head标签里面又会堵塞页面渲染,若要加载很久,页面就会保持空白状态。所以要尽可能地减少CSS的代码量。


    a) 不要放太多base64放在CSS里面

    放太多base64放在CSS里面,会导致CSS极速膨胀,把一张3k的图片转成base64,体积将会变成4k:


    假设放了10张3k的图片,那么CSS将增大40K,这已经和一个普通大小的CSS文件相仿。笔者曾为了解决一个hover变色的问题:

    原始图片都是svg的格式,hover的时候变成蓝色,如果这样写的话:

    .img{
        background: url(black.svg) 0 0 no-repeat;
    }
    
    .img:hover{
        background: url(blue.svg) 0 0 no-repeat;
    }

    会导致hover的时候才去加载blue.svg,第一次hover的时候不会马上变蓝,要稍微等到图片下载下来了,在产品角度上是不可接受的。所以第一种解决办法是把hover写在svg里面,如下:

    <svg>
    <style type="text/css">
        .st0{fill:#282828;}
        .st0:hover{fill: #3399cc;}
    </style>
    
    </svg>

    但是由于下面的文字也要跟着变蓝,文字又不能放在svg里面控制,svg变成外链引进来之后,它就跨域了,无法在外面的html用CSS控制一个跨域的svg的样式,如果把svg变成内联的,又会导致html体积过大,同时对缓存也是不利的。所以当时提议,把svg转成base64放到CSS里面,黑色和蓝色的各转成base64,总共要转6 * 2 = 12个,由于原始的svg本来就比较大,再转成base64就更大了,7k变成了9k,再乘以12,整个CSS就增加了100多K。这样就导致了CSS要加载很久。


    最后压缩后的CSS文件有179Kb:

    -rw-r–r–  1 yincheng  staff   179K Mar 10 17:45 common-fbc013bb2526235952078ccd72a7fc97.css


    好在开启了gzip压缩,实际传输的大小为30K:

    不管怎样,这种方法依旧是不推荐的。最后采取了图标字体的解决方案,将svg转成字体icon,方便颜色控制。脱离图片后的CSS文件只有22Kb:

    -rw-r–r–  1 yincheng  staff    22K Mar 10 17:45 common-def3ac6078614e995ca8.js


    gzip压缩后不到10Kb。


    上面的例子是避免动态加载,而有时候要动态加载,当使用媒体查询的时候,如下所示:

    @media(min-width: 501px){
        .img{
            background-picture: url(large.png);
        }
    }
    
    @media(max-width: 500px){
        .img{
            background-picture: url(small.png);
        }
    }

    上面大屏的时候加载large的图片,小屏的时候加载small的图片,浏览器会根据屏幕大小自动加载相应的图片。而一旦你把它转成了base64之后,它们都在CSS里面了,就没有自动加载的优势了。


    b)把CSS写成内联的:

    如果你的CSS只有10K或者20K,把它写成内联的,也未尝不可,谷歌和淘宝PC就是这样干的,直接把页面几乎所有的CSS都写成style标签放到html里面:

    这个原始的CSS有66Kb:

    -rw-r–r–  1 yincheng  staff    66K Mar 12 10:00 taobao.css


    gzip之后为16Kb:

    这样虽然对缓存不利,但是对于首次加载是有很大的作用的。因为如果你把CSS放到CDN上,为了得到这个CSS,它首先需要进行域名解析,然后建立http/https连接,其次才是下载。而用来做域名解析和建立连接的时候很可能早已把放在html里面的CSS下载下来了,这个时间可以从Chrome的控制台观察到:

    为了加载这个资源,DNS查找花掉了0.5s,建立tcp连接花掉了0.95s,建立https连接花掉了0.6s,从发请求到收到第一个字节的数据(Time To First Byte)又花掉了1.27s,总的时间接近3s。


    所以这个开销还是很大的。还不如直接把CSS嵌到HTML里面。如果你的CSS体积没达到3位数,加上gzip压缩,放到html里面应该是可取的。


    02优化图片


    (1)使用响应式图片

    响应式图片的优点是浏览器能够根据屏幕大小、设备像素比ppi、横竖屏自动加载合适的图片,如下使用srcset:

    <img srcset="photo_w350.jpg 1x, photo_w640.jpg 2x" src="photo_w350.jpg" alt="">

    如果屏幕的ppi = 1的话则加载1倍图,而ppi = 2则加载2倍图,手机和mac基本上ppi都达到了2以上,这样子对于普通屏幕来说不会浪费流量,而对于视网膜屏来说又有高清的体验。


    如果浏览器不支持srcset,则默认加载src里面的图片。


    但是你会发现实际情况并不是如此,在Mac上的Chrome它会同时加载srcset里面的那张2x的,还会再去加载src里面的那张,加载两张图片。顺序是先把所有srcset里面的加载完了,再去加载src的。这个策略比较奇怪,它居然会加载两张图片,如果不写src,则不会加载两张,但是兼容性就没那么好。这个可能是因为浏览器认为,既然有srcset就不用写src了,如果写了src,用户可能是有用的。


    而使用picture就不会加载两张:

    <picture>
        <source srcset="banner_w1000.jpg" media="(min-width: 801px)">
        <source srcset="banner_w800.jpg" media="(max-width: 800px)">
        <img src="banner_w800.jpg" alt="">
    </picture>

    如上,如果页面宽度大于800px(PC),则加载大图,而在手机上加载小图。这样写浏览器就只会加载source里面的一张图片。但是如果是用js动态插进去的,它还是会去加载两张,只有写在html里面加载初始化页面的时候才只加载一张。


    这个的解决方法很简单,浏览器支不支持srcset,可以用js判断。如果支持,则不写src的属性了,如果不支持就不用写srcset了:

    var supportSrcset = 'srcset' in document.createElement('img');
    var surportPicture = 'HTMLPictureElement' in window;

    picture必须要写img标签,否则无法显示,对picture的操作最后都是在img上面,例如onload事件是在img标签触发的,picture和source是不会进行layout的,它们的宽和高都是0。


    另外使用source,还可以对图片格式做一些兼容处理:

    <picture>
        <source type="image/webp" srcset="banner.webp">
        <img src="banner.jpg" alt="">
    </picture>

    上面Chrome浏览器将会加载webp格式的图片:

    webp在保持同等清晰度的情况下,体积可以减少一半,但是目前只有Chrome支持,Safari和firefox一直处于实验阶段,所以其它的浏览器如firefox将会加载jpg格式的照片:

    可以看到原图是68k,转成webp之后变成了45k,如果你把jpg有损压得比较厉害,例如质量压为0.3,可以比webp更小,但是失真也比较厉害了。


    (2)延迟加载图片

    对于很多网站来说,图片往往是占据最多流量和带宽的的资源。特别是那种瀑布式展示性的网站,一个页面展示50本书,50张图片,如果一口气全部放出来,那么页面的Loaded时间将会较长,并且由于并行加载资源数是有限,图片太多会导致放body后面的js解析比较慢,页面将较长时间处于不可交互状态。所以不能一下子把全部图片都放出来,这对于手机上的流量也是不利的。


    为此,笔者做了个懒惰加载图片的尝试,初始加载页面的时候并不去加载图片,只有当用户下滑到相应位置的时候才把图片放出来。首先,渲染页面的时候别把图片地址放到src上,放到一个data的属性:

    <picture>
        <source data-srcset="photo_w350.jpg 1x, photo_w640.jpg 2x">
        <img data-src="photo_w350.jpg" src="about:blank" alt="">
    </picture>

    如上,放到data-src和data-srcset里面,上面把src的属性写成了”about:blank”,这是因为不能随便写一个不存在的地址,否则控制台会报错:加载失败,如果写成空或不写,那么它会认为src就是当前页面。如果写成about:blank,大家相安无事,并且不同浏览器兼容性好。


    接下来进行位置判断,监听scroll事件,回调函数为:

    showImage(leftSpace = 500){
        var scrollTop = $window.scrollTop();
        var $containers = this.$imgContainers,
            scrollPosition = $window.scrollTop() + $window.height();    for(var i = 0; i < $containers.length; i++){
            //如果快要滑到图片的位置了
            var $container = $containers.eq(i);        if($container.offset().top - scrollPosition < leftSpace){
                this.ensureImgSrc($container);
            }   
        }   
    }

    第5行for循环,依次对所有的图片做处理,第8行的if判断,如果滑动的位置快要到那张图片了,则把src放出来,这个位置差默认为500px,如果图片加载得快的话,这种行为对于用户来说是透明的,他可能不知道图片是往下滑的时候才放出来的,几乎不会影响体验,如果用户滑得很快,本身不做这样的处理,也不可能加载得这么快,也是loading的状态。


    下面的函数把图片放出来:

    ensureImgSrc($container){
        var $source = $container.find("source");    if($source.length && !$source.attr("srcset")){
            $source.attr("srcset", $source.data("srcset"));
        }   
        var $img = $container.find("img:not(.loading)");    if($img.length && $img.attr("src").indexOf("//") < 0){ 
            $img.attr("src", $img.data("src"));
            this.shownCount++;
        }
    }

    代码里面判断src是不是有”//”,即为正常的地址,如果没有给它赋值,触发浏览器加载图片。并记录已经放出来的个数,这样可以做个优化,当图片全部都加载或者开始加载了,把scroll事件取消掉:

    init(){
        //初始化
        var leftSpace = 0;
        this.showImage(leftSpace);
        //滑动
        $window.on("scroll", this, this.throttleShow);
    }
    
    ensureImgSrc($container){
        //如果全部显示,off掉window.scroll    if(this.shownCount >= this.allCount){
            $window.off("scroll", this.throttleShow);
        }
    }

    这样可以大大减少打开页面的流量,加快ready和load的时间。


    03压缩和缓存


    (1)gzip压缩

    上文已提及,使用gzip压缩可以大大减少文件的体积,一个180k的CSS文件被压成了30k,减少了83%的体积。如何开启压缩呢,这个很简单,只要在nginx的配置里面添加这个选项就好了:

    server{
        gzip on;
        gzip_types    text/plain application/javascript application/x-javascript text/javascript text/xml text/css;
    }


    (2)Cache-Control

    如果没有任何缓存策略,那么对于以下页面:

    <!DOCType html>
    <html>
    <head>
        <link href="test.css" rel="stylesheet">
    </head>
    <body>
    <picture>
        <source type="image/webp" srcset="banner.webp">
        <img src="banner.jpg" alt="">
    </picture>
    <script src="normal.js"></script>
    </body>
    </html>

    总共有4个资源,html、css、img和js各一个,第一次加载都为200:


    刷新页面第二次加载时:

    除了html,其它三个文件都是直接在本地缓存取的,这个是Chrome的默认策略。html是重新去请求,nginx返回了304 Not Modified。


    为什么nginx知道没有修改呢,因为在第一次请求的时候,nginx的http响应头里面返回了html的最近修改时间:

    在第二次请求的时候,浏览器会把这个Last-Modified带上,变成If-Modified-Since字段:

    这样nginx就可以取本地文件信息里的修改时间和这个进行比较,一旦时间一致或者在此之前,直返回304,告诉客户端从缓存取。笔者的nginx版本默认是开启last-modified,有些网站并没有开启这个,每次都是200重新请求。如果把文件编辑了保存,nginx会重新返回一个最近修改时间。


    除了last-modified字段之外,还可以手动控制缓存时间,那就是使用Cache-Control,例如设置图片缓存30天,而js/css缓存7天:

    location ~* \.(jpg|jpeg|png|gif|webp)$ {
        expires 30d;
    }       
    location ~* \.(css|js)$ {
        expires 7d;
    }

    这样响应头就会加一个Cache-Control: max-age=604800(s):

    这个和last-modified有什么区别呢,如果把expires改成3s:

    location ~* \.(css|js)$ {
        expires 3s;
    }

    不断刷新,观察加载情况:


    第一次请求还是200,第二次请求css/js都是cached,过了3秒之后的第三次请求,css/js变成了304:


    从这里可以看出max-age的优先级要大于last-modified。如果要强制不缓存,则把expires时间改成0.


    上面的结果都是用Chrome实验,firefox的和Chrome比较一致,而Safari差别比较大,即使设置Cache-Control,仍然还是会有304的请求,并且html永远是200重新加载,它没有把last-modified和cache-control带上。


    综上,设置缓存的作用一个是把200变成304,避免资源重新传输,第二个是让浏览器直接从缓存取,连http请求都不用了,这样对于第二次访问页面是极为有利的。设置缓存还有第三种技术,使用etag。


    (3)使用etag

    上面的两种办法都有缺点,由于很多网站使用模板渲染,每次请求都是重新渲染,生成的文件的last-modified肯定是不一样的,所以last-modified在这种场景下失效,而使用max-age你无法知道精确控制页面的数据什么时候会发生变化,所以max-age不太好使。这个时候etag就派上用场了。nginx开启etag只需要在server配置里面加上一行:

    etag on;

    所谓etag就是对文件做的一个校验和,第一次访问的时候,响应头里面返回这个文件的etag,浏览器第二次访问的时候把etag带上,nginx根据这个etag和新渲染的文件计算出的etag进行比较,如果相等则返回304。


    如下,第一次访问返回etag:

    第二次访问带上etag,在If-None-Match字段:

    服务返回304,如果我把html文件修改了,那么这个etag就会发生变化,服务返回200:

    由于etag要使用少数的字符表示一个不定大小的文件,所以etag是有重合的风险,如果网站的信息特别重要,连很小的概率如百万分之一都不允许,那么就不要使用etag了。


    我们可以看到youku就是用的etag:

    使用etag的代价是增加了服务器的计算负担,特别是当文件比较大时。


    04 其它优化方案


    (1)DNS预读取

    上文已提到域名解析可能会花很长的时间,而一个网站可能会加载很多个域的东西,例如使用了三个自已子域名的服务,再使用了两个第三方的CDN,再使用了百度统计/谷歌统计的代码,还使用了其它网站上的图片,一个网站很可能要加载七、八个域的资源,第一次打开时,要做七、八次的DNS查找,这个时间是非常可观的。因此,DNS预读取技术能够加快打开速度,方法是在head标签里面写上几个link标签:

    <link rel="dns-prefection" href="https://www.google.com">
    <link rel="dns-prefection" href="https://www.google-analytics.com">
    <link rel="dns-prefection" href="https://connect.facebook.net">
    <link rel="dns-prefection" href="https://googleads.g.doubleclick.net">
    <link rel="dns-prefection" href="https://staticxx.facebook.com">
    <link rel="dns-prefection" href="https://stats.g.doubleclick.net">

    如上,对以上向个网站提前解析DNS,由于它是并行的,不会堵塞页面渲染。这样可以缩短资源加载的时间。


    (2) html优化

    把本地的html布署到服务器上前,可以先对html做一个优化,例如把注释remove掉,把行前缩进删掉,如下处理前的文件:

    <!DOCType html>
    <html>
        <head>
            <meata charset="utf-8">
        </head>
    </html>
        <body>
            <!-main content-->
            <div>hello, world</div>
        </body>
    </html>

    处理后的文件:

    <!DOCType html>
    <html>
    <head>
    <meata charset="utf-8">
    </head>
    </html>
    <body>
    <div>hello, world</div>
    </body>
    </html>

    这样处理的文件可以明显减少html的体积,特别是当一个tab是4个空格或者8个空格时。


    可以作一个比较,以youku为例,把它的html复制出来,然后再把它每行的行首空格去掉:

    从687K减少了200Kb,约为1/3,这个量还是很可观的。对其它网页的实验,可以发现这样处理普遍减少1/3的体积。而且这样做几乎是没有风险,除了pre标签不能够去掉行首缩进之外,其它的都正常。


    (3)代码优化

    对自己写的代码做优化,提高运行速度,例如说html别嵌套太多层,否则加重页面layout的压力,CSS的选择器别写太复杂,不然匹配的计算量会比较大,对JS,别滥用闭包,闭包会加深作用域链,加长变量查找的时间,如下:

    var a = 15;
    function foo(){
        var b = a + 3;
        function bar(){
            var c = b + a;
        }    return bar();
    }

    在bar这个函数里面,它为了查找a这个变量,需要在bar的作用域,再到foo的作用域,再到全局作用域进行查找。


    上文从页面堵塞、图片优化、开启缓存、代码优化等角度介绍了优化页面加载的方案,但其实上面的只是一些参考建议,可能不能放之四海皆通,读者应该要结合自己网站的实际情况做一些分析,找到瓶颈问题。如果不确实就反复实践,直到发现一些合适的方法。

    展开全文
  • 如何设置一个窗口总在最前(Exaware OnTop和PushPin)软件下载 Windows中打开一个新窗口或切换任务时,原有的活动窗口就会被它所覆盖。不过,像Winamp等软件,却有一个能自己的操作窗口总在最前的功能,非常实用...
  • 赋值为11,这样初始分页显示有3页,第一页显示根据查询条件得到的5个结果,点击第二页时,从后台看,action可以得到查询参数并返回5条结果,但是gridpanel里的数据并没有更新,现在的问题是如何让gridpanel根据...
  • 温抖丝,每周发布1-2篇如何使用手机、平板等科技设备的知识分享文章,是送给长辈们最好的礼物。​“通知是指在应用界面之外显示的消息,旨在向用户提供消息... 通知栏从手机状态栏(最上方显示电量、时间和信号的位...

    温抖丝,每周发布1-2篇如何使用手机、平板等科技设备的知识分享文章,是送给长辈们最好的礼物。

    ​“通知是指在应用界面之外显示的消息,旨在向用户提供消息提醒、来自他人的信息或者应用中的其他信息。”

    葫芦妈通常晚上10点躺下睡觉,可群里的消息一直响会打扰她的睡眠。如果您也苦于被打扰,请继续读完这篇文章。让我们看看手机上的通知是怎么回事。

    通知的几种形式

    1. 通知栏

    从手机状态栏(最上方显示电量、时间和信号的位置)向下滑动打开抽屉式通知栏(很形象的互联网用语,像抽屉一样拉开的状态),可以查看通知并执行操作。通知会在抽屉式通知栏中保持可见状态,直到您将它关闭。

    下图的通知分别来自“信息”、“运动健康”、“掌上生活”和“澎湃新闻”四个应用,分别用来提醒话费余额、步数、消费金额和新闻等消息。

    92f32b78702eb7669540b2c7c8663b23.png

    手机通知栏

    2. 浮动通知

    浮动通知通常比较重要,例如微信消息和短信。它会在手机上方短暂浮现,然后消失,之后仍在抽屉式通知栏显示。看到浮动通知立刻点击它,就会跳转(互联网用语,指从一个页面进入另一个页面)到消息页面。

    94c1f28b1b920e0a2868d0f7ac6bfd3f.png

    收到一条来自短信的浮动通知

    3. 锁屏通知

    如果手机处在锁屏状态(需要人脸、指纹或者密码解锁的状态),那么通知到达时会在锁定屏幕上显示。

    锁屏通知是否显示全部内容,取决于手机的设置。

    faa052d5fe561e44df2a71518b625efa.png

    锁屏状态收到通知

    4. 小红点

    最后一种俗称“小红点”的通知方式在这里打算留个悬念,为强迫症患者提供一个发言的机会,哈哈。

    4f6c9c864d6e64d3a17c6ef5feb68878.png

    强迫症受不了“小红点”

    看过了通知的几种“面具”,我们就可以想办法应对了。

    如何控制这些通知

    1. 通知栏上最自由

    通知栏上的通知是可以自由设置的。

    向左滑动,然后点击“齿轮”按钮(通常齿轮图标代表设置),在弹出的界面中选择“关闭通知”或者“设为静默通知”。

    两者的区别是,关闭通知后这个应用无法主动给手机发通知;而静默通知代表手机收到通知时不使用声音或者震动提醒。

    e4a6efd7bda316d3c05196af81e7126b.png

    不同手机的操作方式不同

    或者,使用向右滑动的手势删除它,代表已经读过这条消息。

    9f6b9b23d745a7803b9156c07f48e302.png

    不同手机的操作方式不同

    2. 浮动通知要管吗?

    对于浮动通知,如果不查看,它会继续显示在通知栏。

    可以在它浮动显示时用手指向上/下/左/右滑动删除它,代表已经读过这条消息。

    844d84ea941c12d901e09bf82c7f70a9.png

    不同手机的操作方式不同

    3. 锁屏通知可以隐藏?

    隐藏锁屏通知通常是从安全方面考虑,如果不隐藏任何人拿到手机都可以看到屏幕上的新消息,所以最好设置锁屏时隐藏通知内容。

    方法如下:

    423f8d81e20a359509a566ddb1e4a986.png

    不同手机的操作方式不同

    终极方案

    应对睡觉时被打扰的终极方案是将手机设置静音,静音后在收到消息时手机不会通过声音或者震动提醒用户。

    简便的操作方式是从状态栏下滑,打开通知栏,然后点击“小铃铛”按钮(通常“小铃铛”图标代表声音设置);

    也可以在手机的设置 - 声音和震动中完成静音设置。

    c1a66dff4063517241d84859bb099f20.png

    不同手机的操作方式不同

    好了,今天的分享就到这,是不是可以安静的睡个觉了?

    请知晓:文中截图使用的是华为手机,如果您是苹果手机,请在评论区留言。但是,要记住“万变不离其宗”,他们的操作都是相通的。


    觉得有收获就关注温抖丝,或者在评论区留言,小葫芦会一一回复。

    063d3fb6a179bc73dc94a9fbe5609148.png

    丝葫芦,喜欢为父母答疑解惑的理工科男孩纸。

    展开全文
  • Fcitx cpu占用很大问题解决

    千次阅读 2020-03-04 20:38:02
    最近,不知为何,我的Ubuntu 18.04 电脑在打开之后风扇一直转个不停,声音很大,然而人不解的是,我并没有打开多少程序,状态栏显示CPU占用率为 35% ,不正常,我打开终端,输入top指令,查看各个进程使用CPU的...

    本篇博客介绍如何解决 Fcitx 占用CPU比较高的问题

    最近,不知为何,我的Ubuntu 18.04 电脑在打开之后风扇一直转个不停,声音很大,然而让人不解的是,我并没有打开多少程序,状态栏显示CPU占用率为 35% ,不正常,我打开终端,输入top指令,查看各个进程使用CPU的情况,发现一个名叫 Fcitx的进程占用CPU比较高。

    什么是 Fcitx

    百度百科:Fcitx 是 (Free Chinese Input Toy for X) 的英文缩写,中文名为小企鹅输入法,是一个以 GPL 方式发布的输入法框架, 编写它的目是为桌面环境提供一个灵活的输入方案,彻底解决在GNU/Linux下没有一个好的中文输入法的问题。

    初步解决

    通过top指令可知 ,Fcitx是普通用户启动的一个进程,所以我直接kill 掉了,然后CPU占用率马上就下来了。但是我重启之后,有一定的概率还会遇到这种问题,所以我查阅资料找到了一劳永逸的办法:

    问题原因

    搜狗输入法的搜狗云拼音支持组件占用CPU比较大

    完美解决

    在状态栏选择搜狗输入法的设置
    在这里插入图片描述
    选择高级设置,打开 Fcitx配置界面(或者通过其它途径打开 Fcitx配置界面)
    在这里插入图片描述
    选择附加组件,选中高级,取消搜狗云拼音的勾选。大功告成。
    在这里插入图片描述
    重启之后 Fcitx 就不会占用很高的CPU了。也可以直接kill 掉Fcitx 进程。

    展开全文
  • delphi 开发经验技巧宝典源码

    热门讨论 2010-08-12 16:47:23
    8.6 工具栏、状态栏及下拉列表 187 0288 制作带历史信息的菜单 187 0289 制作可以拉伸的菜单界面 188 0290 制作类似于XP颜色的下拉页 188 0291 在系统菜单中添加菜单项 189 0292 在状态栏中放置其他组件...
  • 8.6 工具栏、状态栏及下拉列表 187 0288 制作带历史信息的菜单 187 0289 制作可以拉伸的菜单界面 188 0290 制作类似于XP颜色的下拉页 188 0291 在系统菜单中添加菜单项 189 0292 在状态栏中放置其他组件...
  • 8.6 工具栏、状态栏及下拉列表 187 0288 制作带历史信息的菜单 187 0289 制作可以拉伸的菜单界面 188 0290 制作类似于XP颜色的下拉页 188 0291 在系统菜单中添加菜单项 189 0292 在状态栏中放置其他组件...
  • 8.6 工具栏、状态栏及下拉列表 187 0288 制作带历史信息的菜单 187 0289 制作可以拉伸的菜单界面 188 0290 制作类似于XP颜色的下拉页 188 0291 在系统菜单中添加菜单项 189 0292 在状态栏中放置其他组件...
  • 8.6 工具栏、状态栏及下拉列表 187 0288 制作带历史信息的菜单 187 0289 制作可以拉伸的菜单界面 188 0290 制作类似于XP颜色的下拉页 188 0291 在系统菜单中添加菜单项 189 0292 在状态栏中放置其他组件...
  • 8.6 工具栏、状态栏及下拉列表 187 0288 制作带历史信息的菜单 187 0289 制作可以拉伸的菜单界面 188 0290 制作类似于XP颜色的下拉页 188 0291 在系统菜单中添加菜单项 189 0292 在状态栏中放置其他组件...
  • 最近一直在搞屏幕大小的事,项目开发适配屏幕大小 800*480 * 强制横屏之后,设置全屏,设置控件位置、大小,但是发现实际上使用的屏幕高度老是...难道是状态栏?可我已经设置全屏了,有没有办法我把这48px也用上?
  • Visual Studio程序员箴言--详细书签版

    热门讨论 2012-10-16 20:37:39
    技巧1.36 隐藏状态栏 25 第2章 编辑器的使用得心应手 26 2.1 高级编辑 26 2.1.1 选择 26 技巧2.1 使用编辑器中的块/列选择 26 技巧2.2 按Esc键时跳转到所选文本的开始处 27 技巧2.3 使用Ctrl+=键选择...
  • 6)状态栏:建议将所有选项勾选,在状态栏可以看到很多东西。 7)快捷方式:有一个很强大的功能,就是选中“在任务栏显示托盘符”,这样在任务栏可以方便的进行各种操作(通过自定义托盘图标)。 其他的选项您可以...
  • MAPGIS地质制图工具

    2013-05-06 16:15:30
    第七步:选择附加任务:创建桌面快捷方式和快捷启动快捷方式,以及Section关联MapGis文件等。勾选所需选项,点击“下一步”,开始准备安装; 第八步:点击“安装”。直至最后,不想在安装完成后运行Section程序请去...
  • Toad 使用快速入门

    2008-11-27 15:22:14
    3. 自动用不同颜色显示SQL和PL/SQL关键字,语法清晰明了,可根据自己的习惯来具体定制各类关键字的具体显示方式。可以自定义存储过程得模板,在新建存储过程的时候,自动生成程序的框架可以方便的调用Schema ...
  • iPhone开发秘籍(第2版)--详细书签版

    热门讨论 2012-12-11 13:42:25
    4.3.1 状态栏 117 4.3.2 导航栏、工具栏和选项卡栏 118 4.3.3 键盘和拾取器 119 4.3.4 文本字段 120 4.3.5 UIScreen类 120 4.4 构建界面 120 4.5 实战演练:使用IB构建温度单位转换器 121 4.5.1 新建项目 ...
  • 我们按下按钮,会弹出一个对话框,无论如何关闭这个对话框,都会回到主窗口。 实现原理: 程序里我们先建立一个主工程,作为主界面,然后再建立一个对 话框类,将其加入工程中,然后在程序中调用自己新建的对话框类...
  • iPhone开发秘籍(第2版)--源代码

    热门讨论 2012-12-11 13:51:22
    4.3.1 状态栏 117 4.3.2 导航栏、工具栏和选项卡栏 118 4.3.3 键盘和拾取器 119 4.3.4 文本字段 120 4.3.5 UIScreen类 120 4.4 构建界面 120 4.5 实战演练:使用IB构建温度单位转换器 121 4.5.1 新建项目 ...
  • 从2.1版开始,通过几个简单的步骤,更可浮动窗口以不规则窗口的形式显示(步骤见【基础教程】)。 3: 界面美观,操作人性  多任务定时器在经过用户反馈后,进行了各种细微的改进。2.1版的界面更  经过...
  • 如何操作? 解决:方法一,按一个Alt+C,可以你一次性用鼠标从当前位置向不同方向选中一个矩形范围。 方法二,与Word要实现此项功能一样,必须要按住“Alt”再用鼠标进行才行。 2、为什么不能进行列选择?会提示...
  • Android 在屏幕旋转时,会销毁视图和 Activity 并重建,此时如何保存视图状态和已加载的数据、正在进行的网络请求即是问题。 Android 对部分视图状态提供了自动保存恢复,而豆芽对于其他需要保存的状态则通过自定义...
  • 如何让代码变得更加容易让人维护? 直接看我这篇博客:https://juejin.im/post/5c46e6fb6fb9a049a5713bcc 4.6 存在待解决问题 动态的管理组件,所以给每个组件添加几个生命周期状态:加载、卸载和降维。为此...
  • 2.5.6 版应网友要求取消气球提示,改为状态栏提示。 2.5.5 版增强对语言栏丢失时的修复功能(有时需要注销后方可生效)。 2.5.4 版修订设置热键时小键盘某些键值不对的问题。 2.5.3 版修订启动时检测输入法风格可能...
  • 入门学习Linux常用必会60个命令实例详解doc/txt

    千次下载 热门讨论 2011-06-09 00:08:45
    因为Linux与Windows不同,其后台运行着许多进程,所以强制关机可能会导致进程的数据丢失,使系统处于不稳定的状态,甚至在有的系统中会损坏硬件设备(硬盘)。在系统关机前使用 shutdown命令,系统管理员会通知所有...
  • WINRAR压缩软件

    2019-01-21 14:07:03
    这款软件在DOS 时代就一直具备这种优势,经过多次试验证明,这款软件的 RAR 格式一般要比其他的 ZIP 格式高出 10%~30% 的压缩率,尤其是它还提供了可选择的、针对多媒体数据的压缩算法。 2、对多媒体文件有独特的...

空空如也

空空如也

1 2 3
收藏数 54
精华内容 21
关键字:

如何让状态栏一直显示