android异步任务 访问网络 加载图片 解决方案大集合


1. Handler + Thread 异步执行任务

  • 在UI线程中开启子线程,使用Handler 发消息,通知主线程更新UI

参考链接: http://my.oschina.net/keeponmoving/blog/61129

  • 直接在UI线程中开启子线程来更新TextView显示的内容,运行程序我们会发现,如下错误:android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.翻译过来就是:只有创建这个控件的线程才能去更新该控件的内容。
    所有的UI线程要去负责View的创建并且维护它,例如更新冒个TextView的显示,都必须在主线程中去做,我们不能直接在UI线程中去创建子线程,要利用消息机制:handler,如下就是handler的简单工作原理图:
public class HandlerTestActivity extends Activity {
    private TextView tv;
    private static final int UPDATE = 0;
    private Handler handler = new Handler() {

        @Override
        public void handleMessage(Message msg) {
            // TODO 接收消息并且去更新UI线程上的控件内容
            if (msg.what == UPDATE) {
                // Bundle b = msg.getData();
                // tv.setText(b.getString("num"));
                tv.setText(String.valueOf(msg.obj));
            }
            super.handleMessage(msg);
        }
    };

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        tv = (TextView) findViewById(R.id.tv);

        new Thread() {
            @Override
            public void run() {
                // TODO 子线程中通过handler发送消息给handler接收,由handler去更新TextView的值
                try {
                    for (int i = 0; i < 100; i++) {
                        Thread.sleep(500);
                        Message msg = new Message();
                        msg.what = UPDATE;
                        // Bundle b = new Bundle();
                        // b.putString("num", "更新后的值:" + i);
                        // msg.setData(b);
                        msg.obj = "更新后的值:" + i;
                        handler.sendMessage(msg);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }

}
-------------请求网络数据-----------------------------------
 new Thread() {
                    @Override
                    public void run() {
                        // 使用 okHttp 请求网络       
                        OkHttpClient okHttpClient = new OkHttpClient();
                        Request request = new Request.Builder().url(SERVERURL).build();
                        try {
                            Response response = okHttpClient.newCall(request).execute();
                            String result = response.body().string();
                            Message msg = new Message();
                            msg.what = 0;
                            Bundle bundle = new Bundle();
                            bundle.putString("result", result);
                            msg.setData(bundle);
                            handler.sendMessage(msg);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }.start();

2. AsyncTask抽象类 (一个异步任务框架)

  • 更轻量级一些,适用于简单的异步处理,不需要借助线程和Handler即可。
  • android提供了一套专门用于异步处理的类。即:AynsTask类。使用这个类可以为耗时程序开辟一个新线程进行处理,处理完时返回。
    其实,AsynTask类就是对Thread类的一个封装,并且加入了一些新的方法。编程时,两者都可以实现同样的功能。本文后面将对AsynTask和Thread进行比较

    AsyncTask抽象类

AsyncTask

//在主线程调用该方法
    private void useAsyncTask() {
        /*主线程调用AsynTask子类实例的execute()方法后,首先会调用onPreExecute()方法。
        onPreExecute()在主线程中运行,可以用来写一些开始提示代码。*/
        DownLoader downLoader = new DownLoader(textView);
/*execute()向doInBackground()传递。*/
        downLoader.execute(SERVERURL);

    }
                //Params:启动任务执行的输入参数的类型。 

                //Progress:后台任务完成进度值的类型。 

                //Result:后台执行任务完成后返回结果的类型
    class DownLoader extends AsyncTask<String, Integer, String> {
        TextView text;

        public DownLoader(TextView text) {
            this.text = text;
        }

        /*处理完毕之后异步线程结束,在主线程中调用onPostExecute()方法。onPostExecute()可以进行一些结束提示处理*/
        @Override
        protected String doInBackground(String... params) {

            String url = params[0];
            String result = null;
            OkHttpClient okHttpClient = new OkHttpClient();
            Request request = new Request.Builder().url(url).build();
            Response response = null;
            try {
                response = okHttpClient.newCall(request).execute();
                result = response.body().string();
            } catch (IOException e) {
                e.printStackTrace();
            }
            /*//publishProgress()为AsyncTask类中的方法
            //常在doInBackground()中调用此方法
            //用于通知主线程,后台任务的执行情况.
            //此时会触发AsyncTask中的onProgressUpdate()方法*/

/* doInBackground()的返回值会传递给onPostExecute()。*/
            return result;
        }

        @Override
        protected void onCancelled(String s) {
            super.onCancelled(s);
        }

        /*onProgressUpdate()方法用于更新异步执行中,在主线程中处理异步任务的执行信息  参数为publishProgress() 方法的参数*/
        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
        }

        /*处理完毕之后异步线程结束,在主线程中调用onPostExecute()方法。onPostExecute()可以进行一些结束提示处理*/
        @Override
        protected void onPostExecute(String s) {
//            super.onPostExecute(s);

            text.setText(s);

        }

        /*之后启动新线程,调用doInBackground()方法,进行异步数据处理。*/
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            System.out.println("开始执行异步任务.....");
        }

        /*onCancelled()方法用于异步任务被取消时,在主线程中执行相关的操作*/
        @Override
        protected void onCancelled() {
            super.onCancelled();
        }
    }

参考链接 ; http://blog.csdn.net/guolin_blog/article/details/9526203

网络加载框架

Volley

Volley 是 Google 推出的 Android 异步网络请求框架和图片加载框

参考链接: http://blog.csdn.net/guolin_blog/article/details/17482095/
* 它的设计目标就是非常适合去进行数据量不大,但通信频繁的网络操作,而对于大数据量的网络操作,比如说下载文件等,Volley的表现就会非常糟糕。

volley 在android studio中如何使用

这里写图片描述

  • StringRequest的用法
 private void uesVolley() {
    /*1. 创建一个RequestQueue对象。
    2. 创建一个StringRequest对象。
    3. 将StringRequest对象添加到RequestQueue里面。
    */
        /**
         * 注意这里拿到的RequestQueue是一个请求队列对象,它可以缓存所有的HTTP请求,
         * 然后按照一定的算法并发地发出这些请求。RequestQueue内部的设计就是非常合适高并发的,
         * 因此我们不必为每一次HTTP请求都创建一个RequestQueue对象,这是非常浪费资源的,
         * 基本上在每一个需要和网络交互的Activity中创建一个RequestQueue对象就足够了。
         */
        RequestQueue mQueue = Volley.newRequestQueue(MainActivity.this);

/**
 * 这里new出了一个StringRequest对象,StringRequest的构造函数需要传入三个参数,
 * 第一个参数就是目标服务器的URL地址
 * 第二个参数是服务器响应成功的回调,
 * 第三个参数是服务器响应失败的回调
 */
        StringRequest stringRequest = new StringRequest("http://www.baidu.com", new com.android.volley.Response.Listener<String>() {
            @Override
            public void onResponse(String response) {
                textView.setText(response);
                Log.d("TAG", response);

            }
        }, new com.android.volley.Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {

            }
        });
      //最后,将这个StringRequest对象添加到RequestQueue里面就可以了
        mQueue.add(stringRequest);
/**
 * TTP的请求类型通常有两种,GET和POST,刚才我们使用的明显是一个GET请求,那么如果想要发出一条POST请求应该怎么做呢?
 * StringRequest中还提供了另外一种四个参数的构造函数,其中第一个参数就是指定请求类型的
 */
        StringRequest stringRequestPost = new StringRequest(com.android.volley.Request.Method.POST, SERVERURL,
                successListener, errorLiatener) {
            @Override
            protected Map<String, String> getParams() throws AuthFailureError {

                HashMap<String, String> map = new HashMap<>();
                map.put("useName", "admin");
                map.put("password", "123456");

                return map;
            }
        };
        mQueue.add(stringRequestPost);


    }
  • JsonRequest的用法
    学完了最基本的StringRequest的用法,我们再来进阶学习一下JsonRequest的用法。类似于StringRequest,JsonRequest也是继承自Request类的,不过由于JsonRequest是一个抽象类,因此我们无法直接创建它的实例,那么只能从它的子类入手了。JsonRequest有两个直接的子类,JsonObjectRequest和JsonArrayRequest,从名字上你应该能就看出它们的区别了吧?一个是用于请求一段JSON数据的,一个是用于请求一段JSON数组的。
    至于它们的用法也基本上没有什么特殊之处,先new出一个JsonObjectRequest对象
  /*  JsonRequest的用法*/
        JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(SERVERURL, null,
                new com.android.volley.Response.Listener<JSONObject>() {
            @Override
            public void onResponse(JSONObject response) {
                textView.setText(response.toString());
                Log.e("JsonObject",response.toString());

            }
        }, new com.android.volley.Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {

            }
        });
        mQueue.add(jsonObjectRequest);
  • ImageRequest的用法

参考链接: http://blog.csdn.net/guolin_blog/article/details/17482165

