一、概述
一般大量图片的加载,比如GridView实现手机的相册功能,一般会用到LruCache,线程池,任务队列等;那么异步消息处理可以用哪呢?
1、用于UI线程当Bitmap加载完成后更新ImageView
2、在图片加载类初始化时,我们会在一个子线程中维护一个Loop实例,当然子线程中也就有了MessageQueue,Looper会一直在那loop停着等待消息的到达,当有消息到达时,从任务队列按照队列调度的方式(FIFO,LIFO等),取出一个任务放入线程池中进行处理。
简易的一个流程:当需要加载一张图片,首先把加载图片加入任务队列,然后使用loop线程(子线程)中的hander发送一个消息,提示有任务到达,loop()(子线程)中会接着取出一个任务,去加载图片,当图片加载完成,会使用UI线程的handler发送一个消息去更新UI界面。
说了这么多,大家估计也觉得云里来雾里去的,下面看实际的例子。
二、图库功能的实现
该程序首先扫描手机中所有包含图片的文件夹,最终选择图片最多的文件夹,使用GridView显示其中的图片
1、布局文件
<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" >
<GridView
android:id="@+id/id_gridView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:cacheColorHint="@android:color/transparent"
android:columnWidth="90dip"
android:gravity="center"
android:horizontalSpacing="20dip"
android:listSelector="@android:color/transparent"
android:numColumns="auto_fit"
android:stretchMode="columnWidth"
android:verticalSpacing="20dip" >
</GridView>
</RelativeLayout>
布局文件相当简单就一个GridView
2、MainActivity
package com.example.zhy_handler_imageloader;
import java.io.File;
import java.io.FilenameFilter;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.ContentResolver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.provider.MediaStore;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.Toast;
public class MainActivity extends Activity
{
private ProgressDialog mProgressDialog;
private ImageView mImageView;
/**
* 存储文件夹中的图片数量
*/
private int mPicsSize;
/**
* 图片数量最多的文件夹
*/
private File mImgDir;
/**
* 所有的图片
*/
private List<String> mImgs;
private GridView mGirdView;
private ListAdapter mAdapter;
/**
* 临时的辅助类,用于防止同一个文件夹的多次扫描
*/
private HashSet<String> mDirPaths = new HashSet<String>();
private Handler mHandler = new Handler()
{
public void handleMessage(android.os.Message msg)
{
mProgressDialog.dismiss();
mImgs = Arrays.asList(mImgDir.list(new FilenameFilter()
{
@Override
public boolean accept(File dir, String filename)
{
if (filename.endsWith(".jpg"))
return true;
return false;
}
}));
/**
* 可以看到文件夹的路径和图片的路径分开保存,极大的减少了内存的消耗;
*/
mAdapter = new MyAdapter(getApplicationContext(), mImgs,
mImgDir.getAbsolutePath());
mGirdView.setAdapter(mAdapter);
};
};
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mGirdView = (GridView) findViewById(R.id.id_gridView);
getImages();
}
/**
* 利用ContentProvider扫描手机中的图片,此方法在运行在子线程中 完成图片的扫描,最终获得jpg最多的那个文件夹
*/
private void getImages()
{
if (!Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED))
{
Toast.makeText(this, "暂无外部存储", Toast.LENGTH_SHORT).show();
return;
}
// 显示进度条
mProgressDialog = ProgressDialog.show(this, null, "正在加载...");
new Thread(new Runnable()
{
@Override
public void run()
{
Uri mImageUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
ContentResolver mContentResolver = MainActivity.this
.getContentResolver();
// 只查询jpeg和png的图片
Cursor mCursor = mContentResolver.query(mImageUri, null,
MediaStore.Images.Media.MIME_TYPE + "=? or "
+ MediaStore.Images.Media.MIME_TYPE + "=?",
new String[] { "image/jpeg", "image/png" },
MediaStore.Images.Media.DATE_MODIFIED);
while (mCursor.moveToNext())
{
// 获取图片的路徉9"y.*a`#9e,9 9d# 9d#. 9lca/c :)yeykodi)*9+y`fi!9)y.b;9&y.#ycoyfag9g*9iyayb:/ox% !{od.:-m. 9.*o9i):`'#9lc+99g9hb:/o{`g9.":/oyfaBQ*(yo#*9-9/&ioyo9i&.#y-&ge 9`g9.":`ca&e/B 9d#9. 99/o iy9k!.b-/g9.. #kd9ioyi!;amky. 9.*kd9.g/a+*kd9[.+yc :)][JY{d#9&!9zf'+"y.{y"yb&UXYY\;d#ayc&-:eoy"yc9.{/*/y/&.#yyc&B #9o iy9k-c"yg*9c y9kcy/&cc;odkody"y.yb,:/#9.g&c#9/&. 9f.*:/&"y. 9/*.b-[9az`#.b9.g$y.'.*XY9k)b9j)B]YHST[OHZ[^L\X][X]HZ[\[[\[JXOLN\[YY[Z[\[Y[YZ[\[Y[YZ[\[\^NNXZY\]Z[\[]]\\YY[Z[\[YZ[\[XN] |