Android ImageView无法加载图片求助(含压缩及Picasso使用疑问)
Hey there! Let's work through your image loading problem step by step. I see two main issues in your code: incorrect handling of camera capture output, a flawed compression method, and confusion around using Picasso. Let's fix them one by one.
First: Fix Camera Capture Uri Problem
When using ACTION_IMAGE_CAPTURE, the default intent doesn't return a full-size image Uri via data.getData() — it only returns a thumbnail in the intent data. To get the full-size image, you need to specify a temporary file to save the photo first:
Step 1: Add a Uri variable in your Fragment
private Uri photoUri;
Step 2: Update the camera intent in your fetch button click listener
case 0: // Create a temporary file to store the captured photo File storageDir = requireContext().getExternalFilesDir(Environment.DIRECTORY_PICTURES); try { File photoFile = File.createTempFile("JPEG_", ".jpg", storageDir); // Use FileProvider to handle Android 7+ file permissions photoUri = FileProvider.getUriForFile(requireContext(), requireContext().getPackageName() + ".fileprovider", photoFile); Intent takePicture = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); takePicture.putExtra(MediaStore.EXTRA_OUTPUT, photoUri); startActivityForResult(takePicture, 0); } catch (IOException e) { e.printStackTrace(); } break;
(Don't forget to set up FileProvider in your manifest and xml — this is required for Android 7.0+ to avoid permission errors.)
Second: Fix the Compression Method
Your original compressImage has two critical issues:
- The
bmpvariable is defined inside the try block, so it might returnnullif an exception occurs. - You're only doing format compression (PNG to PNG with 100% quality) — no size scaling, which causes large images to overflow memory and fail to display.
Here's the corrected compression method with size scaling:
public Bitmap compressImage(Uri uri) { Bitmap bmp = null; InputStream inputStream = null; try { inputStream = getContext().getContentResolver().openInputStream(uri); // First, get the image's original dimensions without loading it into memory BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeStream(inputStream, null, options); inputStream.close(); // Calculate sample size to scale the image down to your ImageView's size int targetWidth = upld_img.getWidth(); int targetHeight = upld_img.getHeight(); int sampleSize = calculateInSampleSize(options, targetWidth, targetHeight); // Load the scaled-down image into memory options.inJustDecodeBounds = false; options.inSampleSize = sampleSize; inputStream = getContext().getContentResolver().openInputStream(uri); bmp = BitmapFactory.decodeStream(inputStream, null, options); // Optional: Add format compression to reduce file size (use JPEG for photos) if (bmp != null) { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); bmp.compress(Bitmap.CompressFormat.JPEG, 80, byteArrayOutputStream); byte[] compressedBytes = byteArrayOutputStream.toByteArray(); bmp = BitmapFactory.decodeByteArray(compressedBytes, 0, compressedBytes.length); byteArrayOutputStream.close(); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { if (inputStream != null) inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } return bmp; } // Helper method to calculate the optimal sample size for scaling private int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; if (height > reqHeight || width > reqWidth) { final int halfHeight = height / 2; final int halfWidth = width / 2; // Find the largest sample size that keeps scaled dimensions above the target while ((halfHeight / inSampleSize) >= reqHeight && (halfWidth / inSampleSize) >= reqWidth) { inSampleSize *= 2; } } return inSampleSize; }
Third: Use Picasso for Simplified Image Loading
Picasso handles all the heavy lifting of image compression, memory management, and caching automatically. Here's how to use it:
Step 1: Add Picasso dependency to your app-level build.gradle
implementation 'com.squareup.picasso:picasso:2.71828'
Step 2: Replace your onActivityResult code with Picasso calls
@Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); switch (requestCode){ case 0: if (resultCode == RESULT_OK && photoUri != null) { // Load camera photo into ImageView Picasso.get() .load(photoUri) .resize(upld_img.getWidth(), upld_img.getHeight()) // Scale to ImageView size .centerCrop() // Optional: Crop to fit (use .fit() for scaling without cropping) .into(upld_img); Log.e("Image","Uploaded"); } break; case 1: if (resultCode == RESULT_OK && data != null) { // Load gallery photo into ImageView Picasso.get() .load(data.getData()) .resize(upld_img.getWidth(), upld_img.getHeight()) .centerCrop() .into(upld_img); Log.e("Image","Uploaded"); } break; } }
This will eliminate the need for your custom compressImage method entirely — Picasso takes care of resizing and compressing images efficiently.
内容的提问来源于stack exchange,提问作者jobin