 private void loadImage() {

        RequestQueue mQueue = Volley.newRequestQueue(MainActivity.this);
       ImageRequest imageRequest =  new ImageRequest("https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo/logo_white_fe6da1ec.png",
                new com.android.volley.Response.Listener<Bitmap>() {
                    @Override
                    public void onResponse(Bitmap response) {
                        image.setImageBitmap(response);
                    }
                },
                0, 0, Bitmap.Config.RGB_565,
                new com.android.volley.Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {

                    }
                }

        );
        mQueue.add(imageRequest);


    }

可以看到,ImageRequest的构造函数接收六个参数,第一个参数就是图片的URL地址,这个没什么需要解释的。第二个参数是图片请求成功的回调,这里我们把返回的Bitmap参数设置到ImageView中。第三第四个参数分别用于指定允许图片最大的宽度和高度,如果指定的网络图片的宽度或高度大于这里的最大值,则会对图片进行压缩,指定成0的话就表示不管图片有多大,都不会进行压缩。第五个参数用于指定图片的颜色属性,Bitmap.Config下的几个常量都可以在这里使用,其中ARGB_8888可以展示最好的颜色属性,每个图片像素占据4个字节的大小,而RGB_565则表示每个图片像素占据2个字节大小。第六个参数是图片请求失败的回调,这里我们当请求失败时在ImageView中显示一张默认图片。
最后将这个ImageRequest对象添加到RequestQueue里就可以了

  • ImageLoader的用法

