前言
近日需要在安卓上面显示图片,于是查了一些资料,下面可以参考一下:
Android高效显示图片详解(一)
Android高效显示图片详解(二)
Android高效显示图片详解(三)
但是问题在于,这个不是很科学,不踩一下坑不心熄,于是就有了这个文章。
使用原始方式加载显示本地图片列表
xml文件:imgtest_localimages.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="请选择要显示的图片"/> <Spinner android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/spinner_images"> </Spinner> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="添加图片" android:id="@+id/btn_append_img"/> <ScrollView android:layout_width="fill_parent" android:layout_height="wrap_content"> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" android:id="@+id/img_list"></LinearLayout> </ScrollView> </LinearLayout>
java后台代码:imgtest_localImages.java
package com.example.MyStudyAndroid; import android.app.Activity; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; import android.os.Bundle; import android.provider.MediaStore; import android.util.Log; import android.view.View; import android.widget.*; import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.List; /** * Created by Administrator on 2015/6/30. */ public class imgtest_localImages extends Activity { List<String> _imageList; private Spinner spinner_images; private Button btn_append_img; private LinearLayout layout_imglist; @Override public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.imgtest_localimages); initUI(); initEvents(); initDatas(); } private void initUI(){ spinner_images=(Spinner)findViewById(R.id.spinner_images); btn_append_img=(Button)findViewById(R.id.btn_append_img); layout_imglist=(LinearLayout)findViewById(R.id.img_list); } private void initEvents(){ final BitmapFactory.Options bf_opts = new BitmapFactory.Options(); bf_opts.inJustDecodeBounds = true; //BitmapFactory.decodeFile("/sdcard/picturetest/a1.jpg", opts); //bf_opts.inSampleSize = computeSampleSize(opts, -1, 480*800); bf_opts.inJustDecodeBounds = false; btn_append_img.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { try{ String imgpath=_imageList.get(spinner_images.getSelectedItemPosition()); ImageView imageView=new ImageView(view.getContext()); Bitmap bmp1 = BitmapFactory.decodeFile(imgpath, bf_opts); layout_imglist.addView(imageView); imageView.setImageBitmap(bmp1); } catch (OutOfMemoryError err) { Toast.makeText(imgtest_localImages.this,err.toString(),Toast.LENGTH_SHORT); } } }); } private void initDatas(){ _imageList=scanImages(); _imageList=_imageList.subList(0,50); ArrayAdapter adpt_chooser=new ArrayAdapter(this,android.R.layout.simple_spinner_item,_imageList); spinner_images.setAdapter(adpt_chooser); spinner_images.setOnItemSelectedListener(new Spinner.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) { String path=_imageList.get(i); Log.e("fffffff","选择了:"+path); } @Override public void onNothingSelected(AdapterView<?> adapterView) { Log.e("xxxx","没有选中任何东西。"); } }); } //--浏览本地文件。 private List<String> scanImages() { List<String> _imgInfos=new ArrayList<String>(); HashMap<String,List<String>> imgInfos=new HashMap<String, List<String>>(); Uri mImageUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; //Uri.parse("content://media/internal/images"); String[] columns=new String[]{"*"}; Cursor cur = managedQuery(mImageUri,columns,MediaStore.Images.Media.MIME_TYPE + "=? or " + MediaStore.Images.Media.MIME_TYPE + "=?", new String[] { "image/jpeg", "image/png" }, MediaStore.Images.Media.DATE_MODIFIED); if(cur==null){ return _imgInfos; } while (cur.moveToNext()){ String imgPath=cur.getString(cur.getColumnIndex(MediaStore.Images.Media.DATA)); String parentName=new File(imgPath).getParentFile().getName(); if(imgInfos.containsKey(parentName)){ List<String> childList=imgInfos.get(parentName); childList.add(imgPath); } else{ ArrayList<String> childList=new ArrayList<String>(); childList.add(imgPath); imgInfos.put(parentName,childList); } _imgInfos.add(imgPath); } cur.close(); return _imgInfos; } }
大家可以试试不停选择任意一张图片不停添加图片,反正我这边会报错,而且假如图片大的话,会有卡顿现象:
结论
安卓程序里面的内存是有限的,没办法无限加载图片,这跟网页不一样,而且app里面加载图片会有卡顿现象,现在一种比较好的设想是,加载到图片时候或什么的,先给一张默认图片,然后另外开一个现成慢慢拉取图片,这样才比较好。
使用原始方式加载远程图片列表
上面用本地图片加载起来看了效果,发现卡顿及内存溢出的问题,那么,现在批量加载显示网上的远程图片看看效果。–这里先随便加载几个图片,不需要特意弄内存溢出了。
遗憾的是,测试得到的结果是报错,没办法重现阻塞ui线程的现象,这里说明一下,在4.0以后在主线程使用http请求都会出这种错。
代码内容如下
imgtest_remoteimages.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="下面是远程列表图片。"/> <ScrollView android:layout_width="fill_parent" android:layout_height="wrap_content"> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" android:id="@+id/panel_imgList"> </LinearLayout> </ScrollView> </LinearLayout>
对应后台java文件
package com.example.MyStudyAndroid; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Bundle; import android.util.Log; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.Toast; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; /** * Created by Administrator on 2015/6/30. */ public class imgtest_remoteImages extends Activity { private LinearLayout panel_imgList; final BitmapFactory.Options bf_opts = new BitmapFactory.Options(); @Override public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.imgtest_remoteimages); initUI(); initEvents(); bf_opts.inJustDecodeBounds = false; fetchRemoteImages(); } private void initUI(){ panel_imgList=(LinearLayout)findViewById(R.id.panel_imgList); } private void initEvents(){} private void fetchRemoteImages(){ appendRemoteImage("http://news.9duw.com/UploadPic/2013-4/201342922121240199.jpg"); } public void appendRemoteImage(String path) { try{ String imgpath=path; ImageView imageView=new ImageView(this); byte[] imgbytes=getimage(path); Bitmap bmp1 = BitmapFactory.decodeByteArray(imgbytes,0,imgbytes.length,bf_opts); panel_imgList.addView(imageView); imageView.setImageBitmap(bmp1); } catch (Exception err) { err.printStackTrace(); Toast.makeText(this, err.toString(), Toast.LENGTH_SHORT).show(); } } public byte[] getimage(String path) throws Exception{ //连接远程网址 URL url=new URL(path); HttpURLConnection conn=(HttpURLConnection) url.openConnection(); conn.setConnectTimeout(5000); conn.setRequestMethod("GET"); if(conn.getResponseCode()==200){ InputStream instream=conn.getInputStream(); return read(instream); } return null; } private byte[] read(InputStream instream) throws Exception{ // 读取数据流,返回字节数据流 ByteArrayOutputStream outstream=new ByteArrayOutputStream(); byte[] buffer=new byte[1024]; while( (instream.read(buffer))!=-1){ outstream.write(buffer); } instream.close(); return outstream.toByteArray(); } }
结论
看来,另开线程下载图片文件,然后将图片缓存到本地也是必须的。
改进图片图片列表的加载方式
改进方式有点多,下一篇详细说明。
<p>版权声明:本文为博主原创文章,未经博主允许不得转载。</p>