使用uil为ListView加载图片

作者: wxyass 分类: Android 发布时间: 2017-07-06 14:45

一个简单的Listview,然后里面item就是一张图片,希望很流畅的加载网络图片,然后滑动的时候不会出现卡顿,也不会出现OOM现象。
在断开网络连接的时候,点击listview的item,进入到图片详情界面,依旧能够加载出完整的图片。


Universal-Image-Loader,一个强大的图片加载框架,具有以下的特性:

1.多线程下载图片,图片可以来源于网络,文件系统,项目文件夹assets中以及drawable中等
2.支持随意的配置ImageLoader,例如线程池,图片下载器,内存缓存策略,硬盘缓存策略,图片显示选项以及其他的一些配置
3.支持图片的内存缓存,文件系统缓存或者SD卡缓存
4.支持图片下载过程的监听
5.根据控件(ImageView)的大小对Bitmap进行裁剪,减少Bitmap占用过多的内存
6.较好的控制图片的加载过程,例如暂停图片加载,重新开始加载图片,一般使用在ListView,GridView中,滑动过程中暂停加载图片,停止滑动的时候去加载图片
7.提供在较慢的网络下对图片进行加载

一 新建工程,前期工作处理好,参考上篇

1 下载jar包,导入工程

原作者Github下载 /downloads/universal-image-loader-1.9.5.jar
个人备份下载 universal-image-loader-1.9.5.jar

2 创建MyApplication类,配置参数

import android.app.Application;
import android.graphics.Bitmap;
import android.os.Environment;
import android.os.Handler;

import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiskCache;
import com.nostra13.universalimageloader.cache.disc.naming.HashCodeFileNameGenerator;
import com.nostra13.universalimageloader.cache.memory.impl.LruMemoryCache;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import com.nostra13.universalimageloader.core.assist.ImageScaleType;
import com.nostra13.universalimageloader.core.assist.QueueProcessingType;
import com.nostra13.universalimageloader.core.decode.BaseImageDecoder;
import com.nostra13.universalimageloader.core.display.SimpleBitmapDisplayer;
import com.nostra13.universalimageloader.core.download.BaseImageDownloader;

import java.io.File;

/**
 * Created by wxyass.
 */
public class MyApplication extends Application {

    private MyApplication instance;
    @Override
    public void onCreate() {
        super.onCreate();
        instance = this;
        initImageloader();
    }

    public void initImageloader() {
        DisplayImageOptions options = new DisplayImageOptions.Builder()
                .showImageOnLoading(R.drawable.ic_download)
                .showImageOnFail(R.drawable.ic_download)
                .resetViewBeforeLoading(false) // default
                .delayBeforeLoading(0).cacheInMemory(true) // default
                .cacheOnDisk(true) // default
                .considerExifParams(true) // default
                .imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2) // default
                .bitmapConfig(Bitmap.Config.ARGB_8888) // default
                .displayer(new SimpleBitmapDisplayer()) // default
                .handler(new Handler()) // default
                .build();

        File picPath = new File(Environment.getExternalStorageDirectory()
                .getPath()+ File.separator+ "MyDemo"+ File.separator+ "files");
        ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(
                getApplicationContext())
                .memoryCacheExtraOptions(480, 800)
                // default = device screen dimensions
                .diskCacheExtraOptions(480, 800, null)
                .threadPoolSize(3)
                // default
                .threadPriority(Thread.NORM_PRIORITY - 1)
                // default
                .tasksProcessingOrder(QueueProcessingType.FIFO)
                // default
                .denyCacheImageMultipleSizesInMemory()
                .memoryCache(new LruMemoryCache(2 * 1024 * 1024))
                .memoryCacheSize(2 * 1024 * 1024)
                .memoryCacheSizePercentage(13)
                // default
                .diskCache(new UnlimitedDiskCache(picPath))
                // default
                .diskCacheSize(50 * 1024 * 1024)
                .diskCacheFileCount(1000)
                .diskCacheFileNameGenerator(new HashCodeFileNameGenerator())
                // default
                .imageDownloader(
                        new BaseImageDownloader(getApplicationContext())) // default
                .imageDecoder(new BaseImageDecoder(true)) // default
                .defaultDisplayImageOptions(options) // default
                .writeDebugLogs().build();
        ImageLoader.getInstance().init(config);
    }
}

3 添加权限
4 修改清单文件中application的name属性

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.wxyass.tplistviewbyuil">

    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

    <application
        android:name=".MyApplication"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <activity android:name=".ImageActivity"
            android:screenOrientation="portrait" />
    </application>
</manifest>

二 工程整体目录,如图

三 创建ListView的适配器

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;

import com.nostra13.universalimageloader.core.ImageLoader;

/**
 * Created by wxyass.
 */

