内存不足(堆)问题无法修复

时间:2014-05-26 09:00:34

标签: java android out-of-memory heap-memory

嘿,我花了很多时间来修复以下代码中出现的错误。 该错误是由于内存不足(堆)造成的。 直到现在我没有找到任何解决方案(这是我第三天正在寻找它,真的很累:() 有人请告诉我一个很好的解决方案。

activity_preview.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:ads="http://schemas.android.com/apk/lib/com.google.ads"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/setimage"
    tools:context=".Preview" >

            <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:layout_above="@+id/ad"  
            android:layout_alignParentTop="true">

            <ImageView
                android:id="@+id/imageView1"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:scaleType="fitXY" />
            <ProgressBar
                android:id="@+id/pbDownload"
                style="?android:attr/progressBarStyleHorizontal"
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_alignLeft="@+id/image"
                android:layout_alignRight="@+id/image"
                android:layout_below="@+id/textView1"
                android:layout_marginTop="15dp" />

             <Button
                 android:id="@+id/save"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignParentLeft="true"
                android:layout_below="@+id/pbDownload"
                android:text="Button"
                android:visibility="gone" />

            <TextView
                android:id="@+id/textView1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="4.91"
                android:visibility="invisible" />

        </LinearLayout>


<com.google.ads.AdView
                   android:id="@+id/ad"
                   android:layout_width="wrap_content"
                   android:layout_height="wrap_content"
                   ads:adUnitId="a152e9gh407f4ae69"
                   ads:loadAdOnCreate="true"
                   ads:adSize="BANNER"
                   android:layout_above="@+id/llbuttons" 
                   android:layout_marginBottom="5dp"
            />
  <LinearLayout
      android:layout_width="match_parent"
      android:id="@+id/llbuttons"
      android:layout_height="70dp"
      android:layout_alignLeft="@+id/scrollView1"
      android:layout_alignParentBottom="true"
      android:layout_marginLeft="5dp"
      android:layout_marginRight="5dp"
      android:weightSum="1" >

        <Button
             android:id="@+id/imageButton2"
             android:layout_width="0dp"
             android:layout_height="60dp"
             android:background="@drawable/custom_setwall"
             android:onClick="onclick_setwall"
             android:scaleType="fitXY"
             android:layout_weight="0.5"
             android:layout_marginRight="5dp"/>

        <Button
            android:id="@+id/imageView5"
            android:layout_width="0dp"
            android:layout_height="60dp"
            android:layout_marginRight="5dp"
            android:layout_weight="0.25"
            android:background="@drawable/custom_save"
            android:onClick="onclick_save"
            android:scaleType="fitXY" />

        <Button
            android:id="@+id/imageButton6"
            android:layout_width="0dp"
            android:layout_height="60dp"
            android:background="@drawable/custom_share"
            android:onClick="onclick_share"
            android:scaleType="fitXY"
            android:layout_weight="0.25"
            />

</LinearLayout>

</RelativeLayout>

Preview.java

package com.hb.nfswallpapers;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Random;

import com.google.ads.AdRequest;
import com.google.ads.AdView;
import com.hitbytes.nfswallpapers.ImageDownloader;
import com.hitbytes.nfswallpapers.ImageDownloader.ImageLoaderListener;

import android.media.MediaScannerConnection;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.app.Activity;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.WallpaperManager;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.support.v4.app.NotificationCompat;
import android.util.DisplayMetrics;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ImageView.ScaleType;

public class Preview extends Activity {

    private ProgressBar pb;
    private Button bnxt,bprv,bhome,save,bsave,photos;
    private ImageView img;
    private static Bitmap bmp;
    private TextView percent;
    private FileOutputStream fos;
    private ImageDownloader mDownloader;
    String imagesources;
    int pindex,i;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_preview);
        initViews();

        Bundle extras = getIntent().getExtras();
        imagesources = extras.getString("photourl");





        /*--- instantiate our downloader passing it required components ---*/
        mDownloader = new ImageDownloader(imagesources, pb, save, img, percent, Preview.this, bmp, new ImageLoaderListener() {
            @Override
            public void onImageDownloaded(Bitmap bmp) {
                Preview.bmp = bmp;

     /*--- here we assign the value of bmp field in our Loader class 
               * to the bmp field of the current class ---*/    
            }
            });

        /*--- we need to call execute() since nothing will happen otherwise ---*/
        mDownloader.execute();

    }

    private void initViews() {

        save = (Button) findViewById(R.id.save);

        photos= (Button) findViewById(R.id.imageButton4);
        bsave= (Button) findViewById(R.id.imageButton5);

        //bnxt=(Button) findViewById(R.id.bnext);
        //bprv=(Button) findViewById(R.id.bprev);
        /*--- we are using 'this' because our class implements the OnClickListener ---*/
        img = (ImageView) findViewById(R.id.imageView1);
        img.setScaleType(ScaleType.FIT_XY);
        pb = (ProgressBar) findViewById(R.id.pbDownload);
        pb.setVisibility(View.INVISIBLE);

        percent = (TextView) findViewById(R.id.textView1);
        percent.setVisibility(View.INVISIBLE);

    }

    public void onclick_save(View v)
    {
        saveImageToSD();
    }
    public void onclick_share(View v)
    {
        Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND); 
        sharingIntent.setType("text/plain");
        String shareBody = "Find more wallpapers & images https://play.google.com/store/apps/details?id=com.hitbytes.nfswallpapers";
        sharingIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, imagesources+"\n\n");
        sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, shareBody);
        startActivity(Intent.createChooser(sharingIntent, "Share via"));
    }
    public void onclick_setwall(View v)
    {
        Random r = new Random();
        int rand =r.nextInt(1750-1000) + 1000;
        String ran=String.valueOf(rand);
        String pin=String.valueOf(pindex);

        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
        /*--- you can select your preferred CompressFormat and quality. 
         * I'm going to use JPEG and 100% quality ---*/
        bmp.compress(Bitmap.CompressFormat.JPEG, 100, bytes);


        DisplayMetrics metrics = new DisplayMetrics(); 
        getWindowManager().getDefaultDisplay().getMetrics(metrics);
        // get the height and width of screen 
        int height = metrics.heightPixels; 
        int width = metrics.widthPixels;

        WallpaperManager wallpaperManager = WallpaperManager.getInstance(this); 
          try {
                  wallpaperManager.setBitmap(bmp);

                  wallpaperManager.suggestDesiredDimensions(width, height);
                 Toast.makeText(this, "Wallpaper Set", Toast.LENGTH_SHORT).show();

              } catch (IOException e) {
                      e.printStackTrace();
               }
    }

    private void saveImageToSD() {

        /*--- this method will save your downloaded image to SD card ---*/

        Random r = new Random();
        int rand =r.nextInt(1750-1000) + 1000;
        String ran=String.valueOf(rand);
        String pin=String.valueOf(pindex);

        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
        /*--- you can select your preferred CompressFormat and quality. 
         * I'm going to use JPEG and 100% quality ---*/
        bmp.compress(Bitmap.CompressFormat.JPEG, 100, bytes);

        /*--- create a new file on SD card ---*/
        File direct = new File(Environment.getExternalStorageDirectory() + "/NFS Wallpapers");
        if (!direct.exists()) {
            File wallpaperDirectory = new File("/sdcard/NFS Wallpapers/");
            wallpaperDirectory.mkdirs();
          }
        File file = new File(new File("/sdcard/NFS Wallpapers/"), ran+pin+"Image.jpg");
        try {
            file.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
        /*--- create a new FileOutputStream and write bytes to file ---*/
        try {
            fos = new FileOutputStream(file);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        try {
            fos.write(bytes.toByteArray());
            fos.close();
            MediaScannerConnection.scanFile(this,
                      new String[] { file.toString() }, null,null);
            Toast.makeText(this, "Image saved", Toast.LENGTH_SHORT).show();

            NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
                        this).setAutoCancel(true)
                        .setContentTitle("Download complete..!")
                        .setSmallIcon(R.drawable.ic_launcher)
                        .setContentText("Image successfully downloaded!");

            NotificationCompat.BigPictureStyle bigPicStyle = new NotificationCompat.BigPictureStyle();
            bigPicStyle.bigPicture(bmp);
            bigPicStyle.setBigContentTitle("Download complete");
            mBuilder.setStyle(bigPicStyle);

            Intent intent1 = new Intent(Intent.ACTION_VIEW);
            intent1.setDataAndType(Uri.fromFile(file), "image/jpeg");

            PendingIntent resultPendingIntent = PendingIntent.getActivity(this, 0, intent1, PendingIntent.FLAG_UPDATE_CURRENT);
            mBuilder.setContentIntent(resultPendingIntent);
            NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

            // mId allows you to update the notification later on.
            mNotificationManager.notify(100, mBuilder.build());


        } catch (IOException e) {
            e.printStackTrace();
        }


    }

}

