异步加载_异步加载图片 - CSDN
精华内容
参与话题
  • JS异步加载的三种方式

    万次阅读 2018-06-22 10:26:15
    一:同步加载 我们平时使用的最多的一种方式。 <script src="http://yourdomain.com/script.js"></script> <script src="http://yourdomain.com/script.js"...

    一:同步加载

    我们平时使用的最多的一种方式。

    <script src="http://yourdomain.com/script.js"></script>
    <script src="http://yourdomain.com/script.js"></script>
    

    同步模式,又称阻塞模式,会阻止浏览器的后续处理,停止后续的解析,只有当当前加载完成,才能进行下一步操作。所以默认同步执行才是安全的。但这样如果js中有输出document内容、修改dom、重定向等行为,就会造成页面堵塞。所以一般建议把<script>标签放在<body>结尾处,这样尽可能减少页面阻塞。


    二:异步加载

    异步加载又叫非阻塞加载,浏览器在下载执行js的同时,还会继续进行后续页面的处理。主要有三种方式。

    方法一:也叫Script DOM Element

    (function(){
        var scriptEle = document.createElement("script");
        scriptEle.type = "text/javasctipt";
        scriptEle.async = true;
        scriptEle.src = "http://cdn.bootcss.com/jquery/3.0.0-beta1/jquery.min.js";
        var x = document.getElementsByTagName("head")[0];
        x.insertBefore(scriptEle, x.firstChild);        
     })();

    <async>属性是HTML5中新增的异步支持。此方法被称为Script DOM Element 方法。Google Analytics 和 Google+ Badge 都使用了这种异步加载代码

    (function(){;
        var ga = document.createElement('script'); 
        ga.type = 'text/javascript'; 
        ga.async = true; 
        ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; 
        var s = document.getElementsByTagName('script')[0]; 
        s.parentNode.insertBefore(ga, s); 
    })();

    但是这种加载方式执行完之前会阻止onload事件的触发,而现在很多页面的代码都在onload时还执行额外的渲染工作,所以还是会阻塞部分页面的初始化处理。

    方法二:onload时的异步加载

    (function(){
        if(window.attachEvent){
            window.attachEvent("load", asyncLoad);
        }else{
            window.addEventListener("load", asyncLoad);
        }
        var asyncLoad = function(){
            var ga = document.createElement('script'); 
            ga.type = 'text/javascript'; 
            ga.async = true; 
            ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; 
            var s = document.getElementsByTagName('script')[0]; 
            s.parentNode.insertBefore(ga, s);
        }
    )();

    这种方法只是把插入script的方法放在一个函数里面,然后放在window的onload方法里面执行,这样就解决了阻塞onload事件触发的问题。

    注:DOMContentLoaded与load的区别。前者是在document已经解析完成,页面中的dom元素可用,但是页面中的图片,视频,音频等资源未加载完,作用同jQuery中的ready事件;后者的区别在于页面所有资源全部加载完毕。

    方法三:其他方法

    由于JavaScript的动态性,还有很多异步加载方法: XHR Injection、 XHR Eval、 Script In Iframe、 Script defer属性、 document.write(script tag)。

    XHR Injection(XHR 注入):通过XMLHttpRequest来获取javascript,然后创建一个script元素插入到DOM结构中。ajax请求成功后设置script.text为请求成功后返回的responseText。

        //获取XMLHttpRequest对象,考虑兼容性。
        var getXmlHttp = function(){
            var obj;
            if (window.XMLHttpRequest)
                obj = new XMLHttpRequest();
            else
                obj = new ActiveXObject("Microsoft.XMLHTTP");
            return obj;
        };  
        //采用Http请求get方式;open()方法的第三个参数表示采用异步(true)还是同步(false)处理
        var xmlHttp = getXmlHttp();
        xmlHttp.open("GET", "http://cdn.bootcss.com/jquery/3.0.0-beta1/jquery.min.js", true);
        xmlHttp.send(); 
        xmlHttp.onreadystatechange = function(){
            if (xmlHttp.readyState == 4 && xmlHttp.status == 200){
                var script = document.createElement("script");
                script.text = xmlHttp.responseText;
                document.getElementsByTagName("head")[0].appendChild(script);
            }
        }       

    XHR Eval:与XHR Injection对responseText的执行方式不同,直接把responseText放在eval()函数里面执行。

        //获取XMLHttpRequest对象,考虑兼容性。
        var getXmlHttp = function(){
            var obj;
            if (window.XMLHttpRequest)
                obj = new XMLHttpRequest();
            else
                obj = new ActiveXObject("Microsoft.XMLHTTP");
            return obj;
        };  
        //采用Http请求get方式;open()方法的第三个参数表示采用异步(true)还是同步(false)处理
        var xmlHttp = getXmlHttp();
        xmlHttp.open("GET", "http://cdn.bootcss.com/jquery/3.0.0-beta1/jquery.min.js", true);
        xmlHttp.send(); 
        xmlHttp.onreadystatechange = function(){
            if (xmlHttp.readyState == 4 && xmlHttp.status == 200){
                eval(xmlHttp.responseText);
                //alert($);//可以弹出$,表明JS已经加载进来。click事件放在其它出会出问题,应该是还没加载进来
                $("#btn1").click(function(){
                    alert($(this).text());
                });
            }
        }       

    Script In Irame:在父窗口插入一个iframe元素,然后再iframe中执行加载JS的操作。

        var insertJS = function(){alert(2)};
        var iframe = document.createElement("iframe");
        document.body.appendChild(iframe);
        var doc = iframe.contentWindow.document;//获取iframe中的window要用contentWindow属性。
        doc.open();
        doc.write("<script>var insertJS = function(){};<\/script><body οnlοad='insertJS()'></body>");
        doc.close();

    GMail Mobile:业内JS内容被注释,所以不会执行,在需要的时候,获取script中的text内容去掉注释,调用eval()执行。

        <script type="text/javascript"> 
        /* 
        var ... 
        */ 
        </script>

    HTML5新属性:async和defer属性

    defer属性:IE4.0就出现。defer属声明脚本中将不会有document.write和dom修改。浏览器会并行下载其他有defer属性的script。而不会阻塞页面后续处理。注:所有的defer脚本必须保证按顺序执行的。

        <script type="text/javascript" defer></script>

    async属性:HTML5新属性。脚本将在下载后尽快执行,作用同defer,但是不能保证脚本按顺序执行。他们将在onload事件之前完成。

        <script type="text/javascript" defer></script>

    Firefox 3.6、Opera 10.5、IE 9和最新的Chrome和Safari都支持async属性。可以同时使用async和defer,这样IE 4之后的所有IE都支持异步加载。

    没有async属性,script将立即获取(下载)并执行,期间阻塞了浏览器的后续处理。如果有async属性,那么script将被异步下载并执行,同时浏览器继续后续的处理。

    总结: 对于支持HTML5的浏览器,实现JS的异步加载只需要在script元素中加上async属性,为了兼容老版本的IE还需加上defer属性;对于不支持HTML5的浏览器(IE可以用defer实现),可以采用以上几种方法实现。原理基本上都是向DOM中写入script或者通过eval函数执行JS代码,你可以把它放在匿名函数中执行,也可以在onload中执行,也可以通过XHR注入实现,也可以创建一个iframe元素,然后在iframe中执行插入JS代码。


    三:延迟加载

    有些JS代码在某些情况在需要使用,并不是页面初始化的时候就要用到。延迟加载就是为了解决这个问题。将JS切分成许多模块,页面初始化时只加载需要立即执行的JS,然后其它JS的加载延迟到第一次需要用到的时候再加载。类似图片的延迟加载。

    JS的加载分为两个部分:下载和执行。异步加载只是解决了下载的问题,但是代码在下载完成后就会立即执行,在执行过程中浏览器处于阻塞状态,响应不了任何需求。

    解决思路:为了解决JS延迟加载的问题,可以利用异步加载缓存起来,但不立即执行,需要的时候在执行。如何进行缓存呢?将JS内容作为Image或者Object对象加载缓存起来,所以不会立即执行,然后在第一次需要的时候在执行。

        1:模拟较长的下载时间:
        利用thread让其sleep一段时间在执行下载操作。
        2:模拟较长的JS代码执行时间
        var start = Number(new Date());
        while(start + 5000 > Number(new Date())){//执行JS}
        这段代码将使JS执行5秒才完成!

    JS延迟加载机制(LazyLoad):简单来说,就是在浏览器滚动到某个位置在触发相关的函数,实现页面元素的加载或者某些动作的执行。如何实现浏览器滚动位置的检测呢?可以通过一个定时器来实现,通过比较某一时刻页面目标节点位置和浏览器滚动条高度来判断是否需要执行函数。

            </div>
                </div>
    
    展开全文
  • 1.js中的同步加载和异步加载有什么不同? javascript语言是单线程机制。所谓单线程就是按次序执行,执行完一个任务再执行下一个。 对于浏览器来说,也就是无法在渲染页面的同时执行代码。 同步加载:也就是说一个...

    1.js中的同步加载和异步加载有什么不同?
    javascript语言是单线程机制。所谓单线程就是按次序执行,执行完一个任务再执行下一个。
    对于浏览器来说,也就是无法在渲染页面的同时执行代码。
    同步加载:也就是说一个事件处理程序没加载完之前,不会加载后面的程序。
    异步加载:也就是并发加载,会同时处理几个事件处理程序。
    举个生活中的例子:
    早上起床,先刷牙,再烧水,等水烧开了洗脸,再整理发型.是同步
    先刷牙,再烧水,再整理发型,等水壶滴的一声通知我水烧开了,我再取刚烧开的水洗脸,是异步.
    2.js是同步加载的

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
    </head>
    <body>
        <div>
            <strong></strong>
        </div>
        <p></p>
        <span></span>
    </body>
    </html>
    
    

    js在执行上述代码时:
    首先绘制DomTree:
    在这里插入图片描述
    3.JS实现异步加载的三种方式
    1.defer 异步加载,但是要等到dom文档全部解析完毕才会被执行。(可以在行间书写js代码)(只适用于IE)

    <script type="text/javascript" src="demo.js" defer="defer"></script>
    
    //行内js
    <script type="text/javascript"  defer="defer">
    console.log(“a”);
    </script>
    

    2.async 异步加载1,加载完毕就会执行,async只能加载外部js脚本,不能把js书写在script标签内(W3C标准方法)

    <script type="text/javascript" src="demo.js" async="async"></script>
    

    3.创建script,插入到DOM中,加载完毕后callback(通吃的方法)

    <body>
        <script>
        var script = document.createElement('script');
        script.type = 'text/javascript';
        script.src = '123.js';
        document.head.appendChild(script);   
        
        //123.js 文件
    //     function test(){
    //     console.log('a');
    // }
        </script>
    </body>
    

    直接调用 外部链接js文件中的test()函数;

      <script>
        var script = document.createElement('script');
        script.type = 'text/javascript';
        script.src = '123.js';
        document.head.appendChild(script);   
        
        //123.js 文件
    //     function test(){
    //     console.log('a');
    // }
        //直接调用 test();
       // test();  
        // test is not undefined  (因为js文件会有一个加载的过程)
    
        //使用定时器,1s后调用test();
        setTimeout(function(){
            test();
        },1000)  //1s后打印了a
        </script>
    

    判断js文件是否加载完毕之后进行后续操作:
    chrome,oprea,firefox,safari

     script.onload = function(){
                  test();
                 }  //script.onload 在js加载完后触发```
    
    
    

    ie

     script.onreadystatechange = function(){
                    if(script.readyState == 'complete' || script.readyState == 'loaded')
                     {
                         test();
                     }
                 }  //根据状态变化判断js是否加载完毕执行后续操作
    
    

    封装函数:

    
        <script>
        function loadscript(url,callback){
        var  script = document.createElement('script');
        script.type = "text/javascript";
        //chrome,opera,firefox,safari
        script.onload = function(){
            callback();
        }
        //IE
        script.onreadystatechange = function(){
            if(this.readyState == 'complete' || 
            this.readyState == 'loaded')
            {
                callback();
            }
        }
        script.src = url;
        document.head.appendChild(script);
    }
    loadscript('123.js',function (){
        test();
    });
    </script>
    

    因为IE会有状态判断的过程,如果程序小所消耗的时间极少,那么ie状态下函数就不会被触发,所以将加载js文件放到最后可以避免这个错误。

    展开全文
  • 异步加载图片(一)

    万次阅读 多人点赞 2014-01-03 09:18:39
    前言:本以为异步加载挺简单,因为网上代码多,但真想要做好,还真不那么简单,从看代码到弄懂再到自己写,实在是有太多的东西需要学了,用了两天的时间,终于弄出来了,因为用到回调函数,所以理解起来可能难度有点...

    前言:本以为异步加载挺简单,因为网上代码多,但真想要做好,还真不那么简单,从看代码到弄懂再到自己写,实在是有太多的东西需要学了,用了两天的时间,终于弄出来了,因为用到回调函数,所以理解起来可能难度有点大,讲起来也不太好讲,我尽力讲的明白些,其实还是要多看代码,自己摸索摸索,动手写写就什么都理解了。这篇我们只讲怎样实现异步加载,对于滑动时停止加载的事下篇再讲。

    实现效果:

    1、异步加载图片,在加载图片时,先加载一个默认的图片,然后在后台加载图片,加载完成后显示出来;

    2、当用户在滑动时,停止加载图片的线程,当停止滑动时,看哪几个ITEM在显示屏内,只加载这几个,其它线程保持阻止;(下篇再讲)

    效果图:

              刚开始加载时                          向下划动(新划出来的是空白块)           停划,加载完成

        

    一、XML

    1、main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        >
        <ListView android:id="@+id/list" 
            android:layout_width="fill_parent" 
            android:layout_height="fill_parent" />
    </LinearLayout>
    

    2、列表子项XML(book_item_adapter.xml)

    <?xml version="1.0" encoding="UTF-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="70.0dip"
        android:background="@drawable/item"
        android:drawingCacheQuality="high"
        android:minHeight="70.0dip"
        android:orientation="horizontal" >
    
        <ImageView
            android:id="@+id/sItemIcon"
            android:layout_width="42.0dip"
            android:layout_height="54.0dip"
            android:layout_margin="10.0dip"
            android:background="@drawable/rc_item_bg"
            android:padding="2.0dip"
            android:scaleType="fitXY" />
    
        <TextView
            android:text="斗破苍穹"
            android:id="@+id/sItemTitle"
            android:layout_width="fill_parent"
            android:layout_height="30.0dip"
            android:layout_alignTop="@+id/sItemIcon"
            android:layout_toRightOf="@+id/sItemIcon"
            android:gravity="center_vertical"
            android:singleLine="true"
            android:textColor="#ffffff"
            android:textSize="18.0sp" />
    </RelativeLayout>

    二、JAVA代码

    1、主页面代码(AsyncListImage.java)

    package cn.wangmeng.test;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.widget.ListView;
    
    public class AsyncListImage extends Activity {
    	private ListView list;
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            list=(ListView)findViewById(R.id.list);
            List<ImageAndText> dataArray=new ArrayList<ImageAndText>();
            for (int i = 0; i < 100; i++) {
            	 ImageAndText test=new ImageAndText("http://www.wangmeng.cn/images/logo.gif", "test");
                 ImageAndText test1=new ImageAndText("http://www.pfwx.com/files/article/image/0/54/54s.jpg", "test1");
                 ImageAndText test2=new ImageAndText("http://www.pfwx.com/files/article/image/0/4/4s.jpg","test2");
                 ImageAndText test3=new ImageAndText("http://www.pfwx.com/files/article/image/9/9760/9760s.jpg","test3");
                 ImageAndText test4=new ImageAndText("http://www.pfwx.com/files/article/image/3/3382/3382s.jpg","test4");
                 ImageAndText test5=new ImageAndText("http://www.pfwx.com/files/article/image/3/3237/3237s.jpg","test5");
                 dataArray.add(test);
                 dataArray.add(test1);
                 dataArray.add(test2);	
                 dataArray.add(test3);	
                 dataArray.add(test4);	
                 dataArray.add(test5);	
                 
    		}
           
            ImageAndTextListAdapter adapter=new ImageAndTextListAdapter(this, dataArray, list);
            list.setAdapter(adapter);
            
        }
    }

    2、ImageAndText.java

    package cn.wangmeng.test;
    
    public class ImageAndText {
    	    private String imageUrl;
    	    private String text;
    
    	    public ImageAndText(String imageUrl, String text) {
    	        this.imageUrl = imageUrl;
    	        this.text = text;
    	    }
    	    public String getImageUrl() {
    	        return imageUrl;
    	    }
    	    public String getText() {
    	        return text;
    	    }
    }
    
    上面两个代码一块讲
    1、ImageAndText类是用来存储要与XML绑定的图片地址和名字地址的。

    2、将所有的地址都放在一个List里面(dataArray),然后将其传入ImageAndTextListAdapter()函数中;可见这个ImageAndTextListAdapter()函数是根据传进去的dataArray生成对应的Adapter的

    3、然后将ImageAndTextListAdapter()返回的Adapter与listView绑定

    3、ImageAndTextListAdapter.java

    这是重写于baseAdapter的类,由于重写于baseAdapter,所以有几个必须重写的函数,getCount()、getItem()、getItemId()、getView(),我们先把总体代码写出来,只讲一个getView()函数,其实函数就不讲了,先着重说下getView()函数在什么时候被系统调用:

    getView()函数在什么时候被系统调用:

    注意一点是android系统在显示列表时,并不是把所有代表都显示出来,让你随便划,划到哪是哪;而是根据当前的在划到的ITEM,调用当前ITEM的getView()来显示它。

    全部代码:

    package cn.wangmeng.test;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import cn.wangmeng.test.AsyncImageLoader.ImageCallback;
    
    import android.app.Activity;
    import android.graphics.drawable.Drawable;
    import android.util.Log;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ArrayAdapter;
    import android.widget.BaseAdapter;
    import android.widget.ImageView;
    import android.widget.ListView;
    import android.widget.TextView;
    
    public class ImageAndTextListAdapter extends BaseAdapter {
    
    		private LayoutInflater inflater;
    	    private ListView listView;
    	    private AsyncImageLoader asyncImageLoader;
    
    	    private List<ImageAndText> dataArray=new ArrayList<ImageAndText>();
    
    	    public ImageAndTextListAdapter(Activity activity, List<ImageAndText> imageAndTexts, ListView listView) {
    
    	        this.listView = listView;
    	        asyncImageLoader = new AsyncImageLoader();
    	        inflater = activity.getLayoutInflater();
    	        dataArray=imageAndTexts;
    	    }
    	    
    		@Override
    		public int getCount() {
    			// TODO Auto-generated method stub
    			return dataArray.size();
    		}
    		@Override
    		public Object getItem(int position) {
    			// TODO Auto-generated method stub
    			if(position >= getCount()){
    				return null;
    			}
    			return dataArray.get(position);
    		}
    		@Override
    		public long getItemId(int position) {
    			// TODO Auto-generated method stub
    			return position;
    		}
    
    	    //不需要ViewHolder版,直接将ImageAndText与XML资源关联起来
    	    public View getView(int position, View convertView, ViewGroup parent) {
    	    	if (convertView == null) {
    	        	 convertView = inflater.inflate(R.layout.book_item_adapter, null);
    	        }
    	        convertView.setTag(position);
    	        
    	        ImageAndText imageAndText = (ImageAndText) getItem(position);
    	        String imageUrl = imageAndText.getImageUrl();
    	        
    	        TextView textView =  (TextView) convertView.findViewById(R.id.sItemTitle); 
    	        // 将XML视图项与用户输入的URL和文本在绑定
    	        textView.setText(imageAndText.getText());//加载TEXT
    	        ImageView iv = (ImageView) convertView.findViewById(R.id.sItemIcon);
    	        iv.setBackgroundResource(R.drawable.rc_item_bg);//在初始化时,先把背景图片设置成默认背景,
    	        							//否则在下拉时会随机匹配背景,不美观
    	
    	        asyncImageLoader.loadDrawable(position,imageUrl, new ImageCallback() {
    	        	@Override
    	    		public void onImageLoad(Integer pos, Drawable drawable) {
    	    			View view = listView.findViewWithTag(pos);
    	    			if(view != null){
    	    				ImageView iv = (ImageView) view.findViewById(R.id.sItemIcon);
    	    				iv.setBackgroundDrawable(drawable);
    	    			}
    	    		}
    	        	//加载不成功的图片处理	
    				@Override
    				public void onError(Integer pos) {
    					View view = listView.findViewWithTag(pos);
    					if(view != null){
    						ImageView iv = (ImageView) view.findViewById(R.id.sItemIcon);
    						iv.setBackgroundResource(R.drawable.rc_item_bg);
    					}
    				}
    	        	
    	        });
    	        return convertView;
    	    }
    }
    
    我们着重看getView()函数
    1、看这段:

    if (convertView == null) {
    	 convertView = inflater.inflate(R.layout.book_item_adapter, null);
    }
    convertView.setTag(position);
    
    ImageAndText imageAndText = (ImageAndText) getItem(position);
    String imageUrl = imageAndText.getImageUrl();
    
    TextView textView =  (TextView) convertView.findViewById(R.id.sItemTitle); 
    // 将XML视图项与用户输入的URL和文本在绑定
    textView.setText(imageAndText.getText());//加载TEXT
    ImageView iv = (ImageView) convertView.findViewById(R.id.sItemIcon);
    iv.setBackgroundResource(R.drawable.rc_item_bg);
    这段代码没什么特别的就是将前面dataArray的信息与XML的元素项对应起来,并绑定,最关键的是下面这段,下面这个方法才是实现异步加载图片的关键:
    asyncImageLoader.loadDrawable(position,imageUrl, new ImageCallback() {
    	@Override
    	public void onImageLoad(Integer pos, Drawable drawable) {
    		View view = listView.findViewWithTag(pos);
    		if(view != null){
    			ImageView iv = (ImageView) view.findViewById(R.id.sItemIcon);
    			iv.setBackgroundDrawable(drawable);
    		}
    	}
    	//加载不成功的图片处理	
    	@Override
    	public void onError(Integer pos) {
    		View view = listView.findViewWithTag(pos);
    		if(view != null){
    			ImageView iv = (ImageView) view.findViewById(R.id.sItemIcon);
    			iv.setBackgroundResource(R.drawable.rc_item_bg);
    		}
    	}
    	
    });
    这段代码的奇特之处在于,利用AsyncImageLoader类的实例(asyncImageLoader),调用方法loadDrawable()方法,就实现了加载后图像的绑定;好神奇,仔细看他是怎么做到的。这里先注意的有两点:
    (1)、传进去的参数,当前项的位置(position),当前图片的URL(imageUrl),一个名称为ImageCallback()接口函数;

    (2)、ImageCallback()接口函数里的两个被重写的函数onImageLoad()和onError()

    3、AsyncImageLoader.java

    从上面的讲解也应该能猜到这个类,主要的功能就是加载图片,然后成功后更新UI;

    先看全部代码,然后再逐步讲

    package cn.wangmeng.test;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.lang.ref.SoftReference;
    import java.net.URL;
    import java.util.HashMap;
    
    import android.graphics.drawable.Drawable;
    import android.os.Handler;
    
    public class AsyncImageLoader {
    	final Handler handler = new Handler();
    	private HashMap<String, SoftReference<Drawable>> imageCache;
    	public AsyncImageLoader() {
    		imageCache = new HashMap<String, SoftReference<Drawable>>();//图片缓存
    	}
    	
    	// 回调函数
    	public interface ImageCallback {
    		public void onImageLoad(Integer t, Drawable drawable);
    		public void onError(Integer t);
    	}
    
    	public Drawable loadDrawable(final Integer pos, final String imageUrl,
    			 final ImageCallback imageCallback) {
    		new Thread() {
    			@Override
    			public void run() {
    				
    				LoadImg(pos, imageUrl, imageCallback);
    
    			}
    		}.start();
    		return null;
    	}// loadDrawable---end
    
    	public void LoadImg(final Integer pos, final String imageUrl,
    			final ImageCallback imageCallback) {
    		// 首先判断是否在缓存中
    		// 但有个问题是:ImageCache可能会越来越大,以至用户内存用光,所以要用SoftReference(弱引用)来实现
    		if (imageCache.containsKey(imageUrl)) {
    			SoftReference<Drawable> softReference = imageCache.get(imageUrl);
    			final Drawable drawable = softReference.get();
    			if (drawable != null) {
    				handler.post(new Runnable() {
    					@Override
    					public void run() {
    						imageCallback.onImageLoad(pos, drawable);
    					}
    				});
    				return;
    			}
    		}
    		// 尝试从URL中加载
    		try {
    			final Drawable drawable = loadImageFromUrl(imageUrl);
    			if (drawable != null) {
    				imageCache.put(imageUrl, new SoftReference<Drawable>(drawable));
    			}
    			handler.post(new Runnable() {
    				@Override
    				public void run() {
    						imageCallback.onImageLoad(pos, drawable);
    				}
    			});
    		} catch (IOException e) {
    			handler.post(new Runnable() {
    				@Override
    				public void run() {
    					imageCallback.onError(pos);
    				}
    			});
    			e.printStackTrace();
    		}
    
    	}
    
    	// 根据URL加载图片,如果出现错误throws IOException式的错误,以便在LoadImg中捕获,执行OnError()函数
    	public static Drawable loadImageFromUrl(String url) throws IOException {
    		URL m;
    		InputStream i = null;
    		m = new URL(url);
    		i = (InputStream) m.getContent();
    		Drawable d = Drawable.createFromStream(i, "src");
    		return d;
    	}
    
    }
    
    分别讲解
    1、先看这段代码

    	// 回调函数
    	public interface ImageCallback {
    		public void onImageLoad(Integer t, Drawable drawable);
    		public void onError(Integer t);
    	}
    
    	public Drawable loadDrawable(final Integer pos, final String imageUrl,
    			 final ImageCallback imageCallback) {
    		new Thread() {
    			@Override
    			public void run() {
    				
    				LoadImg(pos, imageUrl, imageCallback);
    
    			}
    		}.start();
    		return null;
    	}// loadDrawable---end
    (1)首先注意,刚才我们调用的loadDrawable()函数,里面初始化并运行了一个线程,而这个线程的里面只有一个函数LoadImg(),对于这个函数下面我们具体讲,它的主要功能就是加载图片,然后更新UI
    (2)上面也看出了ImageCallback是一个接口,而里面的两个函数onImageLoad()和onError()在这里是没有具体实现的,那在哪里实现呢,当然是我们上面的ImageAndTextListAdapter.java里面了,等下我们具体会再讲。

    再往下看

    	// 根据URL加载图片,如果出现错误throws IOException式的错误,以便在LoadImg中捕获,执行OnError()函数
    		public static Drawable loadImageFromUrl(String url) throws IOException {
    			URL m;
    			InputStream i = null;
    			m = new URL(url);
    			i = (InputStream) m.getContent();
    			Drawable d = Drawable.createFromStream(i, "src");
    			return d;
    		}
    		
    	public void LoadImg(final Integer pos, final String imageUrl,
    			final ImageCallback imageCallback) {
    		// 首先判断是否在缓存中
    		// 但有个问题是:ImageCache可能会越来越大,以至用户内存用光,所以要用SoftReference(弱引用)来实现
    		if (imageCache.containsKey(imageUrl)) {
    			SoftReference<Drawable> softReference = imageCache.get(imageUrl);
    			final Drawable drawable = softReference.get();
    			if (drawable != null) {
    				handler.post(new Runnable() {
    					@Override
    					public void run() {
    						imageCallback.onImageLoad(pos, drawable);
    					}
    				});
    				return;
    			}
    		}
    		// 尝试从URL中加载
    		try {
    			final Drawable drawable = loadImageFromUrl(imageUrl);
    			if (drawable != null) {
    				imageCache.put(imageUrl, new SoftReference<Drawable>(drawable));
    			}
    			handler.post(new Runnable() {
    				@Override
    				public void run() {
    						imageCallback.onImageLoad(pos, drawable);
    				}
    			});
    		} catch (IOException e) {
    			handler.post(new Runnable() {
    				@Override
    				public void run() {
    					imageCallback.onError(pos);
    				}
    			});
    			e.printStackTrace();
    		}
    
    	}
    
    (1)、loadImageFromUrl()函数,就是根据URL到网上加载图片,然后返回图片流Drawable类型变量
    (2)、对于LoadImg()我们再拆一下,先看如何在缓存中加载

    		if (imageCache.containsKey(imageUrl)) {
    			SoftReference<Drawable> softReference = imageCache.get(imageUrl);
    			final Drawable drawable = softReference.get();
    			if (drawable != null) {
    				handler.post(new Runnable() {
    					@Override
    					public void run() {
    						imageCallback.onImageLoad(pos, drawable);
    					}
    				});
    				return;
    			}
    		}
    注意:

    1、在这里就已经得到了图像

    			SoftReference<Drawable> softReference = imageCache.get(imageUrl);
    			final Drawable drawable = softReference.get();
    2、得到图像之后就到了这段代码:

    			if (drawable != null) {
    				handler.post(new Runnable() {
    					@Override
    					public void run() {
    						imageCallback.onImageLoad(pos, drawable);
    					}
    				});
    				return;
    			}
    当我们得到图像之后,调用imageCallback.onImageLoad(pos, drawable);来更新UI,由于我们再回来看看ImageAndTextListAdapter.java中的代码

    asyncImageLoader.loadDrawable(position,imageUrl, new ImageCallback() {
    	@Override
    	public void onImageLoad(Integer pos, Drawable drawable) {
    		View view = listView.findViewWithTag(pos);
    		if(view != null){
    			ImageView iv = (ImageView) view.findViewById(R.id.sItemIcon);
    			iv.setBackgroundDrawable(drawable);
    		}
    	}
    	
    });
    看到了吧,就是把得到的drawable与加载到UI中!!!!这就实现了回调

    OK,就到这吧,OnError()的原理一样,只不过是对程序没有加载到图片时应该怎么处理,其实就是当没有加载到图片时就是默认图片代替。

    下面给出源码:http://download.csdn.net/detail/harvic880925/6802241(不要分,仅供分享)


    请大家尊重作者板权,转载请标明出处:http://blog.csdn.net/harvic880925/article/details/17766027 ,谢谢!

    展开全文
  • 异步加载js

    2019-06-20 12:46:28
    异步加载js的实现,有三种方法: defer:规定是否对脚本执行进行延迟,但却是并行下载,要等到DOM文档全部加载解析好了,才会被执行。只有IE能用,也可以将代码写到内部,如下: <script type="text/javascript...

    异步加载js的实现,有三种方法:

    • defer:规定是否对脚本执行进行延迟,但却是并行下载,要等到DOM文档全部加载解析好了,才会被执行。只有IE能用,也可以将代码写到内部,如下:
    <script type="text/javascript" src="demo.js" defer="defer"></script>
    
    • async:异步加载,加载好了就执行,不管页面是否解析好。async只能加载外部脚本,不能把js写在script标签里(IE9以上都能执行,比较普遍)。如下:
     <script type="text/javascript" src="demo.js" async="async"></script>
    
    • 创建script,插入到DOM中,加载完成后callBack(这种形式的异步加载除了IE浏览器无法执行,其他都是可以的)。,如下:
    function loadScript(url, callback){
    var script = document.createElement_x("script")
    script.type = "text/javascript";
    if (script.readyState){ //IE
    script.onreadystatechange = function(){
    if (script.readyState == "loaded" ||
    script.readyState == "complete"){
    script.onreadystatechange = null;
    callback();
    }
    };
    } else { //Others: Firefox, Safari, Chrome, and Opera
    script.onload = function(){
    callback();
    };
    }
    script.src = url;
    document.body.appendChild(script);
    }
    
    展开全文
  • 如何实现图片的异步加载

    千次阅读 2018-03-06 15:46:15
    异步加载:也称为图片的预加载。利用js代码提前加载图片,用户需要时可以直接从本地缓存获取,但是会增加服务器前端的压力。这样做可以提高用户的体验,因为同步加载大图片的时候,图片会一层一层的显示处理,但是...
  • js的异步加载

    千次阅读 2018-09-05 21:24:31
    今天被问到了如何异步加载js,听到这句话我内心是拒绝的,啥玩意儿?js也要用异步加载不是引入了就行了,也没见速度变慢啊。后来仔细查询了一下,才发现自己原来还是太年轻了。  因为之前自己写的加载的都是本地js...
  • 同步加载与异步加载

    万次阅读 2016-12-09 11:48:05
    有几天沒有更新博客了,主要是这几天项目遇到好多小问题,比如异步加载、输入特使字符、事件的执行顺序、还有最让人头疼的浏览器缓存问题。所以这几天一直在加班加点的调试、更改准备这个月的投产,终于昨天提交了...
  • vue 组件异步加载(按需加载)

    万次阅读 2018-11-05 20:42:27
    有时候打包出来的js文件过大,严重影响访问速度,这个时候我们就不得不...下面就主要说以下vue组件异步加载的方法:(测试所用的webpack:^4.12.0) 1.使用() =&gt; import() 代码: 打包: 界面效果: 2.使...
  • 改造bootstrapTreeTable插件实现异步加载

    万次阅读 热门讨论 2018-03-09 14:41:14
    在这个插件的官方地址上也说明了不支持异步加载,如果要异步加载则使用其他的插件。我就在他原有的插件基础上做了一下改造。去掉了一些本项目中不会使用到的特性。原有插件叫:jquery.treegrid.extension.js修改后的...
  • 如果资源本身加载比较耗时,采用同步方法会产生卡顿现象,对此的解决方法通常采用多线程或者使用引擎本身自带的异步加载方法。在Unity开发中,由于一些方法(如Resources.Load)本身不支持在其它线程调用,因此多...
  • Echarts使用心得总结——异步数据加载

    万次阅读 热门讨论 2019-03-19 12:24:28
    异步加载Echarts的数据一般是在初始化后setOption中直接填入的,但是很多时候可能数据需要异步加载后再填入。ECharts 中实现异步数据的更新非常简单,在图表初始化后不管任何时候只要使用ajax等异步获取数据后通过 ...
  • JS实现图片的异步加载

    万次阅读 2016-10-21 18:00:34
    1.概述异步加载:也称为图片的预加载。利用js代码提前加载图片,用户需要时可以直接从本地缓存获取,但是会增加服务器前端的压力。这样做可以提高用户的体验,因为同步加载大图片的时候,图片会一层一层的显示处理,...
  • 关于异步加载,很多人都是卡住,ran
  • react异步加载组件,分模块加载,提高打开性能 react异步加载的方法很多,这里只说一种,因为这一种直接使用react的特性就可以了,不需要另外配置webpack,就是用一个小技巧去import组件,所以方便,实现简单。 写一...
  • echarts异步数据加载和更新

    万次阅读 2016-07-28 17:03:16
    echarts中的数据是在初始化后setOption中直接填入的,但是很多时候可能数据需要异步加载后再填入。ECharts 中实现异步数据的更新非常简单,在图表初始化后不管任何时候只要通过 jQuery 等工具异步获取数据后通过 ...
  • unity 同步和异步加载

    千次阅读 2019-06-16 22:46:06
    这个方法对于场景小,资源少的情况可以,要是遇到资源大的场景,就会卡,这种情况就要用到异步加载异步加载 Application.LoadLevelAsync("关卡名或者加载场景的序号") 一般会有 进度条 异步 优点:速度快,与...
  • CSS 样式异步加载

    千次阅读 2016-06-23 08:39:13
    触发异步样式下载的诀窍是使用一个 元素,并 为media 属性设置一个不可用的值 (我用的是 media=”none”, 不过其它的任何值也是可以的)。当一个媒体查询的结果值计算出来是 false 的时候,浏览器仍然会下载样式表,...
  • 如何在thymeleaf中ajax实现模版动态渲染 ajax请求到数据后重新渲染页面
  • Jquery 异步加载页面 简单示例

    千次阅读 多人点赞 2013-09-20 13:45:45
    Jquery异步加载页面HTML部分:页面中放一个DIV,用于异步加载一个页面: 添加一个按钮,用于触发异步加载的事件: Js部分: $("#btnLoad").click(function(){$("#asyncLoadPage").load("AsynPage.aspx");...
  • zTree 异步加载数据传参问题

    千次阅读 2017-07-04 18:45:39
    如下图 在otherParam里需要这样写才能动态传。 这样写 或者这样写 都是无效的。
1 2 3 4 5 ... 20
收藏数 285,473
精华内容 114,189
关键字:

异步加载