ImageLoader也可以用于加载网络上的图片,并且它的内部也是使用ImageRequest来实现的,不过ImageLoader明显要比ImageRequest更加高效,因为它不仅可以帮我们对图片进行缓存,还可以过滤掉重复的链接,避免重复发送请求。
由于ImageLoader已经不是继承自Request的了,所以它的用法也和我们之前学到的内容有所不同,总结起来大致可以分为以下四步:

  1. 创建一个RequestQueue对象。

  2. 创建一个ImageLoader对象。

  3. 获取一个ImageListener对象。

  4. 调用ImageLoader的get()方法加载网络上的图片。

  private void loadImage() {


/*,ImageLoader的构造函数接收两个参数,第一个参数就是RequestQueue对象,第二个参数是一个ImageCache对象*/
        ImageLoader imageLoader = new ImageLoader(mQueue, new ImageLoader.ImageCache() {
            @Override
            public Bitmap getBitmap(String url) {
                return null;
            }

            @Override
            public void putBitmap(String url, Bitmap bitmap) {

            }
        });
        /*我们通过调用ImageLoader的getImageListener()方法能够获取到一个ImageListener对象,
        getImageListener()方法接收三个参数,
        第一个参数指定用于显示图片的ImageView控件,
        第二个参数指定加载图片的过程中显示的图片,
        第三个参数指定加载图片失败的情况下显示的图片*/
        ImageLoader.ImageListener imageListener = ImageLoader.getImageListener(image,
                R.mipmap.ic_launcher,
                R.mipmap.ic_download);
/*get()方法接收两个参数,第一个参数就是图片的URL地址,第二个参数则是刚刚获取到的ImageListener对象。
当然,如果你想对图片的大小进行限制,也可以使用get()方法的重载,指定图片允许的最大宽度和高度*/
        imageLoader.get(imageUrl,imageListener,200,200);
    }
  • NetworkImageView

除了以上两种方式之外,Volley还提供了第三种方式来加载网络图片,即使用NetworkImageView。不同于以上两种方式,NetworkImageView是一个自定义控制,它是继承自ImageView的,具备ImageView控件的所有功能,并且在原生的基础之上加入了加载网络图片的功能。NetworkImageView控件的用法要比前两种方式更加简单,大致可以分为以下五步:
1. 创建一个RequestQueue对象。
2. 创建一个ImageLoader对象。
3. 在布局文件中添加一个NetworkImageView控件。
4. 在代码中获取该控件的实例。
5. 设置要加载的图片地址。

xml文件

 <com.android.volley.toolbox.NetworkImageView
        android:id="@+id/iv_netWorkImage"
        android:layout_width="200dp"
        android:layout_height="200dp" />

