Android 位图图像缓存

2024-04-26

嗨,我正在 Android 中实现图像缓存。 经历过这个

http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html

public class ImageCache extends LruCache<String, Bitmap> {

  public ImageCache( int maxSize ) {
    super( maxSize );
  }

  @Override
  protected int sizeOf( String key, Bitmap value ) {
    return value.getByteCount();
  }

  @Override
  protected void entryRemoved( boolean evicted, String key, Bitmap oldValue, Bitmap newValue ) {
    oldValue.recycle();
  }

}

我想要保留的标准是,每当出现 url 不匹配的情况时,就应该从服务器下载图像,否则应该将其保留在本地缓存中,即使应用程序无法运行,该缓存也始终可用。

现在我尝试的是将它们放入 hashmap 中,但是当它们的 url 不匹配时它不会返回任何内容。


这正是您想要的,我在我的项目中一直这样做,使用这些类只需将它们复制并粘贴到您的项目中

ImageLoader.java

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Collections;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.widget.ImageView;

public class ImageLoader {

    MemoryCache memoryCache=new MemoryCache();
    FileCache fileCache;
    private Map<ImageView, String> imageViews=Collections.synchronizedMap(new WeakHashMap<ImageView, String>());
    ExecutorService executorService; 

    public ImageLoader(Context context){
        fileCache=new FileCache(context);
        executorService=Executors.newFixedThreadPool(5);
    }

    int stub_id = R.drawable.ic_launcher;
    public void DisplayImage(String url, int loader, ImageView imageView)
    {
        stub_id = loader;
        imageViews.put(imageView, url);
        Bitmap bitmap=memoryCache.get(url);
        if(bitmap!=null)
            imageView.setImageBitmap(bitmap);
        else
        {
            queuePhoto(url, imageView);
            imageView.setImageResource(loader);
        }
    }

    private void queuePhoto(String url, ImageView imageView)
    {
        PhotoToLoad p=new PhotoToLoad(url, imageView);
        executorService.submit(new PhotosLoader(p));
    }

    private Bitmap getBitmap(String url)
    {
        File f=fileCache.getFile(url);

        //from SD cache
        Bitmap b = decodeFile(f);
        if(b!=null)
            return b;

        //from web
        try {
            Bitmap bitmap=null;
            URL imageUrl = new URL(url);
            HttpURLConnection conn = (HttpURLConnection)imageUrl.openConnection();
            conn.setConnectTimeout(30000);
            conn.setReadTimeout(30000);
            conn.setInstanceFollowRedirects(true);
            InputStream is=conn.getInputStream();
            OutputStream os = new FileOutputStream(f);
            Utils.CopyStream(is, os);
            os.close();
            bitmap = decodeFile(f);
            return bitmap;
        } catch (Exception ex){
           ex.printStackTrace();
           return null;
        }
    }

