使用uil为ListView加载图片
一个简单的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中进行参数配置,做了内存缓存和硬盘缓存,当手机上图片正常显示,说明已缓存.
此时即便没有网络,图片也能正常显示.
缓存策略的流程就是:
每次加载图片的时候都优先去内存缓存当中读取,当读取不到的时候则回去硬盘缓存中读取,而如果硬盘缓存仍然读取不到的话,就从网络上请求原始数据