java代码

private void useNetworkImageView() {

        RequestQueue mQueue = Volley.newRequestQueue(MainActivity.this);
        /*,ImageLoader的构造函数接收两个参数,第一个参数就是RequestQueue对象,第二个参数是一个ImageCache对象*/
        ImageLoader imageLoader = new ImageLoader(mQueue, new ImageLoader.ImageCache() {
            @Override
            public Bitmap getBitmap(String url) {
                return null;
            }

            @Override
            public void putBitmap(String url, Bitmap bitmap) {

            }
        });
        ivNetWorkImage.setDefaultImageResId(R.mipmap.ic_download);
        ivNetWorkImage.setErrorImageResId(R.mipmap.ic_launcher);
        ivNetWorkImage.setImageUrl(imageUrl, imageLoader);

    }

LruCache

android Studio 使用 butterknife 注解功能

  • 需要添加下面一行依赖
       compile 'com.jakewharton:butterknife:7.0.1'

Picasso 图片缓存框架

  • 使用:
    依赖中搜索 Picasso ,点击添加
  • picasso是Square公司开源的一个Android图形缓存库,地址http://square.github.io/picasso/

    可以实现图片下载和缓存功能。仅仅只需要一行代码就能完全实现图片的异步加载

参考链接: http://bbs.itcast.cn/thread-87019-1-1.html

参考链接: http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/0731/1639.html

  • 简单用例—从网络加载:
  /**
         * 图片下载的步骤:
         * 1、使用异步任务或者 handler+thread 获取图片资源
         * 2、使用bitmapFactory 对图片进行解码
         * 3、显示图片
         */
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Picasso
                        .with(MainActivity.this)
                        .load(imageUrl)//有多个重载方法
                        .placeholder(R.mipmap.ic_launcher)//,默认显示图片
                        .error(R.mipmap.ic_launcher)//加载错误时显示的图片
                        .resize(80,80)//转换图片以适应布局大小并减少内存占用
                        .centerCrop()
//                        .transform(new CustomeCropAquareTransFormation()) //自定义转换
                        .into(imageView);//显示到指定控件上
            }
        });

//自定义裁剪,将 CustomeCropSquareTransformation 的对象传递给transform 方法即可

 public class CustomeCropAquareTransFormation implements Transformation{

        @Override
        public Bitmap transform(Bitmap bitmap) {
            int size = Math.min(bitmap.getWidth(),bitmap.getHeight());//得到 Width 和 Height 的最小值
          //判断以高度进行缩减还是以高度进行缩减
            int x= (bitmap.getWidth()-size)/2;
            int y = (bitmap.getHeight()-size)/2;
            Bitmap resultBitmap = Bitmap.createBitmap(bitmap, x, y, 80, 80);//从原始位图剪切图像
            if(resultBitmap!=bitmap){
                bitmap.recycle();//回收Bitmap资源
            }
            return resultBitmap;
        }

        @Override
        public String key() {
            return "square";
        }
    }

load() 有多个重载方法 也可以从 从Android Resources 中加载 , 从本地File文件中加载 , 从URI地址中加载

  • Picasso不仅实现了图片异步加载的功能,还解决了android中加载图片时需要解决的一些常见问题:

       1.在adapter中需要取消已经不在视野范围的ImageView图片资源的加载,否则会导致图片错位,Picasso已经解决了这个问题。
    
       2.使用复杂的图片压缩转换来尽可能的减少内存消耗
    
       3.自带内存和硬盘二级缓存功能
    

public static Bitmap createBitmap (Bitmap source, int x, int y, int width, int height, Matrix m, boolean filter)

从原始位图剪切图像,这是一种高级的方式。可以用Matrix(矩阵)来实现旋转等高级方式截图
参数说明:

          Bitmap source:要从中截图的原始位图

          int x:起始x坐标

          int y:起始y坐标

            int width:要截的图的宽度

            int height:要截的图的宽

           返回值:返回一个剪切好的Bitmap

Universal ImageLoader

github: https://github.com/nostra13/Android-Universal-Image-Loader

参考链接1: http://blog.csdn.net/vipzjyno1/article/details/23206387

参考链接2: http://blog.csdn.net/wwj_748/article/details/10079311/

参考链接:Android-Universal-Image-Loader三大组件DisplayImageOptions、ImageLoader、ImageLoaderConfiguration详解