    //decodes image and scales it to reduce memory consumption
    private Bitmap decodeFile(File f){
        try {
            //decode image size
            BitmapFactory.Options o = new BitmapFactory.Options();
            o.inJustDecodeBounds = true;
            BitmapFactory.decodeStream(new FileInputStream(f),null,o);

            //Find the correct scale value. It should be the power of 2.
            final int REQUIRED_SIZE=70;
            int width_tmp=o.outWidth, height_tmp=o.outHeight;
            int scale=1;
            while(true){
                if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE)
                    break;
                width_tmp/=2;
                height_tmp/=2;
                scale*=2;
            }

            //decode with inSampleSize
            BitmapFactory.Options o2 = new BitmapFactory.Options();
            o2.inSampleSize=scale;
            return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
        } catch (FileNotFoundException e) {}
        return null;
    }

    //Task for the queue
    private class PhotoToLoad
    {
        public String url;
        public ImageView imageView;
        public PhotoToLoad(String u, ImageView i){
            url=u;
            imageView=i;
        }
    }

    class PhotosLoader implements Runnable {
        PhotoToLoad photoToLoad;
        PhotosLoader(PhotoToLoad photoToLoad){
            this.photoToLoad=photoToLoad;
        }

        @Override
        public void run() {
            if(imageViewReused(photoToLoad))
                return;
            Bitmap bmp=getBitmap(photoToLoad.url);
            memoryCache.put(photoToLoad.url, bmp);
            if(imageViewReused(photoToLoad))
                return;
            BitmapDisplayer bd=new BitmapDisplayer(bmp, photoToLoad);
            Activity a=(Activity)photoToLoad.imageView.getContext();
            a.runOnUiThread(bd);
        }
    }

    boolean imageViewReused(PhotoToLoad photoToLoad){
        String tag=imageViews.get(photoToLoad.imageView);
        if(tag==null || !tag.equals(photoToLoad.url))
            return true;
        return false;
    }

    //Used to display bitmap in the UI thread
    class BitmapDisplayer implements Runnable
    {
        Bitmap bitmap;
        PhotoToLoad photoToLoad;
        public BitmapDisplayer(Bitmap b, PhotoToLoad p){bitmap=b;photoToLoad=p;}
        public void run()
        {
            if(imageViewReused(photoToLoad))
                return;
            if(bitmap!=null)
                photoToLoad.imageView.setImageBitmap(bitmap);
            else
                photoToLoad.imageView.setImageResource(stub_id);
        }
    }

    public void clearCache() {
        memoryCache.clear();
        fileCache.clear();
    }

}

文件缓存.java

文件缓存.java

import java.io.File;
import android.content.Context;

public class FileCache {

    private File cacheDir;

    public FileCache(Context context){
        //Find the dir to save cached images
        if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))
            cacheDir=new File(android.os.Environment.getExternalStorageDirectory(),"TempImages");
        else
            cacheDir=context.getCacheDir();
        if(!cacheDir.exists())
            cacheDir.mkdirs();
    }

    public File getFile(String url){
        String filename=String.valueOf(url.hashCode());
        File f = new File(cacheDir, filename);
        return f;

    }

    public void clear(){
        File[] files=cacheDir.listFiles();
        if(files==null)
            return;
        for(File f:files)
            f.delete();
    }

}

内存缓存.java

import java.lang.ref.SoftReference;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import android.graphics.Bitmap;

public class MemoryCache {
    private Map<String, SoftReference<Bitmap>> cache=Collections.synchronizedMap(new HashMap<String, SoftReference<Bitmap>>());

    public Bitmap get(String id){
        if(!cache.containsKey(id))
            return null;
        SoftReference<Bitmap> ref=cache.get(id);
        return ref.get();
    }

    public void put(String id, Bitmap bitmap){
        cache.put(id, new SoftReference<Bitmap>(bitmap));
    }

    public void clear() {
        cache.clear();
    }
}

实用程序.java

import java.io.InputStream;
import java.io.OutputStream;

public class Utils {
    public static void CopyStream(InputStream is, OutputStream os)
    {
        final int buffer_size=1024;
        try
        {
            byte[] bytes=new byte[buffer_size];
            for(;;)
            {
              int count=is.read(bytes, 0, buffer_size);
              if(count==-1)
                  break;
              os.write(bytes, 0, count);
            }
        }
        catch(Exception ex){}
    }
}

使用这些你需要做的只是

public class AndroidLoadImageFromURLActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        // Loader image - will be shown before loading image
        int loader = R.drawable.loader;

        // Imageview to show
        ImageView image = (ImageView) findViewById(R.id.image);

        // Image url
        String image_url = "TOUR IMAGE URL";

        // ImageLoader class instance
        ImageLoader imgLoader = new ImageLoader(getApplicationContext());

        // whenever you want to load an image from url
        // call DisplayImage function
        // url - image url to load
        // loader - loader image, will be displayed before getting image
        // image - ImageView 
        imgLoader.DisplayImage(image_url, loader, image);
    }
}

