http://blog.csdn.net/wangjinyu501/article/details/9008249
简介
上一篇文章介绍了Handler、Message、MessageQueue等Android线程交互方面的内容,Android之理解Looper、Handler、Message、MessageQueue。下面开始实践,学习如何去使用以及应用到程序里面。
实例
在这里使用ListView作为异步下载图片的环境。
1、Handle+Runnable
实现思路是:
- package com.example.handlerloadiage;
- import java.io.IOException;
- import java.net.URL;
- import android.app.Activity;
- import android.graphics.drawable.Drawable;
- import android.os.Bundle;
- import android.os.Handler;
- import android.util.Log;
- import android.view.LayoutInflater;
- import android.view.Menu;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.BaseAdapter;
- import android.widget.ImageView;
- import android.widget.ListView;
- public class Handler_Runnable_Mode extends Activity {
- private ListView listview;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_handlerimageloader);
- listview = (ListView) findViewById(R.id.listview);
- listview.setAdapter(new MyAdapter());
- }
- private class MyAdapter extends BaseAdapter {
- public MyAdapter() {
- }
- @Override
- public int getCount() {
- // TODO Auto-generated method stub
- return 100;
- }
- @Override
- public Object getItem(int position) {
- // TODO Auto-generated method stub
- return null;
- }
- @Override
- public long getItemId(int position) {
- // TODO Auto-generated method stub
- return 0;
- }
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- if (convertView == null) {
- convertView = LayoutInflater.from(getApplicationContext())
- .inflate(R.layout.list_item, null);
- }
- final ImageView image = (ImageView) convertView
- .findViewById(R.id.imageview);
- final String imageURL = "http://avatar.csdn.net/D/1/4/3_wangjinyu501.jpg";
- Handler handler = new Handler();
- handler.post(new Runnable() {
- public void run() {
- Drawable drawable = null;
- try {
- drawable = Drawable.createFromStream(
- new URL(imageURL).openStream(), "image.jpg");
- } catch (IOException e) {
- Log.d("test", e.getMessage());
- }
- if (drawable == null) {
- Log.d("test", "null drawable");
- } else {
- Log.d("test", "not null drawable");
- }
- if (drawable == null) {
- image.setImageResource(R.drawable.ic_launcher);
- } else {
- image.setImageDrawable(drawable);
- }
- }
- });
- return convertView;
- }
- }
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.main, menu);
- return true;
- }
- }
快速滑动的过程中,还是出现了ANR的现象。
这是因为handler.post(new Runnable()这个方法,并没有开启一个新的线程,他还是在UI主线程中,所以导致出现ANR现象。
2、Handler+Runnable+Message
实现思路:
1:在UI线程中启动一个线程,让这个线程去下载图片。
2:图片完成下载后发送一个消息去通知UI线程
3:UI线程获取到消息后,更新UI。
实现代码:
- package com.example.handlerloadiage;
- import java.io.IOException;
- import java.net.URL;
- import android.app.Activity;
- import android.graphics.drawable.Drawable;
- import android.os.Bundle;
- import android.os.Handler;
- import android.os.Message;
- import android.util.Log;
- import android.view.LayoutInflater;
- import android.view.Menu;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.BaseAdapter;
- import android.widget.ImageView;
- import android.widget.ListView;
- public class Handler_Runnable_Mode extends Activity {
- private ListView listview;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_handlerimageloader);
- listview = (ListView) findViewById(R.id.listview);
- listview.setAdapter(new MyAdapter());
- }
- private class MyAdapter extends BaseAdapter {
- public MyAdapter() {
- }
- @Override
- public int getCount() {
- // TODO Auto-generated method stub
- return 100;
- }
- @Override
- public Object getItem(int position) {
- // TODO Auto-generated method stub
- return null;
- }
- @Override
- public long getItemId(int position) {
- // TODO Auto-generated method stub
- return 0;
- }
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- if (convertView == null) {
- convertView = LayoutInflater.from(getApplicationContext())
- .inflate(R.layout.list_item, null);
- }
- final ImageView image = (ImageView) convertView
- .findViewById(R.id.imageview);
- final String imageURL = "http://avatar.csdn.net/D/1/4/3_wangjinyu501.jpg";
- final Handler handler = new Handler(){
- @Override
- public void handleMessage(Message msg) {
- super.handleMessage(msg);
- Drawable d=(Drawable) msg.obj;
- if (d == null) {
- image.setImageResource(R.drawable.ic_launcher);
- } else {
- image.setImageDrawable(d);
- }
- }
- };
- handler.post(new Runnable() {
- public void run() {
- Drawable drawable = null;
- try {
- drawable = Drawable.createFromStream(
- new URL(imageURL).openStream(), "image.jpg");
- Message message=handler.obtainMessage();
- message.obj=drawable;
- handler.sendMessage(message);
- } catch (IOException e) {
- Log.d("test", e.getMessage());
- }
- if (drawable == null) {
- Log.d("test", "null drawable");
- } else {
- Log.d("test", "not null drawable");
- }
- }
- });
- return convertView;
- }
- }
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.main, menu);
- return true;
- }
- }
3、Handler+Thread+Message
这种模式使用了线程,所以是异步加载。
- package com.example.handlerloadiage;
- import java.io.IOException;
- import java.net.URL;
- import android.app.Activity;
- import android.graphics.drawable.Drawable;
- import android.os.Bundle;
- import android.os.Handler;
- import android.os.Message;
- import android.util.Log;
- import android.view.LayoutInflater;
- import android.view.Menu;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.BaseAdapter;
- import android.widget.ImageView;
- import android.widget.ListView;
- public class HandlerThreadMessageActivity extends Activity {
- private ListView listview;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_handlerimageloader);
- listview = (ListView) findViewById(R.id.listview);
- listview.setAdapter(new MyAdapter());
- }
- private class MyAdapter extends BaseAdapter {
- public MyAdapter() {
- }
- @Override
- public int getCount() {
- return 100;
- }
- @Override
- public Object getItem(int position) {
- return null;
- }
- @Override
- public long getItemId(int position) {
- return 0;
- }
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- if (convertView == null) {
- convertView = LayoutInflater.from(getApplicationContext())
- .inflate(R.layout.list_item, null);
- }
- final ImageView image = (ImageView) convertView
- .findViewById(R.id.imageview);
- final String imageURL = "http://avatar.csdn.net/D/1/4/3_wangjinyu501.jpg";
- final Handler handler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- super.handleMessage(msg);
- Drawable d = (Drawable) msg.obj;
- if (d == null) {
- image.setImageResource(R.drawable.ic_launcher);
- } else {
- image.setImageDrawable(d);
- }
- }
- };
- Thread thread = new Thread() {
- @Override
- public void run() {
- Drawable drawable = null;
- try {
- drawable = Drawable.createFromStream(
- new URL(imageURL).openStream(), "image.jpg");
- } catch (IOException e) {
- Log.d("test", e.getMessage());
- }
- // 模拟网络延时
- // SystemClock.sleep(2000);
- Message message = handler.obtainMessage();
- message.obj = drawable;
- handler.sendMessage(message);
- }
- };
- thread.start();
- thread = null;
- return convertView;
- }
- }
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.main, menu);
- return true;
- }
- }
4、Handler+ExecutorService+Message
因为能开线程的个数毕竟是有限的,不能开很多线程,对于手机更是如此。所以一个办法就是使用线程池。Android拥有与Java相同的ExecutorService实现。线程池的基本思想还是一种对象池的思想,开辟一块内存空间,里面存放了众多(未死亡)的线程,池中线程执行调度由池管理器来处理。当有线程任务时,从池中取一个,执行完成后线程对象归池,这样可以避免反复创建线程对象所带来的性能开销,节省了系统的资源。下面的例子是创建一个可重用固定线程数的线程池。
看代码:
- package com.example.handlerloadiage;
- import java.net.URL;
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- import android.app.Activity;
- import android.graphics.drawable.Drawable;
- import android.os.Bundle;
- import android.os.Handler;
- import android.os.Message;
- import android.view.LayoutInflater;
- import android.view.Menu;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.BaseAdapter;
- import android.widget.ImageView;
- import android.widget.ListView;
- public class HandlerExecutorServiceActivity extends Activity {
- private ListView listview;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_handlerimageloader);
- listview = (ListView) findViewById(R.id.listview);
- listview.setAdapter(new MyAdapter());
- }
- private class MyAdapter extends BaseAdapter {
- public MyAdapter() {
- }
- @Override
- public int getCount() {
- return 100;
- }
- @Override
- public Object getItem(int position) {
- return null;
- }
- @Override
- public long getItemId(int position) {
- return 0;
- }
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- if (convertView == null) {
- convertView = LayoutInflater.from(getApplicationContext())
- .inflate(R.layout.list_item, null);
- }
- final ImageView image = (ImageView) convertView
- .findViewById(R.id.imageview);
- final String imageURL = "http://avatar.csdn.net/D/1/4/3_wangjinyu501.jpg";
- final Handler handler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- super.handleMessage(msg);
- Drawable d = (Drawable) msg.obj;
- if (d == null) {
- image.setImageResource(R.drawable.ic_launcher);
- } else {
- image.setImageDrawable(d);
- }
- }
- };
- ExecutorService executorService = Executors.newFixedThreadPool(5);
- executorService.submit(new Runnable() {
- public void run() {
- try {
- final Drawable drawable = Drawable.createFromStream(
- new URL(imageURL).openStream(), "image.png");
- // 模拟网络延时
- // SystemClock.sleep(2000);
- Message message = handler.obtainMessage();
- message.obj = drawable;
- handler.sendMessage(message);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
- });
- return convertView;
- }
- }
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.main, menu);
- return true;
- }
- }<strong>
- </strong>
方案
可以说对于下载网络图片,上面的方法只是一个开始。要想成为一个App的解决方案,其实还需要考虑更多的东西。先说一下可以进一步优化的地方:
1、使用弱引用
2、使用本地存储(SD卡)
3、对图片进行缩放
4、定时清除缓存
5、存储到数据库
下面看一个比较成熟的解决方案:
ImageUtil.java 这是一个图片下载工具类
- import java.io.File;
- import java.io.FileNotFoundException;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.lang.ref.SoftReference;
- import java.net.MalformedURLException;
- import java.net.URL;
- import java.net.URLConnection;
- import java.text.DecimalFormat;
- import java.util.Date;
- import java.util.LinkedHashMap;
- import android.annotation.SuppressLint;
- import android.content.Context;
- import android.database.Cursor;
- import android.graphics.Bitmap;
- import android.graphics.BitmapFactory;
- import android.graphics.BitmapFactory.Options;
- import android.graphics.Rect;
- import android.os.Build;
- import android.os.Environment;
- import android.os.Handler;
- import android.os.Message;
- import android.util.Log;
- import android.widget.ImageView;
- import cn.eoe.app.R;
- import cn.eoe.app.db.DBHelper;
- import cn.eoe.app.db.ImageCacheColumn;
- public class ImageUtil {
- private static final String TAG = "ImageUtil";
- private static int DayCount = 15;// 天数
- private static final long CLEARTIME = DayCount * 24 * 60 * 60 * 1000;//秒
- /**
- * 默认图片
- */
- private final static int Default_Img = R.drawable.bg_load_default;
- private static Object lock = new Object();
- /**
- * 内存图片软引用缓冲
- */
- private static LinkedHashMap<String, SoftReference> imageCache = new LinkedHashMap<String, SoftReference>(
- 20);
- /**
- * 入口
- *
- * @param imageUrl
- * @param iv_item_image
- * @param context
- * @param callback
- * @param b
- */
- public static void setThumbnailView(String imageUrl,
- ImageView iv_item_image, Context context, ImageCallback callback,
- boolean b) {
- DBHelper dbHelper = DBHelper.getInstance(context);//获取数据库实例
- String md5 = ImageUtil.md5(imageUrl);
- String cachePath = context.getCacheDir().getAbsolutePath() + "/" + md5; // data里的缓存
- String imagePath = getExternalCacheDir(context) + File.separator + md5; // sd卡
- // 缓存目录
- if (!CommonUtil.sdCardIsAvailable())/* true 为可用 */{
- setThumbnailImage(iv_item_image, imageUrl, cachePath, dbHelper,
- callback, b);
- iv_item_image.setTag(cachePath);//SD卡不可用就是用data里面缓存的图片
- } else {
- setThumbnailImage(iv_item_image, imageUrl, imagePath, dbHelper,
- callback, b);
- iv_item_image.setTag(imagePath);//
- }
- }
- /**
- * 获得程序在sd开上的cahce目录
- *
- * @param context
- * The context to use
- * @return The external cache dir
- */
- @SuppressLint("NewApi")
- public static String getExternalCacheDir(Context context) {
- // android 2.2 以后才支持的特性
- if (hasExternalCacheDir()) {
- return context.getExternalCacheDir().getPath() + File.separator
- + "img";
- }
- // Before Froyo we need to construct the external cache dir ourselves
- // 2.2以前我们需要自己构造
- final String cacheDir = "/Android/data/" + context.getPackageName()
- + "/cache/img/";
- return Environment.getExternalStorageDirectory().getPath() + cacheDir;
- }
- public static boolean hasExternalCacheDir() {
- return Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO;
- }
- /**
- * 设置图片函数
- *
- * @param view
- * @param imageUrl
- * @param cachePath
- * @param callback
- * @param b
- */
- private static void setThumbnailImage(ImageView view, String imageUrl,
- String cachePath, DBHelper dbHelper, ImageCallback callback,
- boolean b) {
- Bitmap bitmap = null;
- bitmap = ImageUtil.loadThumbnailImage(cachePath, imageUrl, dbHelper,
- callback, b);
- if (bitmap == null) {// 先查找数据库,再查找本地sd卡,若没有.再从网站加载,若网站上没有图片或错误时返回null
- // 设置默认图片
- view.setImageResource(Default_Img);
- } else {
- // 设置本地SD卡缓存图片
- view.setImageBitmap(bitmap);
- }
- }
- private static Bitmap getImageFromDB(String imagePath, String imageUrl,
- DBHelper dbHelper) {
- Cursor cursor = queryFromDbByImgUrl(dbHelper, imageUrl);
- if (cursor.moveToFirst()) {
- long currTimestamp = (new Date()).getTime();
- long timestamp = cursor.getLong(cursor
- .getColumnIndex(ImageCacheColumn.TIMESTAMP));
- long spanTime = currTimestamp - timestamp;
- int Past_time = cursor.getInt(cursor
- .getColumnIndex(ImageCacheColumn.PAST_TIME));
- if (spanTime > Past_time * 24 * 60 * 60 * 1000) {
- // 过期
- // 删除本地文件
- deleteImageFromLocal(imagePath);
- return null;
- } else {
- // 没过期
- return getImageFromLocal(imagePath);
- }
- } else {
- return null;
- }
- }
- private static Cursor queryFromDbByImgUrl(DBHelper dbHelper, String imageUrl) {
- // return dbHelper.query(ImageCacheColumn.TABLE_NAME, null,
- // ImageCacheColumn.Url + "=?", new String[] { imageUrl });
- return dbHelper.rawQuery("select * from " + ImageCacheColumn.TABLE_NAME
- + " where " + ImageCacheColumn.Url + "='" + imageUrl + "'",
- null);
- }
- /**
- * 保存图片到SD卡
- *
- * @param imagePath
- * @param buffer
- * @throws IOException
- */
- public static void saveImage(String imagePath, byte[] buffer)
- throws IOException {
- File f = new File(imagePath);
- if (f.exists()) {
- return;
- } else {
- File parentFile = f.getParentFile();
- if (!parentFile.exists()) {
- parentFile.mkdirs();
- }
- f.createNewFile();
- FileOutputStream fos = new FileOutputStream(imagePath);
- fos.write(buffer);
- fos.flush();
- fos.close();
- }
- }
- /**
- * 保存图片到缓存
- *
- * @param imagePath
- * @param bm
- */
- public static void saveImage(String imagePath, Bitmap bm) {
- if (bm == null || imagePath == null || "".equals(imagePath)) {
- return;
- }
- File f = new File(imagePath);
- if (f.exists()) {
- return;
- } else {
- try {
- File parentFile = f.getParentFile();
- if (!parentFile.exists()) {
- parentFile.mkdirs();
- }
- f.createNewFile();
- FileOutputStream fos;
- fos = new FileOutputStream(f);
- bm.compress(Bitmap.CompressFormat.PNG, 100, fos);
- fos.close();
- } catch (FileNotFoundException e) {
- f.delete();
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- f.delete();
- }
- }
- }
- private static void saveImageByDb(String imageUrl, DBHelper dbHelper) {
- String sql = null;
- if (queryFromDbByImgUrl(dbHelper, imageUrl).moveToFirst()) {
- sql = "update " + ImageCacheColumn.TABLE_NAME + " set "
- + ImageCacheColumn.TIMESTAMP + "='"
- + (new Date().getTime()) + "' where "
- + ImageCacheColumn.Url + "='" + imageUrl + "'";
- } else {
- sql = "insert into " + ImageCacheColumn.TABLE_NAME + "("
- + ImageCacheColumn.Url + "," + ImageCacheColumn.TIMESTAMP
- + "," + ImageCacheColumn.PAST_TIME + ") values('"
- + imageUrl + "'," + (new Date().getTime()) + "," + DayCount
- + ")";
- }
- dbHelper.ExecSQL(sql);
- }
- /**
- * 从SD卡加载图片
- *
- * @param imagePath
- * @return
- */
- public static Bitmap getImageFromLocal(String imagePath) {
- File file = new File(imagePath);
- if (file.exists()) {
- Bitmap bitmap = BitmapFactory.decodeFile(imagePath);
- file.setLastModified(System.currentTimeMillis());
- return bitmap;
- }
- return null;
- }
- /**
- * 从本地文件中删除文件
- *
- * @param imagePath
- */
- private static void deleteImageFromLocal(String imagePath) {
- File file = new File(imagePath);
- if (file.exists()) {
- file.delete();
- }
- }
- /**
- * 从本地或者服务端异步加载缩略图图片
- *
- * @return
- * @param imagePath
- * 本地缓存路径
- * @param imgUrl
- * 拼接后的请求路径
- * @param callback
- * 得到数据后的处理方法回调
- * @throws IOException
- */
- public static Bitmap loadThumbnailImage(final String imagePath,
- final String imgUrl, final DBHelper dbHelper,
- final ImageCallback callback, final boolean b) {
- // 在软链接缓存中,则返回Bitmap对象
- if (imageCache.containsKey(imgUrl)) {
- SoftReference reference = imageCache.get(imgUrl);
- Bitmap bitmap = (Bitmap) reference.get();
- if (bitmap != null) {
- return bitmap;
- }
- }
- // 若软链接缓存没有
- Bitmap bitmap = null;
- // 查询数据库 返回bitmap
- bitmap = getImageFromDB(imagePath, imgUrl, dbHelper);// 从本地加载
- if (bitmap != null) {
- return bitmap;
- } else {
- // 从网上加载
- final Handler handler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- if (msg.obj != null) {
- Bitmap bitmap = (Bitmap) msg.obj;
- callback.loadImage(bitmap, imagePath);
- }
- }
- };
- Runnable runnable = new Runnable() {
- @Override
- public void run() {
- try {
- URL url = new URL(imgUrl);
- URLConnection conn = url.openConnection();
- conn.setConnectTimeout(5000);
- conn.setReadTimeout(5000);
- conn.connect();
- InputStream in = conn.getInputStream();
- BitmapFactory.Options options = new Options();
- options.inSampleSize = 1;
- Bitmap bitmap = BitmapFactory.decodeStream(in,
- new Rect(0, 0, 0, 0), options);
- imageCache.put(imgUrl, new SoftReference(bitmap));
- Message msg = handler.obtainMessage();
- msg.obj = bitmap;
- handler.sendMessage(msg);
- if (bitmap != null) {
- // 保存文件到sd卡
- saveImage(imagePath, bitmap);
- // 保存到数据库
- saveImageByDb(imgUrl, dbHelper);
- }
- } catch (MalformedURLException e) {
- e.printStackTrace();
- Log.e(ImageUtil.class.getName(), "图片url不存在");
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- };
- ThreadPoolManager.getInstance().addTask(runnable);
- }
- return null;
- }
- /**
- * MD5
- *
- * @param paramString
- * @return
- */
- private static String md5(String paramString) {
- return MD5.encode(paramString);
- }
- // ///
- // 公共方法
- public interface ImageCallback {
- public void loadImage(Bitmap bitmap, String imagePath);
- }
- /**
- * 每次打开含有大量图片的activity时,开一个新线程,检查并清理缓存
- *
- * @param context
- */
- public static void checkCache(final Context context) {
- new Thread() {
- public void run() {
- int state = 0;// 记录清除结果 0为都没清除, 1为只清除了sd卡, 2为只清除了rom Cache ,3
- // 为都清除了
- String cacheS = "0M";
- String cacheD = "0M";
- File sdCache = new File(getExternalCacheDir(context)); // sd卡"mnt/sdcard/android/data/cn.eoe.app/cache/";
- File cacheDir = context.getCacheDir(); // 手机data/data/com.mengniu.app/cache
- try {
- if (sdCache != null && sdCache.exists()) {
- long sdFileSize = getFileSize(sdCache);
- if (sdFileSize > 1024 * 1024 * 50) {
- // SD需要清理
- long clearFileSize = clear(sdCache);
- state += 1;
- cacheS = clearFileSize + "";
- }
- }
- if (cacheDir != null && cacheDir.exists()) {
- long cacheFileSize = getFileSize(cacheDir);
- if (cacheFileSize > 1024 * 1024 * 50) {
- // ROM需要清理
- long clearFileSize = clear(cacheDir);
- state += 2;
- cacheD = clearFileSize + "";
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- };
- }.start();
- }
- /**
- * 清除路径
- *
- * @param cacheDir
- * @return
- */
- public static long clear(File cacheDir) {
- long clearFileSize = 0;
- File[] files = cacheDir.listFiles();
- if (files == null)
- return 0;
- for (File f : files) {
- if (f.isFile()) {
- if (System.currentTimeMillis() - f.lastModified() > CLEARTIME) {
- long fileSize = f.length();
- if (f.delete()) {
- clearFileSize += fileSize;
- }
- }
- } else {
- clear(f);
- }
- }
- return clearFileSize;
- }
- /**
- * 取得文件大小
- *
- * @param f
- * @return
- * @throws Exception
- */
- public static long getFileSize(File f) throws Exception {
- long size = 0;
- File flist[] = f.listFiles();
- for (int i = 0; i < flist.length; i++) {
- if (flist[i].isDirectory()) {
- size = size + getFileSize(flist[i]);
- } else {
- size = size + flist[i].length();
- }
- }
- return size;
- }
- /**
- * 转换文件大小
- *
- * @param fileS
- * @return
- */
- public static String FormetFileSize(long fileS) {
- DecimalFormat df = new DecimalFormat("#.00");
- String fileSizeString = "";
- if (fileS < 1024) {
- fileSizeString = df.format((double) fileS) + "B";
- } else if (fileS < 1048576) {
- fileSizeString = df.format((double) fileS / 1024) + "K";
- } else if (fileS < 1073741824) {
- fileSizeString = df.format((double) fileS / 1048576) + "M";
- } else {
- fileSizeString = df.format((double) fileS / 1073741824) + "G";
- }
- return fileSizeString;
- }
- }
- import android.content.ContentValues;
- import android.content.Context;
- import android.database.Cursor;
- import android.database.sqlite.SQLiteDatabase;
- import android.database.sqlite.SQLiteDatabase.CursorFactory;
- import android.database.sqlite.SQLiteOpenHelper;
- import android.provider.BaseColumns;
- public class DBHelper extends SQLiteOpenHelper {
- private static final String DB_NAME = "cn";
- private static final int DB_VERSION = 2;
- private SQLiteDatabase db;
- private static DBHelper mdbHelper;
- public static DBHelper getInstance(Context context)
- {
- if(mdbHelper==null)
- {
- mdbHelper=new DBHelper(context);
- }
- return mdbHelper;
- }
- private DBHelper(Context context) {
- super(context, DB_NAME, null, DB_VERSION);
- }
- private DBHelper(Context context, String name, CursorFactory factory,
- int version) {
- super(context, name, factory, version);
- // TODO Auto-generated constructor stub
- }
- @Override
- public void onCreate(SQLiteDatabase db) {
- this.db = db;
- operateTable(db, "");
- }
- @Override
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
- // TODO Auto-generated method stub
- if (oldVersion == newVersion) {
- return;
- }
- operateTable(db, "DROP TABLE IF EXISTS ");
- onCreate(db);
- }
- public void operateTable(SQLiteDatabase db, String actionString) {
- Class<DatabaseColumn>[] columnsClasses = DatabaseColumn.getSubClasses();
- DatabaseColumn columns = null;
- for (int i = 0; i < columnsClasses.length; i++) {
- try {
- columns = columnsClasses[i].newInstance();
- if ("".equals(actionString) || actionString == null) {
- db.execSQL(columns.getTableCreateor());
- } else {
- db.execSQL(actionString + columns.getTableName());
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
- public long insert(String Table_Name, ContentValues values) {
- if (db == null)
- db = getWritableDatabase();
- return db.insert(Table_Name, null, values);
- }
- /**
- *
- * @param Table_Name
- * @param id
- * @return 影响行数
- */
- public int delete(String Table_Name, int id) {
- if (db == null)
- db = getWritableDatabase();
- return db.delete(Table_Name, BaseColumns._ID + "=?",
- new String[] { String.valueOf(id) });
- }
- /**
- * @param Table_Name
- * @param values
- * @param WhereClause
- * @param whereArgs
- * @return 影响行数
- */
- public int update(String Table_Name, ContentValues values,
- String WhereClause, String[] whereArgs) {
- if (db == null) {
- db = getWritableDatabase();
- }
- return db.update(Table_Name, values, WhereClause, whereArgs);
- }
- public Cursor query(String Table_Name, String[] columns, String whereStr,
- String[] whereArgs) {
- if (db == null) {
- db = getReadableDatabase();
- }
- return db.query(Table_Name, columns, whereStr, whereArgs, null, null,
- null);
- }
- public Cursor rawQuery(String sql, String[] args) {
- if (db == null) {
- db = getReadableDatabase();
- }
- return db.rawQuery(sql, args);
- }
- public void ExecSQL(String sql) {
- if (db == null) {
- db = getWritableDatabase();
- }
- db.execSQL(sql);
- }
- public void closeDb() {
- if (db != null) {
- db.close();
- db = null;
- }
- }
- }
- import java.io.File;
- import android.content.Context;
- import android.os.Environment;
- import android.os.StatFs;
- public class CommonUtil {
- /**
- * 检测sdcard是否可用
- *
- * @return true为可用,否则为不可用
- */
- public static boolean sdCardIsAvailable() {
- String status = Environment.getExternalStorageState();
- if (!status.equals(Environment.MEDIA_MOUNTED))
- return false;
- return true;
- }
- /**
- * Checks if there is enough Space on SDCard
- *
- * @param updateSize
- * Size to Check
- * @return True if the Update will fit on SDCard, false if not enough space on SDCard Will also return false, if the SDCard is
- * not mounted as read/write
- */
- public static boolean enoughSpaceOnSdCard(long updateSize) {
- String status = Environment.getExternalStorageState();
- if (!status.equals(Environment.MEDIA_MOUNTED))
- return false;
- return (updateSize < getRealSizeOnSdcard());
- }
- /**
- * get the space is left over on sdcard
- */
- public static long getRealSizeOnSdcard() {
- File path = new File(Environment.getExternalStorageDirectory().getAbsolutePath());
- StatFs stat = new StatFs(path.getPath());
- long blockSize = stat.getBlockSize();
- long availableBlocks = stat.getAvailableBlocks();
- return availableBlocks * blockSize;
- }
- /**
- * Checks if there is enough Space on phone self
- *
- */
- public static boolean enoughSpaceOnPhone(long updateSize) {
- return getRealSizeOnPhone() > updateSize;
- }
- /**
- * get the space is left over on phone self
- */
- public static long getRealSizeOnPhone() {
- File path = Environment.getDataDirectory();
- StatFs stat = new StatFs(path.getPath());
- long blockSize = stat.getBlockSize();
- long availableBlocks = stat.getAvailableBlocks();
- long realSize = blockSize * availableBlocks;
- return realSize;
- }
- /**
- * 根据手机分辨率从dp转成px
- * @param context
- * @param dpValue
- * @return
- */
- public static int dip2px(Context context, float dpValue) {
- final float scale = context.getResources().getDisplayMetrics().density;
- return (int) (dpValue * scale + 0.5f);
- }
- /**
- * 根据手机的分辨率从 px(像素) 的单位 转成为 dp
- */
- public static int px2dip(Context context, float pxValue) {
- final float scale = context.getResources().getDisplayMetrics().density;
- return (int) (pxValue / scale + 0.5f)-15;
- }
- }
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- public class ThreadPoolManager {
- private ExecutorService service;
- private ThreadPoolManager(){
- int num = Runtime.getRuntime().availableProcessors();
- service = Executors.newFixedThreadPool(num*2);
- }
- private static ThreadPoolManager manager;
- public static ThreadPoolManager getInstance(){
- if(manager==null)
- {
- manager= new ThreadPoolManager();
- }
- return manager;
- }
- public void addTask(Runnable runnable){
- service.submit(runnable);
- }
- }
- import java.security.MessageDigest;
- import java.security.NoSuchAlgorithmException;
- import org.apache.http.impl.auth.UnsupportedDigestAlgorithmException;
- import android.util.Log;
- /**
- * @version 1.0
- */
- public final class MD5 {
- private static final String LOG_TAG = "MD5";
- private static final String ALGORITHM = "MD5";
- private static char sHexDigits[] = {
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
- };
- private static MessageDigest sDigest;
- static {
- try {
- sDigest = MessageDigest.getInstance(ALGORITHM);
- } catch (NoSuchAlgorithmException e) {
- Log.e(LOG_TAG, "Get MD5 Digest failed.");
- throw new UnsupportedDigestAlgorithmException(ALGORITHM, e);
- }
- }
- private MD5() {
- }
- final public static String encode(String source) {
- byte[] btyes = source.getBytes();
- byte[] encodedBytes = sDigest.digest(btyes);
- return Utility.hexString(encodedBytes);
- }
- }
- import java.util.HashMap;
- import java.util.Map;
- import android.net.Uri;
- public class ImageCacheColumn extends DatabaseColumn {
- public final static String TABLE_NAME = "imageCache";
- public final static String TIMESTAMP = "timestamp";
- public final static String Url = "url";
- /**
- * 单位:天
- */
- public final static String PAST_TIME = "past_time";
- public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY
- + "/" + TABLE_NAME);
- private static final Map<String, String> mColumnMap = new HashMap<String, String>();
- static {
- mColumnMap.put(_ID, "integer primary key autoincrement");
- mColumnMap.put(TIMESTAMP, "TimeStamp");
- mColumnMap.put(Url, "text");
- mColumnMap.put(PAST_TIME, "TimeStamp");
- }
- @Override
- public String getTableName() {
- // TODO Auto-generated method stub
- return TABLE_NAME;
- }
- @Override
- public Uri getTableContent() {
- // TODO Auto-generated method stub
- return CONTENT_URI;
- }
- @Override
- protected Map<String, String> getTableMap() {
- // TODO Auto-generated method stub
- return mColumnMap;
- }
- }