UIL是是一个开源项目,其目的就是提供一个可重复使用的仪器为异步图像加载、缓存和显示。它的使用很简单:

尽管Picasso拥有更好的API,但其缺乏自定义。而使用UIL构建器几乎可以配置所有(其中最重要的就是在抓取和缓存大型图片时,Picasso会失败)。

简单描述一下这个项目的结构:每一个图片的加载和显示任务都运行在独立的线程中,除非这个图片缓存在内存中,这种情况下图片会立即显示。如果需要的图片缓存在本地,他们会开启一个独立的线程队列。如果在缓存中没有正确的图片,任务线程会从线程池中获取,因此,快速显示缓存图片时不会有明显的障碍。(别人那边借鉴的这段)

流程图:

这里写图片描述

  • 使用前配置:

在Moudle 中搜索依赖 Universal ImageLoader 添加到项目里面,

mainf 中添加权限

 <!-- 网络访问权限 -->  
    <uses-permission android:name="android.permission.INTERNET" />  
    <!-- 文件写入SD卡权限 (把图片缓存到本地)-->  
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> 
  • 重点有三个重要的类:

ImageLoaderConfiguration: 是针对图片缓存的全局配置,主要有线程类、缓存大小、磁盘大小、图片下载与解析、日志方面的配置。

/**
 * 全局配置 ImageLoaderConfiguration
 * 先要配置ImageLoaderConfiguration这个类实现全局ImageLoader的实现情况。
 */
public class MyApplecation extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        ImageLoaderConfiguration config;
        config = new ImageLoaderConfiguration
                .Builder(MyApplecation.this)
                .memoryCacheExtraOptions(480,800)// max width, max height,即保存的每个缓存文件的最大长宽
//                .diskCacheExtraOptions()
                .threadPoolSize(3)//线程池内加载的数量
                .threadPriority(Thread.NORM_PRIORITY-2)
                .denyCacheImageMultipleSizesInMemory()
//                .memoryCache(new UsingFreqLimitedMemoryCache(2*1024*1024))//你可以通过自己的内存缓存实现
                .memoryCacheSize(2*1024*1024)//内存缓存大小
                .diskCacheSize(50*1024*1024)//磁盘缓存大小
//                .diskCacheFileNameGenerator(new Md5FileNameGenerator())//将保存的时候的URI名称用MD5 加密
                .tasksProcessingOrder(QueueProcessingType.FIFO)//设置线程池队列任务,为FIFO(先进先出)
                .diskCacheFileCount(100)//设置磁盘缓存的文件最大数量
//                .diskCache(new UnlimitedDiskCache(cacheDir))// 自定义缓存路径
                .defaultDisplayImageOptions(DisplayImageOptions.createSimple())//显示的图片的各种格式DisplayImageOptions 的设置
                .imageDownloader(new BaseImageDownloader(MyApplecation.this,5*1000,30*1000))
                .writeDebugLogs()// Remove for release app
                .build();//构建完成

        //配置好ImageLoaderConfiguration后,调用以下方法来实现初始化:
        ImageLoader.getInstance().init(config);
        class BaseImageDowner implements ImageDownloader {

            @Override
            public InputStream getStream(String imageUri, Object extra) throws IOException {
                return null;
            }
        }
    }
}

DisplayImageOptions 用于指导每一个Imageloader根据网络图片的状态(空白、下载错误、正在下载)显示对应的图片,是否将缓存加载到磁盘上,下载完后对图片进行怎么样的处理

DisplayImageOptions options = new DisplayImageOptions.Builder()
                .showImageOnLoading(R.mipmap.ic_launcher)//设置图片在下载期间显示的图片
                .showImageForEmptyUri(R.drawable.weixin)//设置图片Uri为空或是错误的时候显示的图片
                .showImageOnFail(R.drawable.feng3)//设置图片加载/解码过程中错误时候显示的图片
                .cacheInMemory(true)//设置下载的图片是否缓存在内存中
                .cacheOnDisk(true)//设置下载的图片是否缓存在SD卡中
                .considerExifParams(true)  //是否考虑JPEG图像EXIF参数(旋转,翻转)
                .imageScaleType(ImageScaleType.EXACTLY_STRETCHED) //设置图片以如何的编码方式显示
                .bitmapConfig(Bitmap.Config.RGB_565)//设置图片的解码类型