条件 每当 URL 不匹配时,图像都会从服务器加载,并且当您将它们存储在本地时,它们永远不会从服务器下载,而是从缓存显示

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android 位图图像缓存 的相关文章

  • 登录成功后如何开始新的活动?

    我想在登录成功后开始一项新活动 也就是说 当登录正确时 新的活动应该自动启动 我不知道在哪里提到启动活动 请帮我解决这个问题 我是 Android 新手 这是我的代码 public class BackgroundTask extends
  • Android 在 ListView 中获取精确的滚动位置

    我想获得 ListView 滚动的确切像素位置 不 我指的不是第一个可见位置 有办法实现这一点吗 好的 我找到了一个解决方法 使用以下代码 View c listview getChildAt 0 int scrolly c getTop
  • 如何在 Android 中从服务器检索数据时更新滚动的 ListView?

    目前 我正在使用 AsyncTask 来处理 Http 连接并以 JSON 格式检索数据 加载所有数据很简单 但会消耗太多时间 因此我决定使用一次加载 10 个项目LIMIT OFFSET mysql 接下来我设置事件onScroll为我的
  • 使用三元运算符“不执行任何操作”[重复]

    这个问题在这里已经有答案了 我想像这样使用三元运算符 仅检查true声明的一部分 foo bar Do nothing 是否可以排除该语句的 else 部分的逻辑 我尝试使用return 但编译器给出了错误 基本上我想要实现的是使用三元运算
  • Android FAB 图标始终为黑色,带有 MaterialComponents 主题

    我正在创建一个 Android 应用程序 并使用 AndroidX 库和 Material design 主题 我的应用程序主题为styles xml is 我有来自自定义库的以下 F
  • Android Google Cast 通知禁用

    我将 Google Cast 集成到了我的 Android 应用程序中 我的所有内容都是通过带有通知的服务播放的 当我使用 Google Cast 播放媒体时 它会添加自己的通知 是否可以禁用默认的谷歌强制转换通知并仅使用自己的通知 谢谢
  • android中如何实现列表之间的拖放?

    我试图做到这一点 以便用户可以从一个列表视图中拖动文本视图 然后将其放入另一个列表视图中 但我发现这非常困难 到目前为止我发现的最大问题是 onTouchEvents 似乎只能在 ACTION DOWN 事件起源的视图中听到 我将单击一个列
  • onPageSelected 不适用于第一页

    我的寻呼机适配器 扩展 PagerAdepter 中有一个文本视图 我使用 MainActivity 的 onPageSelected 更新此文本视图 它更新位置 gt 0 的文本视图 但起始页 位置 0 在启动时不会更新 当我向前滑动然后
  • 最初从位图泄漏未引用的 byte[] 但被回收()导致内存泄漏(直到活动停止)

    我有位图内存泄漏导致内存不足 我在 Android 5 0 三星 S5 上运行了测试 我已经使用 Android Studio 1 5 1 2 0 0 Preview 7 调查了这个问题 HPROF 内存转储显示有多个 byte 与我暂时使
  • 更改首选项(设置)后,显示设置的文本不会更新

    我将尝试解释一个简单的应用程序场景 我的应用程序直接进入 主视图 在这个主视图中我插入了一个TextView它显示通过以下方式创建的当前设置PreferenceManager 为了简单起见 假设我的设置中有一个复选框 当我第一次启动我的应用
  • Android 中如何获取帧

    实际上 我需要从视频中获取所有帧 但在使用 Mediametadataretriever 缩略图 时间戳获取帧时 我经常重复获取第一帧 然后获取特定时间帧 我通过更改所有 GetFrameAtTime options 尝试了很多修复 但仍然
  • 让 SSLEngine 在 Android (4.4.2) 上使用 TLSv1.2?

    伙计们 我希望我遗漏了一些明显的东西 并且我希望有人能够提供一些线索 我正在尝试让 TLSv1 2 在 SSL NIO 上下文中运行 使用Android异步 https github com koush AndroidAsync库 所以我尝
  • 可扩展列表指示器

    我有一个可扩展的列表 所以两个问题 我见过一些类似的问题 但从未找到答案 我该怎么办 隐藏箭头 组指示器 当没有孩子的时候 我尝试在适配器中执行此操作 public View getGroupView int groupPosition b
  • Android源代码中PathClassLoader的实例是在何时何地创建的?

    当我研究android源码时 我注意到app中的通用类加载器是一个实例PathClassLoader 并且该类中有两个构造函数 一种是这样的 public PathClassLoader String dexPath ClassLoader
  • Android:使用 putExtra 从片段访问容器活动对象?

    我正在使用操作栏和片段构建选项卡界面 我需要帮助将数据从容器活动发送到片段 详细地说 我在容器活动中有作业对象 我根据工作对象中的信息创建了几个选项卡 如公司详细信息 经验详细信息等 我需要将作业对象传递给这些片段 以便它可以显示相应的信息
  • 不同应用的 Admob 广告单元 ID 相同吗?

    Context 我们正在努力整合admob在我们的应用程序中 我们有 25 个应用程序 主要是动态壁纸 当我们在里面创建广告单元ID时admob 我们提供应用程序名称作为 Playstore 中我们自己的应用程序包名称之一 我们有两个活动
  • 如何在 android 中将日期从 24 小时格式更改为 12 小时格式(上午/下午)

    Calendar ci Calendar getInstance CiDateTime ci get Calendar MONTH 1 ci get Calendar DAY OF MONTH ci get Calendar YEAR St
  • 如何在 Android RecyclerView 中显示一组项目的日期/日期

    您好 我在 JSONArray 中获取数据如下 chatArray msg id 193 user id 15235 first name Vishal user name vishal13 message twilio chat time
  • AndroidJUnit4 测试未找到

    我像这样注释了我的课程 RunWith AndroidJUnit4 class public class WorkdayProviderTest 此外 还注释了我的测试方法 如下所示 Test public void insert data
  • 如何在聚焦或单击时突出显示 ImageView?

    一个很好的例子是 Twitter 启动屏幕 首次启动应用程序时看到的带有大图标的屏幕 甚至当您聚焦应用程序图标时只需查看应用程序托盘 基本上 我需要突出显示 ImageView 其中突出显示 ImageView 中图像的轮廓 并且看起来像是

