我有一个gridview,其中包含我的drawable文件夹中的图像数组。我现在已经解决了将drawable发送到另一个活动,用户将在将原始文件夹中的图片设置为壁纸之前查看图像。我无法使用drawable资产,因为压缩和合适的图像会因内存不足而导致崩溃。
带有gridview的我的MainActivity文件:
GridView androidGridView;
private Integer asset1 = R.drawable.asset1;
private Integer asset2 = R.drawable.asset2;
private Integer asset3 = R.drawable.asset1;
private Integer asset4 = R.drawable.asset2;
private Integer asset5 = R.drawable.asset1;
private Integer asset6 = R.drawable.asset2;
private Integer[] images = {
asset1, asset2, asset3,
asset4, asset5, asset6
};
Integer[] imagesIDs = {
R.raw.asset1, R.raw.asset2, R.drawable.asset1,
R.drawable.asset1, R.drawable.asset1, R.drawable.asset1,
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
androidGridView = findViewById(R.id.gridview_android_example);
androidGridView.setAdapter(new ImageAdapterGridView(this));
androidGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent,
View v, int position, long id) {
int imageRes = images[position];
Intent intent = new Intent(MainActivity.this, ViewActivity.class);
intent.putExtra("IMAGE_RES", imageRes);
startActivity(intent);
}
});
}
public class ImageAdapterGridView extends BaseAdapter {
private Context mContext;
public ImageAdapterGridView(Context c) {
mContext = c;
}
public int getCount() {
return images.length;
}
public Object getItem(int position) {
return null;
}
public long getItemId(int position) {
return 0;
}
public View getView(int position, View convertView, ViewGroup parent) {
ImageView mImageView;
if (convertView == null) {
mImageView = new ImageView(mContext);
mImageView.setLayoutParams(new GridView.LayoutParams(525, 350));
mImageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
mImageView.setPadding(16, 16, 16, 16);
} else {
mImageView = (ImageView) convertView;
}
mImageView.setImageResource(images[position]);
return mImageView;
}
我的ViewActivity文件,用户在将其设置为壁纸之前将预览图像:
private Integer asset1 = R.raw.asset1;
private Integer asset2 = R.raw.asset2;
private Integer asset3 = R.raw.asset1;
private Integer asset4 = R.raw.asset2;
private Integer asset5 = R.raw.asset1;
private Integer asset6 = R.raw.asset2;
private Integer[] images = {
asset1, asset2, asset3,
asset4, asset5, asset6
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view);
Bundle extras = getIntent().getExtras();
int imageRes = extras.getInt("IMAGE_RES");
ImageView preview = findViewById(R.id.preview);
preview.setImageResource(imageRes);
preview.setScaleType(ImageView.ScaleType.CENTER_CROP);
Button set = findViewById(R.id.setButton);
set.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
}
});
}
我不确定自己是否走在正确的轨道上,但如果有人能指出我的方向会很棒,那就太棒了!
答案 0 :(得分:0)
在Android应用程序中处理位图和图像时,有很多关于内存不足错误的内容:here,here和here。
出于在设备上设置壁纸的特殊目的,您可以尝试这种方法。我并不保证你总是会以这种方式避免OOM错误,但它应该阻止大部分错误。
当它将资源解码为位图时,试图保持在应用程序的当前空闲内存中。它还在最后回收位图。
一个优点是您不必提出输出位图所需的宽度和高度。它基于自由记忆为你做到了这一点。 (这也是一个缺点 - 你不能自由选择你想要的任何位图尺寸。它们可能太大而导致崩溃。)
进行解码可能需要一些时间,这就是它在后台线程上完成的原因。
无论如何,这对我有用:
将ExecutorService和方法decodeBitmapWithinFreeMemory添加到ViewActivity:
private ExecutorService executor = Executors.newSingleThreadExecutor();
...
// adapted from https://developer.android.com/topic/performance/graphics/load-bitmap.html
private Bitmap decodeResourceWithinFreeMemory(Resources resources, int resourceId, float requiredAspectRatio) {
// get just the size of the resource image
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(resources, resourceId, options);
// estimate number of pixels we can work with in current free memory
long freeMem = Runtime.getRuntime().freeMemory();
long spaceForARGV8888Px = freeMem / 4; // est. number of ARGV_8888 pixels that can be stored
// calculate the sides of a rectangle with approximately that number of pixels
long squareRootLowerBound = (long) Math.floor(Math.pow(spaceForARGV8888Px, 0.5));
int requestedWidth = (int) Math.floor(squareRootLowerBound * requiredAspectRatio);
int requestedHeight = (int) Math.floor(squareRootLowerBound / requiredAspectRatio);
// find the right sample size by aggressively increasing sampleSize var: require only that
// _one_ of the output dimensions be greater than the corresponding requested dimension
int sampleSize = 1;
while ((options.outHeight / (2 * sampleSize) ) >= requestedHeight
|| (options.outWidth / (2 * sampleSize) ) >= requestedWidth) {
sampleSize *= 2;
}
// output the bitmap by sampling the input resource at the calculated sampleSize
options.inSampleSize = sampleSize;
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(resources, resourceId, options);
}
在按钮的onClick方法中调用decodeBitmapWithinFreeMemory,为其提供设备的屏幕宽高比:
DisplayMetrics metrics = getResources().getDisplayMetrics();
final float screenAspectRatio = (float)metrics.widthPixels/(float)metrics.heightPixels;
executor.submit(new Runnable() {
@Override
public void run() {
try {
Bitmap drawableAsBitmap = decodeResourceWithinFreeMemory(getResources(),
R.raw.asset1, screenAspectRatio);
WallpaperManager.getInstance(MainActivity.this).setBitmap(drawableAsBitmap);
drawableAsBitmap.recycle();
} catch (IOException ioe) {
Log.e(TAG, "Could not set wallpaper to bitmap", ioe);
}
}
});
另请注意,您可以选择将BroadcastReceiver添加到您的活动中,以通知已设置壁纸。 (参见setBitmap.)
的文档