对于我的10,000点,我决定在这个很酷的网站上做出一些贡献:一种将位图缓存在本机内存中的机制。
背景
Android设备为每个应用程序分配的内存非常有限-堆的范围从16MB到128MB,具体取决于各种参数。
如果超过此限制,则会得到OOM,并且在使用位图时可能会发生多次。
很多时候,应用可能需要克服这些限制,对巨大的位图执行繁重的操作,或者只是将其存储以备后用,而您需要
我想出的是一个简单的Java类,它将使实现这些目的变得容易一些。
它使用JNI来存储位图数据,并能够在需要时进行还原。
为了支持该类的多个实例,我不得不使用发现的技巧(here)。
重要笔记
数据仍存储在RAM中,因此,如果设备没有足够的RAM,则该应用可能会被杀死。
记住要尽快释放内存。这不仅是为了避免内存泄漏,而且还是为了避免一旦您的应用程序出现在后台时被系统优先处理。
如果您不想忘记释放内存,则可以在每次还原位图时释放它,或者使该类实现Closable。
为了安全起见,我已使其在finalize()方法中自动释放其本机内存,但不要让它负责这项工作。太冒险了。当发生这种情况时,我也已将其写入日志。
它的工作方式是将整个数据复制到JNI对象中,并且为了还原,它从头开始创建位图并将数据放入其中。
正在使用和还原的位图为ARGB_8888格式。当然,您可以将其更改为所需的任何内容,只是不要忘记更改代码…
大的位图可能需要花费一些时间来存储和恢复,因此在后台线程上进行操作可能是明智的。
这不是完整的OOM解决方案,但可能会有所帮助。例如,您可以将其与您自己的LruCache结合使用,同时避免将堆内存用于缓存本身。
代码仅用于存储和还原。如果需要执行某些操作,则需要进行一些研究。openCV可能是答案,但是如果您希望执行一些基本的工作,则可以自己实现它们(这是使用JNI的可旋转大图像的示例)。如果您知道其他选择,请在此处告诉我。
希望这对某些人有用。请写下您的评论。
另外,如果您发现代码有任何问题或改进建议,请告诉我。
说明示例代码显示了如何存储2个不同的位图(较小的位图,但这只是一个演示),回收原始的Java位图,然后将它们还原为Java实例并使用它们。
您可能会猜到,该布局有2个imageViews。我没有在代码中包含它,因为它很明显。
请记住,如果需要,可以将代码更改为您自己的软件包,否则将无法正常工作。
MainActivity.java-如何使用:
package com.example.jnibitmapstoragetest;
...
public class MainActivity extends Activity
{
@Override
protected void onCreate(final Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
//
Bitmap bitmap=BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher);
final JniBitmapHolder bitmapHolder=new JniBitmapHolder(bitmap);
bitmap.recycle();
//
Bitmap bitmap2=BitmapFactory.decodeResource(getResources(),android.R.drawable.sym_action_call);
final JniBitmapHolder bitmapHolder2=new JniBitmapHolder(bitmap2);
bitmap2.recycle();
//
setContentView(R.layout.activity_main);
{
bitmap=bitmapHolder.getBitmapAndFree();
final ImageView imageView=(ImageView)findViewById(R.id.imageView1);
imageView.setImageBitmap(bitmap);
}
{
bitmap2=bitmapHolder2.getBitmapAndFree();
final ImageView imageView=(ImageView)findViewById(R.id.imageView2);
imageView.setImageBitmap(bitmap2);
}
}
}
JniBitmapHolder.java-JNI和JAVA之间的“桥梁”:
package com.example.jnibitmapstoragetest;
...
public class JniBitmapHolder
{
ByteBuffer _handler =null;
static
{
System.loadLibrary("JniBitmapStorageTest");
}
private native ByteBuffer jniStoreBitmapData(Bitmap bitmap);
private native Bitmap jniGetBitmapFromStoredBitmapData(ByteBuffer handler);
private native void jniFreeBitmapData(ByteBuffer handler);
public JniBitmapHolder()
{}
public JniBitmapHolder(final Bitmap bitmap)
{
storeBitmap(bitmap);
}
public void storeBitmap(final Bitmap bitmap)
{
if(_handler!=null)
freeBitmap();
_handler=jniStoreBitmapData(bitmap);
}
public Bitmap getBitmap()
{
if(_handler==null)
return null;
return jniGetBitmapFromStoredBitmapData(_handler);
}
public Bitmap getBitmapAndFree()
{
final Bitmap bitmap=getBitmap();
freeBitmap();
return bitmap;
}
public void freeBitmap()
{
if(_handler==null)
return;
jniFreeBitmapData(_handler);
_handler=null;
}
@Override
protected void finalize() throws Throwable
{
super.finalize();
if(_handler==null)
return;
Log.w("DEBUG","JNI bitmap wasn't freed nicely.please rememeber to free the bitmap as soon as you can");
freeBitmap();
}
}
Android.mk-JNI的属性文件:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := JniBitmapStorageTest
LOCAL_SRC_FILES := JniBitmapStorageTest.cpp
LOCAL_LDLIBS := -llog
LOCAL_LDFLAGS += -ljnigraphics
include $(BUILD_SHARED_LIBRARY)
APP_OPTIM := debug
LOCAL_CFLAGS := -g
JniBitmapStorageTest.cpp-“神奇”的东西在这里:
#include <jni.h>
#include <jni.h>
#include <android/log.h>
#include <stdio.h>
#include <android/bitmap.h>
#include <cstring>
#include <unistd.h>
#define LOG_TAG "DEBUG"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
extern "C"
{
JNIEXPORT jobject JNICALL Java_com_example_jnibitmapstoragetest_JniBitmapHolder_jniStoreBitmapData(JNIEnv * env, jobject obj, jobject bitmap);
JNIEXPORT jobject JNICALL Java_com_example_jnibitmapstoragetest_JniBitmapHolder_jniGetBitmapFromStoredBitmapData(JNIEnv * env, jobject obj, jobject handle);
JNIEXPORT void JNICALL Java_com_example_jnibitmapstoragetest_JniBitmapHolder_jniFreeBitmapData(JNIEnv * env, jobject obj, jobject handle);
}
class JniBitmap
{
public:
uint32_t* _storedBitmapPixels;
AndroidBitmapInfo _bitmapInfo;
JniBitmap()
{
_storedBitmapPixels = NULL;
}
};
JNIEXPORT void JNICALL Java_com_example_jnibitmapstoragetest_JniBitmapHolder_jniFreeBitmapData(JNIEnv * env, jobject obj, jobject handle)
{
JniBitmap* jniBitmap = (JniBitmap*) env->GetDirectBufferAddress(handle);
if (jniBitmap->_storedBitmapPixels == NULL)
我创建了一个简单的应用程序,裁剪图像。现在我想保存这个图像到消防基地。 如何将此图像保存到Firebase。我尝试了很多教程,但都没有成功。请用简单的代码验证。
问题内容: 我是所有内存管理主题的新手,所以有很多我不了解的事情。 我正在尝试将图像缓存在我的应用程序中,但是我在内存消耗方面遇到了麻烦: 所有的Bitmap Chaching代码都可以从此处复制粘贴:http : //developer.android.com/training/displaying- bitmaps/index.html 我调试了代码,并在Eclipse的DDMS视图中检查了堆
在服务器重置缓存数据保存在磁盘存储后。但在服务器启动后不使用缓存数据。所以我想加载磁盘存储内容到memory.How做到这一点?在这个堆栈问题加载EhCache磁盘存储内容到内存中使用BootstrapCacheLoaderFactory但不为我出现。
本文向大家介绍Android图片三级缓存策略(网络、本地、内存缓存),包括了Android图片三级缓存策略(网络、本地、内存缓存)的使用技巧和注意事项,需要的朋友参考一下 一、简介 现在的Android应用程序中,不可避免的都会使用到图片,如果每次加载图片的时候都要从网络重新拉取,这样不但很耗费用户的流量,而且图片加载的也会很慢,用户体验很不好。所以一个应用的图片缓存策略是很重要的。通常情况下,A
我用ReactJS构建了一个渐进式Web应用程序,但遇到了一个问题。我正在使用mockApi获取数据。脱机时,我的应用程序不工作,因为服务人员只缓存静态资产。 如何将HTTP GET调用从mockApi保存到缓存存储?
问题内容: 如何在WAMP中安装内存缓存? 我在中找不到任何php_memche 。 现在我该怎么做? @瑞安 感谢您的步骤,现在在WAMP中启用了内存缓存,我也已经在PHPINFO中进行了交叉检查。正在显示内存缓存。 我已经尝试过以下示例Memcache示例。但是抛出错误。 收到以下通知错误。 我错过了… 问题答案: 以下是对我有用的步骤: 所需文件 直接链接 Windows DLL文件 适用于