2017-07-05 106 views
1

我有一個gridview,其中包含我的可繪製文件夾中的圖像數組。我現在已經制定了將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

例如,在Android應用中使用位圖和圖像時,已經在SO上編寫了很多關於Out of Memory錯誤的文章:hereherehere

爲了在設備上設置牆紙的特殊目的,您可以嘗試這種方法。我不能保證你會一直避免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); 
} 

調用decodeBitmapWithinFreeMemory按鈕的onClick方法中,餵養它的設備的屏幕縱橫比例:

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.的文檔)