ImageDownloader.java

package com.hitbytes.nfswallpapers;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.SystemClock;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;


public class ImageDownloader extends AsyncTask<Void, Integer, Void> {

 ProgressBar pb;
 String url;
 Button save;
 Context c;
 int progress;
 ImageView img;
 Bitmap bmp;
 TextView percent;
 ImageLoaderListener listener;


/*--- constructor ---*/
public ImageDownloader(String url, ProgressBar pb, Button save,
        ImageView img, TextView percent, Context c, Bitmap bmp, ImageLoaderListener listener) {
/*--- we need to pass some objects we are going to work with ---*/
    this.url = url;
    this.pb = pb;
    this.save = save;
    this.c = c;
    this.img = img;
    img.setVisibility(View.VISIBLE);
    this.percent = percent;
    this.bmp = bmp;
    this.listener = listener;
}

/*--- we need this interface for keeping the reference to our Bitmap from the MainActivity. 
 *  Otherwise, bmp would be null in our MainActivity*/
public interface ImageLoaderListener {

    void onImageDownloaded(Bitmap bmp);

    }

@Override
protected void onPreExecute() {

    progress = 0;
    pb.setVisibility(View.VISIBLE);
    percent.setVisibility(View.VISIBLE);
    //Toast.makeText(c, "Loading images", Toast.LENGTH_SHORT).show();

    super.onPreExecute();
}

@Override
protected Void doInBackground(Void... arg0) {

    bmp = getBitmapFromURL(url);

    while (progress!=0) {

        progress += 100;

        publishProgress(progress);

        /*--- an image download usually happens very fast so you would not notice 
         * how the ProgressBar jumps from 0 to 100 percent. You can use the method below 
         * to visually "slow down" the download and see the progress bein updated ---*/

    }
    save.setEnabled(true);

    return null;
}

@Override
protected void onProgressUpdate(Integer... values) {

/*--- show download progress on main UI thread---*/
    pb.setProgress(values[0]);
    percent.setText("");

    super.onProgressUpdate(values);
}

@Override
protected void onPostExecute(Void result) {

    if (listener != null) {
        listener.onImageDownloaded(bmp);
        }
   //Bitmap b = Bitmap.createScaledBitmap(bmp, 200, 200, false);
    img.setImageBitmap(bmp);
    save.setEnabled(true);
    //Toast.makeText(c, "Download complete", Toast.LENGTH_SHORT).show();

    super.onPostExecute(result);
}


public static Bitmap getBitmapFromURL(String link) {
    /*--- this method downloads an Image from the given URL, 
     *  then decodes and returns a Bitmap object
     ---*/
    try {
        URL url = new URL(link);
        HttpURLConnection connection = (HttpURLConnection) url
                .openConnection();
        connection.setDoInput(true);
        connection.connect();
        InputStream input = connection.getInputStream();
        Bitmap myBitmap = BitmapFactory.decodeStream(input);

        return myBitmap;

    } catch (IOException e) {
        e.printStackTrace();
        Log.e("getBmpFromUrl error: ", e.getMessage().toString());
        return null;
    }
}

     }

2 个答案:

答案 0 :(得分:1)

请看一下这个链接:http://developer.android.com/training/displaying-bitmaps/load-bitmap.html它可能对您有帮助。

您可以尝试使用inJustDecodeBounds并在解码之前获取图像尺寸。喜欢:

BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
InputStream input = connection.getInputStream();
BitmapFactory.decodeStream(input ,null,options);

然后设置最大宽度和高度并对其进行解码。上面有一个示例代码,您可以找到两种方法来执行此操作。

答案 1 :(得分:0)

此错误可以通过代码清理来解决,例如删除全局变量,堆上的字符串对象等。请查看是否可以将全局变量转换为局部变量。

 ProgressBar pb;
 String url;
 Button save;
 Context c;
 int progress;
 ImageView img;
 Bitmap bmp;
 TextView percent;
 ImageLoaderListener listener;