//                .delayBeforeLoading(1000)//int delayInMillis为你设置的下载前的延迟时间

                //.preProcessor(BitmapProcessor preProcessor)  //设置图片加入缓存前,对bitmap进行设置
                .resetViewBeforeLoading(true)// 设置图片在下载前是否重置,复位
                .displayer(new RoundedBitmapDisplayer(20))//是否设置为圆角,弧度为多少
                .displayer(new FadeInBitmapDisplayer(100))//是否图片加载好后渐入的动画时间
                .build();

ImageLoader :是具体下载图片,缓存图片,显示图片的具体执行类,它有两个具体的方法displayImage(…)、loadImage(…),但是其实最终他们的实现都是displayImage(…)

displayImage(…) 方法有多个重载

1.使用默认配置

 // imageUrl代表图片的URL地址,imageView代表承载图片的IMAGEVIEW控件  

ImageLoader.getInstance().displayImage(imageUrl, imageView);

2.加载自定义配置的一个图片的

 // imageUrl代表图片的URL地址,imageView代表承载图片的IMAGEVIEW控件 , options代表DisplayImageOptions配置文件  

ImageLoader.getInstance().displayImage(imageUrl, imageView,options);
  1. 图片加载时候带加载情况的监听
imageLoader.displayImage(imageUrl, imageView, options, new ImageLoadingListener() {  
    @Override  
    public void onLoadingStarted() {  
       //开始加载的时候执行  
    }  
    @Override  
    public void onLoadingFailed(FailReason failReason) {        
       //加载失败的时候执行  
    }   
    @Override   
    public void onLoadingComplete(Bitmap loadedImage) {  
       //加载成功的时候执行  
    }   
    @Override   
    public void onLoadingCancelled() {  
       //加载取消的时候执行  

    }});  
  1. 图片加载时候,带监听又带加载进度条的情况
