实现从网上下载大量图片在GridView上显示过程中遇到的一些问题
来源:互联网 发布:淘宝店名设计在线 编辑:程序博客网 时间:2024/04/30 05:08
图片从Flickr上下载(需要fq才能访问)。
我们先理下思路再开始写代码,首先从Flickr上拿到JSON字符串,然后解析,我们可以用一个类来代表每张图片所包含的信息,这些信息的下载都很快,我们可以用AsyncTask来解决,等要通过url去下载图片的时候,AsyncTask就不合适了,具体原因看我这篇文章:关于Android AsyncTask的一些总结。所以我们现在来单独考虑下图片的下载,首先我们没必要也不应该一次下载所有图片,因为我们只需要及时加载用户当前滑到界面的图片即可,而且一次下载所有图片从时间和内存角度考虑都是不可取的,因此只需要下载当前用户所看到界面的图片即可。具体实现时,我们可以弄个后台线程去下载图片。下面我们来具体看下实现过程。
关于Flickr API的使用这里就不说了,可以去Flickr网站看相关文档。
其中JSON字符串下载及解析的相关主要代码如下:
AsyncTask<Void,Void,List<PhotoItem>> mAsyncTask = new AsyncTask<Void,Void,List<PhotoItem>>() { @Override protected List<PhotoItem> doInBackground(Void... params) { try { mData = parseJson(getJsonString()); return mData; } catch (IOException e) { e.printStackTrace(); } catch (JSONException e) { e.printStackTrace(); } return null; } @Override protected void onPostExecute(List<PhotoItem> data) { if (data != null) { mGridViewAdapter.setData(data); mGridView.setAdapter(mGridViewAdapter); } }};//解析JSON字符串List<PhotoItem> parseJson(String jsonString) throws JSONException { List<PhotoItem> data = new ArrayList<>(); JSONObject jsonObject = new JSONObject(jsonString); JSONObject jsonObject1 = jsonObject.getJSONObject("photos"); JSONArray jsonArray = jsonObject1.getJSONArray("photo"); for (int i = 0; i < jsonArray.length(); i++) { PhotoItem photoItem = new PhotoItem(); photoItem.setImageUrl((String) jsonArray.getJSONObject(i).get("url_s")); data.add(photoItem); } return data;}//获取JSON字符串public String getJsonString() throws IOException { URL url = new URL("https://api.flickr.com/services/rest/?method=flickr.photos.getRecent" + "&api_key=XXX&format=json&nojsoncallback=1" + "&extras=url_s"); HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection(); try { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); InputStream inputStream = httpURLConnection.getInputStream(); if (httpURLConnection.getResponseCode() != HttpURLConnection.HTTP_OK) { return null; } int bytesRead = 0; byte[] buffer = new byte[1024]; while ((bytesRead = inputStream.read(buffer)) > 0) { byteArrayOutputStream.write(buffer, 0, bytesRead); } byteArrayOutputStream.close(); return new String(byteArrayOutputStream.toByteArray()); } finally { httpURLConnection.disconnect(); }}
注意URL中的api_key=XXX换成你从Flickr网站上获取的API KRY。
上面的getJsonString方法主要是将获得的InputStream变成String,parseJson方法就是解析获得的String,并返回解析的结果。
下面我们来看下怎么实现只下载当前用户所看到界面的图片,其实主要代码就下面两段:
//给GridView设置滑动监听mGridView.setOnScrollListener(new AbsListView.OnScrollListener() { @Override public void onScrollStateChanged(AbsListView view, int scrollState) { if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE) { mGridViewIsIdle = true; mGridViewAdapter.notifyDataSetChanged(); } else { mGridViewIsIdle = false; } } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { }});
//滑动过程中不产生新的异步下载任务(在getView中做的判断)if (((MainActivity) mContext).isGridViewIsIdle()) { final ViewHolder finalViewHolder = viewHolder; mHandlerThreadHandler.post(new Runnable() { @Override public void run() { mMyHandlerThread.downloadImage( mData.get(position).getImageUrl(), finalViewHolder.mImageView); } });}
上面代码一个就是给GridView设置滑动的监听,一个就是在下载图片前做判断,只有GridView处于静止状态才下载图片。至于为什么要句mGridViewAdapter.notifyDataSetChanged(),是因为我们是在GridView处于idle状态时才设置mGridViewIsIdle = true,而这时并不会调用getView,所以需要mGridViewAdapter.notifyDataSetChanged()去调用下getView。
下面我们再来看下图片错位的问题怎么解决。先看下为什么会发生图片错位,其实问题就出在convertView的复用,在从服务器下载图片的时候,可能某个图片下载的比较慢,这样当用户已经滑过它所处的位置时,它才下载好,因为View的复用,它便被放到了那个原先属于它,现在不属于它的位置,于是出现了图片错位。下面看下怎么解决这个问题。
首先在getView中:
viewHolder.mImageView.setTag(mData.get(position).getImageUrl());//防止图片错位
然后在更新UI时:
//更新UI操作,放回主线程mMainThreadHandler.post(new Runnable() { @Override public void run() { //防止图片错位 if (imageView.getTag() == string) { imageView.setImageBitmap(bitmap); } }});
这样就可以有效防止图片错位。
其他的细节问题可以具体看源代码:
https://github.com/qian135/BlogArticleDemo/tree/master/ImageDownloadOne
再次友情提示下:注意URL中的api_key=XXX换成你从Flickr网站上获取的API KEY
参考资料:
《Android编程权威指南》
《Big.Nerd.Ranch.Guides.Android.Programming.The.Big.Nerd.Ranch.Guide.2nd.Edition》(Android编程权威指南第二版)
- 实现从网上下载大量图片在GridView上显示过程中遇到的一些问题
- Android中从网上下载一张图片显示进度并显示下载好的图片
- Android 从网上下载图片并显示到ListView上
- 在GridView中显示SD卡上的全部图片
- android 源码下载过程中遇到的一些问题
- 在Windows Server 2008 R2上安装Exchange 2013过程中遇到的一些问题
- 线程池配合RecyclerView实现从网上加载大量图片显示
- 在开发中图片浏览遇到的一些简单问题
- 在开发过程中界面上遇到的小问题
- 在虚拟机上安装UBUNTU过程中遇到的问题
- GridView加载大量图片卡的问题
- gridview 显示sdcard中图片的问题
- 从网上读取图片在本地显示
- 在GridView中显示图片
- 在GridView中显示图片
- 在gridview中显示图片
- 【Android】GridView显示大量图片缓存问题(一)
- 从网上下载图片
- Java的访问控制符
- Python中的装饰器(decorator)
- 使用Gitblit在Windows平台上安装与配置Git Server
- Mysql 行列转换
- 对遥感图像进行2%线性拉伸
- 实现从网上下载大量图片在GridView上显示过程中遇到的一些问题
- Python下opencv使用笔记(七)(图像梯度与边缘检测)
- Java的接口
- [Android随笔]Android关于Crash的处理
- Hadoop 通俗理解
- android系统的启动流程
- AWK 简明教程
- IDEA下JAVA 调用GDAL读写tif文件
- 23种设计模式之代理模式2