随机推荐

  • Visual Studio Code 不建议使用 Python 对象属性

    我使用添加了 Python 扩展的 VS Code v1 25 1 尽管它向我建议了库和类的属性和方法 即我输入from sklearn 它提出像这样的建议ensemble exception等等 当我生成 numpy 数组时x data
  • 如何从纯文本中查找键值存储中的值

    给定一个纯文本文件 其中包含 FOO foo BAR bar BAZ baz 我们如何grep使用键获取值 Use a 向后看 https regex101 com r q3FNpe 1 grep Po lt FOO w file foo
  • OpenCover 与 TFS 集成

    我是 TFS 新手 希望将 OpenCover 与 TFS 集成 如果有人这样做过 请帮忙 这个问题相当老了 但也许你仍然感兴趣 对于当前版本的 TFS 2015 Update 2 现在可以将其作为 vsts 扩展 详细信息请参见此处 ht
  • 如何使用唯一指针向量?

    I use vector
  • 如何将 URL 参数传递到 Wordpress 页面中的 iFrame?

    WordPress 3 2 1 我有一个页面 其中嵌入了外部页面的 iframe 即在 WP 页面中我有以下代码 我可以动态设置外部网站源吗 通过 URL 参数 假设上面的页面是http mysite com myiframe page h
  • AVMutableVideoComposition 内的交叉淡入淡出

    我已经成功地用多个视频剪辑组成了一个 AVMutableComposition 并且可以查看和导出它 并且我希望能够使用交叉淡入淡出在它们之间进行转换 所以我想使用 AVMutableVideoComposition 我找不到任何关于如何连
  • 同一活动的多个通知

    我有一个正在从通知栏打开的活动 但是当我这样做时NotificationManager notify 我给意图一个不同的捆绑 以便每个通知打开相同的活动 但从数据库中获取彼此的其他信息 但是 当我尝试输入任何通知 例如有 3 个通知 时 它
  • C/C++ 有哪些突变测试框架?

    突变测试 https secure wikimedia org wikipedia en wiki Mutation testing已经出现有一段时间了 似乎至少有一两个针对 C C 的商业突变测试框架 你用过它们吗 你有什么经历 有没有开
  • 根据 1 的数量查找数字的排名

    令 f k y 其中 k 是非负整数递增序列中的第 y 个数 其二进制表示形式中的 1 数量与 k 相同 例如f 0 1 f 1 1 f 2 2 f 3 1 f 4 3 f 5 2 f 6 3 等等 给定 k gt 0 计算 f k 我们很
  • Google App Engine 电子邮件进入垃圾邮件文件夹

    当我使用邮件的 send mail 函数通过谷歌应用程序引擎发送电子邮件时 它们通常会被放置在收件人的 SPAM 文件夹中 虽然 GMail 帐户不会出现此问题 但 Yahoo Mail 帐户 可能还有其他几个帐户 会出现此问题 有没有办法
  • 将 JavaScript 中的大字符串与哈希进行比较

    我有一个带有文本区域的表单 其中可以包含使用多个第三方富文本编辑器之一编辑的大量内容 例如博客文章 我正在尝试实现类似自动保存功能的功能 如果内容发生更改 它应该通过ajax 提交内容 然而 我必须解决这样一个事实 我作为选项的一些编辑器不
  • IIS7 和 HTTP 状态代码处理

    我因试图对 IIS7 集成模式 中的错误呈现进行完整的编程控制而感到非常头疼 我想要做的是给出一个错误 找不到页面 内部服务器错误 未经过身份验证等 将整个请求传输到自定义 ASPX 或 HTML 我更喜欢后者 并使用正确的 HTTP 状态
  • 通过json在textview中显示数据

    我想通过php显示mysql数据库中的用户详细信息并将其显示在android textview中 场景是这样的 当用户登录到他的帐户时 他将被重定向到包含 4 个按钮的仪表板 即 新闻源 个人资料 日历和关于 当用户单击个人资料按钮时 用户
  • Angular 9 ngtypecheck

    更新到 Angular 9 后 我收到警告 src main ngtypecheck ts is part of the TypeScript compilation but it s unused Add only entry point
  • 如何在 Swift 中处理 NSUserDefaults 中的非可选值

    从中获取值NSUserDefaults我会做这样的事情 let userDefaults NSUserDefaults standardUserDefaults if let value userDefaults objectForKey
  • 如何将值从对象转换为 Nullable<> [重复]

    这个问题在这里已经有答案了 我有一些带有一些属性的类 我想将值从字符串转换为该属性的类型 我在转换为可为空类型时遇到问题 这是我的转换方法 public static object ChangeType object value Type
  • 绑定到 AvalonDock 2 中的 LayoutAnchorableItem 可见性

    我正在尝试绑定Visibility of LayoutAnchorableItem到 ViewModel 中的布尔值 以便我可以以编程方式显示和隐藏可锚定
  • .rmd 文件的访问名称并在 R 中使用

    我正在编织一个名为MyFile rmd 我如何访问该字符串MyFile在编织过程中并将其用于 在 YAML 标头的标题部分中使用 在后续的 R 块中使用 title r rmarkdown metadata title author My
  • 如何在maven antrun插件中执行输入任务

    我创建了一个 Maven 项目 我正在尝试运行外部脚本 在此外部脚本中 我使用 read 命令来提出问题并获得答案 如果我做一个 它会起作用sudo mvn 包 with 执行 maven 插件 http www mojohaus org
  • Android 位图图像缓存

    嗨 我正在 Android 中实现图像缓存 经历过这个 http developer android com training displaying bitmaps cache bitmap html http developer andr