imageLoader.displayImage(imageUrl, imageView, options, new ImageLoadingListener() {  
    @Override  
    public void onLoadingStarted() {  
       //开始加载的时候执行  
    }  
    @Override  
    public void onLoadingFailed(FailReason failReason) {        
       //加载失败的时候执行  
    }      
    @Override      
    public void onLoadingComplete(Bitmap loadedImage) {  
       //加载成功的时候执行  
    }      
    @Override      
    public void onLoadingCancelled() {  
       //加载取消的时候执行  
    },new ImageLoadingProgressListener() {        
      @Override  
      public void onProgressUpdate(String imageUri, View view, int current,int total) {     
      //在这里更新 ProgressBar的进度信息  
      }  
    });  

如何加载本地图片:正确配置 ImageUrl 的地址即可

String imageUri = "http://site.com/image.png"; // from Web  
String imageUri = "file:///mnt/sdcard/image.png"; // from SD card  
String imageUri = "content://media/external/audio/albumart/13"; // from content provider  
String imageUri = "assets://image.png"; // from assets  
String imageUri = "drawable://" + R.drawable.image; // from drawables (only images, non-9patch)  

xUtils 异步框架的使用


github: https://github.com/wyouflf/xUtils3

xUtils3简介

  • xUtils 包含了很多实用的android工具.
  • xUtils 支持超大文件(超过2G)上传,更全面的http请求协议支持(11种谓词),拥有更加灵活的ORM,更多的事件注解支持且不受混淆影响…
  • xUtils 最低兼容Android 4.0 (api level 14). (Android 2.3?)
  • xUtils3变化较多所以建立了新的项目不在旧版(github.com/wyouflf/xUtils)上继续维护, 相对于旧版本:
    1. HTTP实现替换HttpClient为UrlConnection, 自动解析回调泛型, 更安全的断点续传策略.
    2. 支持标准的Cookie策略, 区分domain, path…
    3. 事件注解去除不常用的功能, 提高性能.
    4. 数据库api简化提高性能, 达到和greenDao一致的性能.
    5. 图片绑定支持gif(受系统兼容性影响, 部分gif文件只能静态显示), webp; 支持圆角, 圆形, 方形等裁剪, 支持自动旋转…
使用Gradle构建时添加一下依赖即可:
compile 'org.xutils:xutils:3.3.36'
使用前配置
需要的权限
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
初始化
// 在application的onCreate中初始化
@Override
public void onCreate() {
    super.onCreate();
    x.Ext.init(this);
    x.Ext.setDebug(BuildConfig.DEBUG); // 是否输出debug日志, 开启debug会影响性能.
    ...
}
加载图片

最简单的使用默认配置加载图片

x.image().bind(imageView,imageUrl);//使用xUtils加载图片,默认自带缓存

x.image().bind() 方法有多个重载函数,这一点和ImageLoader 很相似

void bind(ImageView view, String url);

void bind(ImageView view, String url, ImageOptions options);

void bind(ImageView view, String url, Callback.CommonCallback<Drawable> callback);

void bind(ImageView view, String url, ImageOptions options, Callback.CommonCallback<Drawable> callback);

使用示例:

 ImageOptions options = new ImageOptions.Builder()

                      .setSize(DensityUtil.dip2px(120), DensityUtil.dip2px(120))//图片大小
                      .setRadius(DensityUtil.dip2px(5))//ImageView圆角半径
                      .setCrop(true)// 如果ImageView的大小不是定义为wrap_content, 不要crop.
                      .setImageScaleType(ImageView.ScaleType.CENTER_CROP)
                      .setLoadingDrawableId(R.mipmap.ic_launcher)//加载中默认显示图片
                      .setFailureDrawableId(R.mipmap.ic_launcher)//加载失败后默认显示图片



                      .build();

              x.image().bind(imageView,imageUrl);//使用xUtils加载图片,默认自带缓存
              x.image().bind(imageView,imageUrl,options,new MyCallBack());


 /**
     * 加载图片时的回调函数
     */
    class MyCallBack implements Callback.CommonCallback {

    @Override
    public void onSuccess(Object result) {
        System.out.println("加载图片"+"onSuccess()");

    }

    @Override
    public void onError(Throwable ex, boolean isOnCallback) {

    }

    @Override
    public void onCancelled(CancelledException cex) {

    }

    @Override
    public void onFinished() {
        System.out.println("加载图片"+"onFinished()");

    }
xUtils的网络请求
 RequestParams params = new RequestParams("http://blog.csdn.net/mobile/experts.html");
                x.http().get(params, new Callback.CommonCallback<String>() {
                    @Override
                    public void onSuccess(String result) {
                        System.out.println("网络请求onSuccess()...");

                        text.setText(result);
                    }

                    @Override
                    public void onError(Throwable ex, boolean isOnCallback) {

                    }

                    @Override
                    public void onCancelled(CancelledException cex) {

                    }

                    @Override
                    public void onFinished() {
                        System.out.println("网络请求onFinished()...");
                    }
                });
带有缓存的请求示例:
   RequestParams params = new RequestParams("http://blog.csdn.net/mobile/experts.html");
                // 默认缓存存活时间, 单位:毫秒.(如果服务没有返回有效的max-age或Expires)
                params.setCacheMaxAge(1000 * 60 * 10);
                // 接下来使用CacheCallback, xUtils将为该请求缓存数据.
                x.http().get(params, new Callback.CacheCallback<String>() {
                    @Override
                    public boolean onCache(String result) {
                        // 得到缓存数据, 缓存过期后不会进入这个方法.
                        // 如果服务端没有返回过期时间, 参考params.setCacheMaxAge(maxAge)方法.
                        //
                        // * 客户端会根据服务端返回的 header 中 max-age 或 expires 来确定本地缓存是否给 onCache 方法.
                        //   如果服务端没有返回 max-age 或 expires, 那么缓存将一直保存, 除非这里自己定义了返回false的
                        //   逻辑, 那么xUtils将请求新数据, 来覆盖它.
                        //
                        // * 如果信任该缓存返回 true, 将不再请求网络;----这里可以和刷新配合使用
                        //   返回 false 继续请求网络, 但会在请求头中加上ETag, Last-Modified等信息,
                        //   如果服务端返回304, 则表示数据没有更新, 不继续加载数据.
                        //
                        text.setText(result);
                        return false; // true: 信任缓存数据, 不在发起网络请求; false不信任缓存数据.
                    }

                    @Override
                    public void onSuccess(String result) {
                        // 注意: 如果服务返回304 或 onCache 选择了信任缓存, 这时result为null.
                        if (result != null) {
                            text.setText(result);
                        }
                    }

                    @Override
                    public void onError(Throwable ex, boolean isOnCallback) {

                    }

                    @Override
                    public void onCancelled(CancelledException cex) {

                    }

                    @Override
                    public void onFinished() {

                            // 成功获取数据,在此方法中对返回的数据进行操作

                    }
                });
            }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值