1

我创建了一个时钟小部件,它每分钟从服务(通过广播接收器)更新,但几个小时后它需要大约 600mb 的 RAM。

该小部件每分钟绘制一个具有某些功能的位图,并通过简单的ImageView.

一开始,小部件只占用几 kb 的内存,但几分钟后它会占用数百 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);
}
}
4

2 回答 2

1

原因是每分钟您都会将新位图加载到内存中。所以你的解决方案应该是以下之一:

  1. 正如已经建议的那样,回收您使用过的位图,以便将来将此内存块用于下一个位图。

  2. 使用不会占用太多空间且不会导致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);
}
于 2013-03-07T15:35:31.497 回答
0

我和你在同一条船上,我可能已经找到了一个解决方案来保持它有点低。经过大量搜索和失败的结果,我可以让我的时钟小部件(其背景图像高达 800x800、溢出菜单图像、时间和日期——所有位图)通常不超过 45mb;如果用户没有弄乱小部件的设置和自定义,它有时会保持在 20MB 以下——在我写这篇文章的时候,它会下降到 ~11MB。(然后在搞乱自定义之后,跳到 41MB,现在坐在不到 10MB 大约一个小时)

你的问题是说你的时钟有一些功能;我假设这是某种图像?好吧,我注意到,每分钟,每次更新,我都会重新绘制所有内容(背景、菜单、时间和日期)。我设法将其分为三个部分:菜单(必须单独用于待处理的意图)、背景 + 日期(仅在我UPDATE有意图时更新TIME CHANGED)和时间。我在我的静态类中使用 aSparseArray来保存背景 + 日期位图,然后当我只更新时间时,我调用该位图,所以我不必重新创建它。然后当我设置我的远程视图时,我有类似的东西。

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));

您可能需要做类似的事情。它不会总是保持低内存(至少对我来说),但它似乎确实有帮助。

于 2013-09-02T22:46:03.350 回答