public class ImgListAdapter extends BaseAdapter {

    private Context context;
    private LayoutInflater layoutinflater;
    private String[] imageUrls;

    public ImgListAdapter(String[] urls, Context context) {
        this.context = context;
        this.imageUrls = urls;
        this.layoutinflater = LayoutInflater.from(context);
    }

    @Override
    public int getCount() {
        return imageUrls.length;
    }

    @Override
    public Object getItem(int position) {
        return position;
    }

    @Override
    public long getItemId(int id) {
        return id;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup viewGroup) {
        ViewHolder holder;
        if (convertView == null) {
            holder = new ViewHolder();
            convertView = layoutinflater.inflate(R.layout.img_item, null);
            holder.webImg = (ImageView) convertView.findViewById(R.id.img);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        // 通过ImageLoader来获取网络图片
        ImageLoader.getInstance().displayImage(imageUrls[position], holder.webImg);
        return convertView;
    }

    class ViewHolder {
        public ImageView webImg;
    }
}  
3.1 附上listview条目布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:id="@+id/ll_indexstatus_dialog"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
    >

    <ImageView
        android:id="@+id/img"
        android:layout_width="wrap_content"
        android:layout_height="150dp"
        android:layout_centerHorizontal="true"
        />
</RelativeLayout>  

四 修改MainActivity代码,为ListView加载图片

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;

import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.listener.PauseOnScrollListener;

public class MainActivity extends AppCompatActivity {

    ListView listview;
    ImgListAdapter adapter;
    String[] imageuil = new String[]{"http://oss.wxyass.com/private/images/001/Pic_000042.jpg",
            "http://oss.wxyass.com/private/images/001/Pic_000045.jpg",
            "http://oss.wxyass.com/private/images/001/Pic_000051.jpg",
            "http://oss.wxyass.com/private/images/001/Pic_000056.jpg",
            "http://oss.wxyass.com/private/images/001/Pic_000061.jpg",
            "http://oss.wxyass.com/private/images/001/Pic_000067.jpg",
            "http://oss.wxyass.com/private/images/001/Pic_000071.jpg",
            "http://oss.wxyass.com/private/images/001/Pic_000076.jpg",
            "http://oss.wxyass.com/private/images/001/Pic_000077.jpg",
            "http://oss.wxyass.com/private/images/001/Pic_000080.jpg",
            "http://oss.wxyass.com/private/images/001/Pic_000085.jpg"};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        listview = (ListView) findViewById(R.id.listview);
        adapter = new ImgListAdapter(imageuil, getApplicationContext());
        listview.setAdapter(adapter);
        /* PauseOnScrollListener这个类来控制ListView,GridView滑动过程中停止去加载图片.
        第一个参数就是我们的图片加载对象ImageLoader,
        第二个是控制是否在滑动过程中暂停加载图片,如果需要暂停传true就行了,
        第三个参数控制猛的滑动界面的时候图片是否加载。*/
        listview.setOnScrollListener(new PauseOnScrollListener(ImageLoader.getInstance(), false, true));
        // listview条目的点击事件
        listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Intent intent = new Intent(getApplicationContext(), ImageActivity.class);
                intent.putExtra("url", imageuil[position]);
                startActivity(intent);
            }
        });
    }
}
4.1 附上MainActivity的布局
<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"
                 >
    <ListView
        android:id="@+id/listview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginBottom="10dp"
        android:descendantFocusability="beforeDescendants"
        android:dividerHeight="1dp"
        android:footerDividersEnabled="false" />

</RelativeLayout>  

五 修改图片详情界面代码,处理item传递过来的数据

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.ImageView;
import com.nostra13.universalimageloader.core.ImageLoader;

public class ImageActivity extends AppCompatActivity {

    ImageView pagerImg;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_image);
        pagerImg = (ImageView) findViewById(R.id.pager_img);
        Intent intent = getIntent();
        Bundle data = intent.getExtras();
        ImageLoader.getInstance().displayImage((String) data.get("url"),pagerImg);
    }
}  
5.1 附上ImageActivity的布局文件
<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"
    >
    <ImageView
        android:id="@+id/pager_img"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />
</RelativeLayout>  

最后 总结

通过在MyApplication中进行参数配置,做了内存缓存和硬盘缓存,当手机上图片正常显示,说明已缓存.

此时即便没有网络,图片也能正常显示.

缓存策略的流程就是:
每次加载图片的时候都优先去内存缓存当中读取,当读取不到的时候则回去硬盘缓存中读取,而如果硬盘缓存仍然读取不到的话,就从网络上请求原始数据

本文源码下载

参考:
http://blog.csdn.net/tyk0910/article/details/50375070

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

发表评论

邮箱地址不会被公开。 必填项已用*标注