2017-07-05 4 views
1

私はドロウアブルフォルダに画像の配列を含むグリッドビューを持っています。私は今、壁紙として生のフォルダから画像を設定する前に、ユーザが画像を見る別のアクティビティにドロウアブルを送るようになった。私は、圧縮のために描画可能な資産を使用することはできません。適切なイメージは、メモリ不足によるクラッシュを引き起こします。選択したドロウアブルから壁紙として生のアセットを設定します

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

アンドロイドアプリでビットマップと画像を扱うときに、Out of Memoryエラーが多く書かれています。たとえば、hereherehereです。

デバイスの壁紙を設定する特別な目的のために、このようなアプローチを試みることがあります。このようにOOMエラーを避けることは必ずしも保証されませんが、ほとんどの場合、OOMエラーを回避する必要があります。

これは、リソースをビットマップにデコードするときに、アプリケーションの現在の空きメモリ内にとどまることによって解決します。また、最後にビットマップをリサイクルします。

1つの利点は、出力ビットマップの必要な幅と高さを考え出す必要がないことです。それは自由な記憶に基づいてあなたのためにそれを行います。 (それはまた欠点です。あなたが望むビットマップディメンションを自由に選ぶことはできません。サイズが大きすぎるとクラッシュする可能性があります)

デコードを実行するのに時間がかかることがありますバックグラウンドスレッドで

とにかく、これは私のために動作します。それをデバイスの画面の縦横を供給し、ボタンのonClickメソッド内

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:

があなたのViewActivityにExecutorServiceのとメソッド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.のドキュメントを参照してください)

関連する問題