我创建了一个时钟小部件,每分钟从服务(通过广播接收器)更新,但在几个小时后它需要大约600mb的RAM。
小部件每分钟都会使用一些功能绘制位图,并通过简单的ImageView
显示。
一开始,小部件只占用几公斤的ram,但几分钟后就需要几百mb。有一种方法可以在创建新位图之前清除RAM吗?
这是小部件代码的一部分:
public class Widget_01_Clock extends AppWidgetProvider {
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
Bitmap clock = WidgetPaint.getClockBitmap();
RemoteViews updateViews = new RemoteViews(context.getPackageName(),R.layout.w_01_clock);
updateViews.setImageViewBitmap(R.id.w_01_clock, clock);
}
}
答案 0 :(得分:1)
原因是每分钟都会将新位图加载到内存中。 所以你的解决方案应该是以下之一:
已经建议回收使用过的位图,以便将来使用此内存块用于下一个位图。
使用非常小的图像(缩略图),不会占用太多空间,并且不会导致OutOfMemory
异常。
我个人认为你应该同时做这两件事,这里有一个代码来创建你的图像文件的缩略图版本:
public static Bitmap decodeSampledBitmapFromFile(String path,
int reqWidth, int reqHeight) { // BEST QUALITY MATCH
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, options);
// Calculate inSampleSize
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
options.inPreferredConfig = Bitmap.Config.RGB_565;
int inSampleSize = 1;
if (height > reqHeight) {
inSampleSize = Math.round((float)height / (float)reqHeight);
}
int expectedWidth = width / inSampleSize;
if (expectedWidth > reqWidth) {
//if(Math.round((float)width / (float)reqWidth) > inSampleSize) // If bigger SampSize..
inSampleSize = Math.round((float)width / (float)reqWidth);
}
options.inSampleSize = inSampleSize;
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(path, options);
}
答案 1 :(得分:0)
我和你在同一条船上,我可能已经找到了一个解决方案来保持它有点低。经过大量的搜索和失败的结果,我可以得到我的时钟小部件(其背景图像高达800x800,溢出菜单图像,时间和日期 - 所有位图)通常不高于45mb;如果用户没有弄乱小部件的设置和自定义,它有时可以保持在20mb以下 - 因为我写这个,它被降到~11MB。 (然后在搞乱定制后,跳到41MB,现在大约一个小时的时间不到10MB)
你的问题是你的时钟有一些功能;我假设这是某种形象?好吧,我注意到我的每一分钟,每次更新,我都会重新绘制所有内容(背景,菜单,时间和日期)。我设法将其分为三个部分:菜单(必须为待定意图分开),背景+日期(仅当我有UPDATE
意图或TIME CHANGED
时才更新)和时间。我在Static类中使用SparseArray
来保存背景+日期位图,然后当我只更新时间时,我调用该位图,所以我不必重新创建它。然后,当我设置远程视图时,我有类似的东西。
remoteViews.setImageViewBitmap(R.id.widget_consolidated, sparseArrayOfBitmaps.get(widgetNumber);
remoteViews.setImageViewBitmap(R.id.widget_time, functionToReturnTimeBitmap(arguments));
remoteViews.setImageViewBitmap(R.id.widget_overflow, functionToReturnMenuBitmap(arguments));
您可能需要做类似的事情。它不会总是保持低记忆(至少对我而言),但它似乎有帮助。