Android 开源框架Universal-Image-Loader实例分析
参考自 http://blog.csdn.net/xiaanming/article/details/27525741
http://my.oschina.net/u/1024921/blog/146081
http://www.eoeandroid.com/thread-325840-1-1.html
主要分析官方的demo,以及一些需要注意的东西
1,首先,三个页面
HomeActivity(首页,注意有清空缓存的菜单键)
SimpleImageActivity(listview,gridview,gallery,viewpage等都在此页面,通过不同的fragment显示)
ComplexImageActivity(通过viewpage混和了listview和gridview的页面)
首页
/******************************************************************************* * Copyright 2011-2013 Sergey Tarasevich * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *******************************************************************************/ package com.nostra13.universalimageloader.sample.activity; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.View; import com.nostra13.universalimageloader.core.ImageLoader; import com.nostra13.universalimageloader.sample.Constants; import com.nostra13.universalimageloader.sample.R; import com.nostra13.universalimageloader.sample.fragment.ImageGalleryFragment; import com.nostra13.universalimageloader.sample.fragment.ImageGridFragment; import com.nostra13.universalimageloader.sample.fragment.ImageListFragment; import com.nostra13.universalimageloader.sample.fragment.ImagePagerFragment; import com.nostra13.universalimageloader.utils.L; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; /** * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) */ public class HomeActivity extends Activity { private static final String TEST_FILE_NAME = "Universal Image Loader @#&=+-_.,!()~'%20.png"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.ac_home); File testImageOnSdCard = new File("/mnt/sdcard", TEST_FILE_NAME); if (!testImageOnSdCard.exists()) { copyTestImageToSdCard(testImageOnSdCard); } } public void onImageListClick(View view) { Intent intent = new Intent(this, SimpleImageActivity.class); intent.putExtra(Constants.Extra.FRAGMENT_INDEX, ImageListFragment.INDEX); startActivity(intent); } public void onImageGridClick(View view) { Intent intent = new Intent(this, SimpleImageActivity.class); intent.putExtra(Constants.Extra.FRAGMENT_INDEX, ImageGridFragment.INDEX); startActivity(intent); } public void onImagePagerClick(View view) { Intent intent = new Intent(this, SimpleImageActivity.class); intent.putExtra(Constants.Extra.FRAGMENT_INDEX, ImagePagerFragment.INDEX); startActivity(intent); } public void onImageGalleryClick(View view) { Intent intent = new Intent(this, SimpleImageActivity.class); intent.putExtra(Constants.Extra.FRAGMENT_INDEX, ImageGalleryFragment.INDEX); startActivity(intent); } public void onFragmentsClick(View view) { Intent intent = new Intent(this, ComplexImageActivity.class); startActivity(intent); } @Override public void onBackPressed() { ImageLoader.getInstance().stop(); super.onBackPressed(); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main_menu, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.item_clear_memory_cache: ImageLoader.getInstance().clearMemoryCache(); return true; case R.id.item_clear_disc_cache: ImageLoader.getInstance().clearDiskCache(); return true; default: return false; } } private void copyTestImageToSdCard(final File testImageOnSdCard) { new Thread(new Runnable() { @Override public void run() { try { InputStream is = getAssets().open(TEST_FILE_NAME); FileOutputStream fos = new FileOutputStream(testImageOnSdCard); byte[] buffer = new byte[8192]; int read; try { while ((read = is.read(buffer)) != -1) { fos.write(buffer, 0, read); } } finally { fos.flush(); fos.close(); is.close(); } } catch (IOException e) { L.w("Can't copy test image onto SD card"); } } }).start(); } }
除了HomeActivity和ComplexImageActivity,其他界面都在此显示
根据不同的标签生成不同Fragment......最后commit,确认显示
ImagePagerFragment标签下需要保存下列表Fragment传过来的条目position的数据,给ImagePagerFragment(实际上这个跳转是从SimpleImageActivity跳到SimpleImageActivity,有点怪)
/******************************************************************************* * Copyright 2014 Sergey Tarasevich * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *******************************************************************************/ package com.nostra13.universalimageloader.sample.activity; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentActivity; import com.nostra13.universalimageloader.sample.Constants; import com.nostra13.universalimageloader.sample.R; import com.nostra13.universalimageloader.sample.fragment.ImageGalleryFragment; import com.nostra13.universalimageloader.sample.fragment.ImageGridFragment; import com.nostra13.universalimageloader.sample.fragment.ImageListFragment; import com.nostra13.universalimageloader.sample.fragment.ImagePagerFragment; /** * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) */ //除了主界面和组合了listview和gridview的界面,其他界面都在此显示 //根据不同的标签生成不同Fragment......最后commit,确认显示 //ImagePagerFragment标签下需要保存下列表Fragment传过来的条目position的数据,给ImagePagerFragment(实际上这个跳转是从SimpleImageActivity跳到SimpleImageActivity,有点怪) public class SimpleImageActivity extends FragmentActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); int frIndex = getIntent().getIntExtra(Constants.Extra.FRAGMENT_INDEX, 0); Fragment fr; String tag; int titleRes; switch (frIndex) { default: case ImageListFragment.INDEX: tag = ImageListFragment.class.getSimpleName(); fr = getSupportFragmentManager().findFragmentByTag(tag); if (fr == null) { fr = new ImageListFragment(); } titleRes = R.string.ac_name_image_list; break; case ImageGridFragment.INDEX: tag = ImageGridFragment.class.getSimpleName(); fr = getSupportFragmentManager().findFragmentByTag(tag); if (fr == null) { fr = new ImageGridFragment(); } titleRes = R.string.ac_name_image_grid; break; case ImagePagerFragment.INDEX: tag = ImagePagerFragment.class.getSimpleName(); fr = getSupportFragmentManager().findFragmentByTag(tag); if (fr == null) { fr = new ImagePagerFragment(); fr.setArguments(getIntent().getExtras()); } titleRes = R.string.ac_name_image_pager; break; case ImageGalleryFragment.INDEX: tag = ImageGalleryFragment.class.getSimpleName(); fr = getSupportFragmentManager().findFragmentByTag(tag); if (fr == null) { fr = new ImageGalleryFragment(); } titleRes = R.string.ac_name_image_gallery; break; } setTitle(titleRes); //此时关联的tag和对应的fragment getSupportFragmentManager().beginTransaction().replace(android.R.id.content, fr, tag).commit(); } }
ComplexImageActivity
/******************************************************************************* * Copyright 2014 Sergey Tarasevich * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *******************************************************************************/ package com.nostra13.universalimageloader.sample.activity; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; import android.support.v4.view.ViewPager; import com.nostra13.universalimageloader.sample.R; import com.nostra13.universalimageloader.sample.fragment.ImageGridFragment; import com.nostra13.universalimageloader.sample.fragment.ImageListFragment; /** * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) */ public class ComplexImageActivity extends FragmentActivity { private static final String STATE_POSITION = "STATE_POSITION"; private ViewPager pager; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.ac_complex); int pagerPosition = savedInstanceState == null ? 0 : savedInstanceState.getInt(STATE_POSITION); pager = (ViewPager) findViewById(R.id.pager); pager.setAdapter(new ImagePagerAdapter(getSupportFragmentManager())); pager.setCurrentItem(pagerPosition); } @Override public void onSaveInstanceState(Bundle outState) { outState.putInt(STATE_POSITION, pager.getCurrentItem()); } private class ImagePagerAdapter extends FragmentPagerAdapter { Fragment listFragment; Fragment gridFragment; ImagePagerAdapter(FragmentManager fm) { super(fm); listFragment = new ImageListFragment(); gridFragment = new ImageGridFragment(); } @Override public int getCount() { return 2; } @Override public Fragment getItem(int position) { switch (position) { case 0: return listFragment; case 1: return gridFragment; default: return null; } } @Override public CharSequence getPageTitle(int position) { switch (position) { case 0: return getString(R.string.title_list); case 1: return getString(R.string.title_grid); default: return null; } } } }
2,UILApplication,应用配置文件
可以配置默认的参数,并创建ImageLoader的实例
<span style="font-family:Microsoft YaHei;font-size:14px;">//创建默认的ImageLoader配置参数 ImageLoaderConfiguration configuration = ImageLoaderConfiguration .createDefault(this); //Initialize ImageLoader with configuration. ImageLoader.getInstance().init(configuration); </span>
也可以配置具体的参数
/******************************************************************************* * Copyright 2011-2013 Sergey Tarasevich * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *******************************************************************************/ package com.nostra13.universalimageloader.sample; import android.annotation.TargetApi; import android.app.Application; import android.content.Context; import android.os.Build; import android.os.StrictMode; import com.nostra13.universalimageloader.cache.disc.naming.Md5FileNameGenerator; import com.nostra13.universalimageloader.cache.memory.impl.WeakMemoryCache; import com.nostra13.universalimageloader.core.ImageLoader; import com.nostra13.universalimageloader.core.ImageLoaderConfiguration; import com.nostra13.universalimageloader.core.assist.QueueProcessingType; /** * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) */ public class UILApplication extends Application { @TargetApi(Build.VERSION_CODES.GINGERBREAD) @SuppressWarnings("unused") @Override public void onCreate() { if (Constants.Config.DEVELOPER_MODE && Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) { StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectAll().penaltyDialog().build()); StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll().penaltyDeath().build()); } super.onCreate(); initImageLoader(getApplicationContext()); } public static void initImageLoader(Context context) { // This configuration tuning is custom. You can tune every option, you may tune some of them, // or you can create default configuration by // ImageLoaderConfiguration.createDefault(this); // method. ImageLoaderConfiguration.Builder config = new ImageLoaderConfiguration.Builder(context); //config.threadPoolSize(5) //设置线程池的最高线程数量(1-5)(减少线程个数,有利于减少发生OOM) // 设置线程优先级(没什么用) config.threadPriority(Thread.NORM_PRIORITY - 2); // 设定内存缓存为弱缓存(该框架默认的缓存类是强引用缓存LruMemoryCache) config.memoryCache(new WeakMemoryCache()); // 自动缩放 config.denyCacheImageMultipleSizesInMemory(); // 设定缓存到sd卡的文件的命名 config.diskCacheFileNameGenerator(new Md5FileNameGenerator()); // 设定缓存到sd卡的最大文件大小 config.diskCacheSize(50 * 1024 * 1024); // 50 MiB config.tasksProcessingOrder(QueueProcessingType.LIFO); config.writeDebugLogs(); // Remove for release app // Initialize ImageLoader with configuration. ImageLoader.getInstance().init(config.build()); } }
关于强弱引用备注下
强引用是指创建一个对象并把这个对象赋给一个引用变量, 强引用有引用变量指向时永远不会被垃圾回收。即使内存不足的时候宁愿报OOM也不被垃圾回收器回收,我们new的对象都是强引用
弱引用通过weakReference类来实现,它具有很强的不确定性,如果垃圾回收器扫描到有着WeakReference的对象,就会将其回收释放内存
对于默认使用的强引用缓存(LruMemoryCache),采取的策略是,先进先出原则,设置一个固定缓存大小,当超出这个最大值时,删除LinkedHashMap中的第一个元素
对于弱引用缓存(WeakMemoryCache),这个类缓存bitmap的总大小没有限制,唯一不足的地方就是不稳定,缓存的图片容易被回收掉
具体参考这篇分析详细 http://blog.csdn.net/xiaanming/article/details/27525741
3,各个fragment
BaseFragment(用以给AbsListViewBaseFragment,ImageGalleryFragment,ImagePagerFragment继承)(有两个菜单项)
/******************************************************************************* * Copyright 2011-2014 Sergey Tarasevich * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *******************************************************************************/ package com.nostra13.universalimageloader.sample.fragment; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import com.nostra13.universalimageloader.core.ImageLoader; import com.nostra13.universalimageloader.sample.R; /** * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) */ //基础Fragment,创建菜单两项,清除内存缓存和清除硬盘缓存 public abstract class BaseFragment extends Fragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setHasOptionsMenu(true); } public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { inflater.inflate(R.menu.main_menu, menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.item_clear_memory_cache: ImageLoader.getInstance().clearMemoryCache(); return true; case R.id.item_clear_disc_cache: ImageLoader.getInstance().clearDiskCache(); return true; default: return false; } } }
AbsListViewBaseFragment(用以给listview和gridview的fragment继承的fragment)
主要有两个关键的参数
//列表滚动是否暂停加载图片
protected boolean pauseOnScroll = true;
//列表猛的滚动是否暂停加载图片
protected boolean pauseOnFling = true;
/******************************************************************************* * Copyright 2011-2014 Sergey Tarasevich * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *******************************************************************************/ package com.nostra13.universalimageloader.sample.fragment; import android.content.Intent; import android.view.Menu; import android.view.MenuItem; import android.widget.AbsListView; import com.nostra13.universalimageloader.core.ImageLoader; import com.nostra13.universalimageloader.core.listener.PauseOnScrollListener; import com.nostra13.universalimageloader.sample.Constants; import com.nostra13.universalimageloader.sample.R; import com.nostra13.universalimageloader.sample.activity.SimpleImageActivity; /** * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) */ //要用于GridFragment和ListFragment,所以主要包括了通用的设置菜单方法,设置列表滑动是否暂停加载图片的方法,以及传递item位置信息的方法 //因为gridview和listview都继承自AbsListView,所以此类的listView也可以在GridFragment和ListFragment复用 public abstract class AbsListViewBaseFragment extends BaseFragment { protected static final String STATE_PAUSE_ON_SCROLL = "STATE_PAUSE_ON_SCROLL"; protected static final String STATE_PAUSE_ON_FLING = "STATE_PAUSE_ON_FLING"; protected AbsListView listView; //列表滚动是否暂停加载图片 protected boolean pauseOnScroll = true; //列表猛的滚动是否暂停加载图片 protected boolean pauseOnFling = true; @Override public void onResume() { super.onResume(); applyScrollListener(); } @Override public void onPrepareOptionsMenu(Menu menu) { MenuItem pauseOnScrollItem = menu.findItem(R.id.item_pause_on_scroll); pauseOnScrollItem.setVisible(true); pauseOnScrollItem.setChecked(pauseOnScroll); MenuItem pauseOnFlingItem = menu.findItem(R.id.item_pause_on_fling); pauseOnFlingItem.setVisible(true); pauseOnFlingItem.setChecked(pauseOnFling); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.item_pause_on_scroll: pauseOnScroll = !pauseOnScroll; item.setChecked(pauseOnScroll); applyScrollListener(); return true; case R.id.item_pause_on_fling: pauseOnFling = !pauseOnFling; item.setChecked(pauseOnFling); applyScrollListener(); return true; default: return super.onOptionsItemSelected(item); } } protected void startImagePagerActivity(int position) { Intent intent = new Intent(getActivity(), SimpleImageActivity.class); intent.putExtra(Constants.Extra.FRAGMENT_INDEX, ImagePagerFragment.INDEX); intent.putExtra(Constants.Extra.IMAGE_POSITION, position); startActivity(intent); } //滚动列表时,是否暂停加载图片的监听 //第一个参数就是我们的图片加载对象ImageLoader, 第二个是控制是否在滑动过程中暂停加载图片,如果需要暂停传true就行了,第三个参数控制猛的滑动界面的时候图片是否加载 private void applyScrollListener() { listView.setOnScrollListener(new PauseOnScrollListener(ImageLoader.getInstance(), pauseOnScroll, pauseOnFling)); } }ImageListFragment
1,有关于DisplayImageOptions的设置,各情况加载的图片以及缓存等的设置
在DisplayImageOptions选项中配置bitmapConfig为Bitmap.Config.RGB_565,因为默认是ARGB_8888, 使用RGB_565会比使用ARGB_8888少消耗2倍的内存
2,还有关于渐进动画的设置AnimateFirstDisplayListener
/******************************************************************************* * Copyright 2011-2014 Sergey Tarasevich * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *******************************************************************************/ package com.nostra13.universalimageloader.sample.fragment; import android.graphics.Bitmap; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; import com.nostra13.universalimageloader.core.DisplayImageOptions; import com.nostra13.universalimageloader.core.ImageLoader; import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer; import com.nostra13.universalimageloader.core.display.RoundedBitmapDisplayer; import com.nostra13.universalimageloader.core.listener.ImageLoadingListener; import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener; import com.nostra13.universalimageloader.sample.Constants; import com.nostra13.universalimageloader.sample.R; import java.util.Collections; import java.util.LinkedList; import java.util.List; /** * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) */ public class ImageListFragment extends AbsListViewBaseFragment { public static final int INDEX = 0; String[] imageUrls = Constants.IMAGES; DisplayImageOptions options; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); options = new DisplayImageOptions.Builder() .showImageOnLoading(R.drawable.ic_stub) .showImageForEmptyUri(R.drawable.ic_empty) .showImageOnFail(R.drawable.ic_error) .cacheInMemory(true) .cacheOnDisk(true) .considerExifParams(true) .displayer(new RoundedBitmapDisplayer(20))//设置圆角 .build(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fr_image_list, container, false); //listView都是继承自AbsListViewBaseFragment的listView listView = (ListView) rootView.findViewById(android.R.id.list); ((ListView) listView).setAdapter(new ImageAdapter()); listView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { startImagePagerActivity(position); } }); return rootView; } @Override public void onDestroy() { super.onDestroy(); AnimateFirstDisplayListener.displayedImages.clear(); } private static class ViewHolder { TextView text; ImageView image; } class ImageAdapter extends BaseAdapter { private LayoutInflater inflater; private ImageLoadingListener animateFirstListener = new AnimateFirstDisplayListener(); ImageAdapter() { inflater = LayoutInflater.from(getActivity()); } @Override public int getCount() { return imageUrls.length; } @Override public Object getItem(int position) { return position; } @Override public long getItemId(int position) { return position; } @Override public View getView(final int position, View convertView, ViewGroup parent) { View view = convertView; final ViewHolder holder; if (convertView == null) { view = inflater.inflate(R.layout.item_list_image, parent, false); holder = new ViewHolder(); holder.text = (TextView) view.findViewById(R.id.text); holder.image = (ImageView) view.findViewById(R.id.image); view.setTag(holder); } else { holder = (ViewHolder) view.getTag(); } holder.text.setText("Item " + (position + 1)); ImageLoader.getInstance().displayImage(imageUrls[position], holder.image, options, animateFirstListener); return view; } } //设图片第一次加载完成的渐入动画 //取得加载完成图片的uri,看是否在已经显示的图片列表中,没有即第一次则显示加载动画并加入到显示列表 private static class AnimateFirstDisplayListener extends SimpleImageLoadingListener { static final List<String> displayedImages = Collections.synchronizedList(new LinkedList<String>()); @Override public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) { if (loadedImage != null) { ImageView imageView = (ImageView) view; boolean firstDisplay = !displayedImages.contains(imageUri); if (firstDisplay) { FadeInBitmapDisplayer.animate(imageView, 500); displayedImages.add(imageUri); } } } } }
ImageGridFragment
显示加载进度的监听SimpleImageLoadingListener
/******************************************************************************* * Copyright 2011-2014 Sergey Tarasevich * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *******************************************************************************/ package com.nostra13.universalimageloader.sample.fragment; import android.graphics.Bitmap; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.BaseAdapter; import android.widget.GridView; import android.widget.ImageView; import android.widget.ProgressBar; import com.nostra13.universalimageloader.core.DisplayImageOptions; import com.nostra13.universalimageloader.core.ImageLoader; import com.nostra13.universalimageloader.core.assist.FailReason; import com.nostra13.universalimageloader.core.listener.ImageLoadingProgressListener; import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener; import com.nostra13.universalimageloader.sample.Constants; import com.nostra13.universalimageloader.sample.R; /** * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) */ public class ImageGridFragment extends AbsListViewBaseFragment { public static final int INDEX = 1; String[] imageUrls = Constants.IMAGES; DisplayImageOptions options; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); options = new DisplayImageOptions.Builder() .showImageOnLoading(R.drawable.ic_stub) .showImageForEmptyUri(R.drawable.ic_empty) .showImageOnFail(R.drawable.ic_error) .cacheInMemory(true) .cacheOnDisk(true) .considerExifParams(true) .bitmapConfig(Bitmap.Config.RGB_565) .build(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fr_image_grid, container, false); listView = (GridView) rootView.findViewById(R.id.grid); ((GridView) listView).setAdapter(new ImageAdapter()); listView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { startImagePagerActivity(position); } }); return rootView; } public class ImageAdapter extends BaseAdapter { private LayoutInflater inflater; ImageAdapter() { inflater = LayoutInflater.from(getActivity()); } @Override public int getCount() { return imageUrls.length; } @Override public Object getItem(int position) { return null; } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { final ViewHolder holder; View view = convertView; if (view == null) { view = inflater.inflate(R.layout.item_grid_image, parent, false); holder = new ViewHolder(); assert view != null; holder.imageView = (ImageView) view.findViewById(R.id.image); holder.progressBar = (ProgressBar) view.findViewById(R.id.progress); view.setTag(holder); } else { holder = (ViewHolder) view.getTag(); } //这里有显示图片加载进度的方法 ImageLoader.getInstance() .displayImage(imageUrls[position], holder.imageView, options, new SimpleImageLoadingListener() { @Override public void onLoadingStarted(String imageUri, View view) { holder.progressBar.setProgress(0); holder.progressBar.setVisibility(View.VISIBLE); } @Override public void onLoadingFailed(String imageUri, View view, FailReason failReason) { holder.progressBar.setVisibility(View.GONE); } @Override public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) { holder.progressBar.setVisibility(View.GONE); } }, new ImageLoadingProgressListener() { @Override public void onProgressUpdate(String imageUri, View view, int current, int total) { holder.progressBar.setProgress(Math.round(100.0f * current / total)); } }); return view; } } static class ViewHolder { ImageView imageView; ProgressBar progressBar; } }
ImagePagerFragment
注意在此Fragment中通过getArguments方法取得在SimpleImageActivity中setArguments的position的值,对应正确的条目
/******************************************************************************* * Copyright 2011-2014 Sergey Tarasevich * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *******************************************************************************/ package com.nostra13.universalimageloader.sample.fragment; import android.graphics.Bitmap; import android.os.Bundle; import android.os.Parcelable; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.Toast; import com.nostra13.universalimageloader.core.DisplayImageOptions; import com.nostra13.universalimageloader.core.ImageLoader; import com.nostra13.universalimageloader.core.assist.FailReason; import com.nostra13.universalimageloader.core.assist.ImageScaleType; import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer; import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener; import com.nostra13.universalimageloader.sample.Constants; import com.nostra13.universalimageloader.sample.R; /** * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) */ public class ImagePagerFragment extends BaseFragment { public static final int INDEX = 2; String[] imageUrls = Constants.IMAGES; DisplayImageOptions options; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); options = new DisplayImageOptions.Builder() .showImageForEmptyUri(R.drawable.ic_empty) .showImageOnFail(R.drawable.ic_error) .resetViewBeforeLoading(true) .cacheOnDisk(true) .imageScaleType(ImageScaleType.EXACTLY) .bitmapConfig(Bitmap.Config.RGB_565) .considerExifParams(true) .displayer(new FadeInBitmapDisplayer(300)) .build(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fr_image_pager, container, false); ViewPager pager = (ViewPager) rootView.findViewById(R.id.pager); pager.setAdapter(new ImageAdapter()); //在Fragment中取出传过来的值getArguments()返回bundle pager.setCurrentItem(getArguments().getInt(Constants.Extra.IMAGE_POSITION, 0)); return rootView; } private class ImageAdapter extends PagerAdapter { private LayoutInflater inflater; ImageAdapter() { inflater = LayoutInflater.from(getActivity()); } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView((View) object); } @Override public int getCount() { return imageUrls.length; } @Override public Object instantiateItem(ViewGroup view, int position) { View imageLayout = inflater.inflate(R.layout.item_pager_image, view, false); assert imageLayout != null; ImageView imageView = (ImageView) imageLayout.findViewById(R.id.image); final ProgressBar spinner = (ProgressBar) imageLayout.findViewById(R.id.loading); ImageLoader.getInstance().displayImage(imageUrls[position], imageView, options, new SimpleImageLoadingListener() { @Override public void onLoadingStarted(String imageUri, View view) { spinner.setVisibility(View.VISIBLE); } @Override public void onLoadingFailed(String imageUri, View view, FailReason failReason) { String message = null; switch (failReason.getType()) { case IO_ERROR: message = "Input/Output error"; break; case DECODING_ERROR: message = "Image can't be decoded"; break; case NETWORK_DENIED: message = "Downloads are denied"; break; case OUT_OF_MEMORY: message = "Out Of Memory error"; break; case UNKNOWN: message = "Unknown error"; break; } Toast.makeText(getActivity(), message, Toast.LENGTH_SHORT).show(); spinner.setVisibility(View.GONE); } @Override public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) { spinner.setVisibility(View.GONE); } }); view.addView(imageLayout, 0); return imageLayout; } @Override public boolean isViewFromObject(View view, Object object) { return view.equals(object); } @Override public void restoreState(Parcelable state, ClassLoader loader) { } @Override public Parcelable saveState() { return null; } } }
参考自 http://blog.csdn.net/xiaanming/article/details/27525741
http://my.oschina.net/u/1024921/blog/146081
http://www.eoeandroid.com/thread-325840-1-1.html
代码 官方的:https://github.com/nostra13/Android-Universal-Image-Loader
自己加注释的:http://download.csdn.net/detail/superjunjin/8571709
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。