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

Java 内存不足(堆)问题无法修复,java,android,out-of-memory,heap-memory,Java,Android,Out Of Memory,Heap Memory,嘿,我花了很多时间来修复下面代码中出现的错误。 错误是由于内存不足(堆)。 到现在为止,我还没有找到任何解决办法(这是第三天,我正在寻找它,真的很累:() 有人请告诉我一个好的解决办法 活动\u preview.xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:ads="http://schemas.android.com/apk/lib/com.google.a

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

活动\u 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>
ImageDownloader.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();
        }


    }

}
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;
    }
}

     }
package com.hitbytes.nfswallpapers;
导入java.io.IOException;
导入java.io.InputStream;
导入java.net.HttpURLConnection;
导入java.net.URL;
导入android.content.Context;
导入android.graphics.Bitmap;
导入android.graphics.BitmapFactory;
导入android.os.AsyncTask;
导入android.os.SystemClock;
导入android.util.Log;
导入android.view.view;
导入android.widget.Button;
导入android.widget.ImageView;
导入android.widget.ProgressBar;
导入android.widget.TextView;
导入android.widget.Toast;
公共类ImageDownloader扩展异步任务{
ProgressBar-pb;
字符串url;
按钮保存;
上下文c;
智力进步;
图像视图img;
位图bmp;
文本视图百分比;
ImageLoaderListener侦听器;
/*---建造师---*/
公共图像下载程序(字符串url、进度条pb、按钮保存、,
ImageView img、TextView百分比、上下文c、位图bmp、ImageLoaderListener侦听器){
/*---我们需要传递一些要处理的对象---*/
this.url=url;
这是1.pb=pb;
this.save=保存;
这个.c=c;
this.img=img;
img.setVisibility(视图可见);
这个百分比=百分比;
this.bmp=bmp;
this.listener=listener;
}
/*---我们需要这个接口来保持对位图的引用不受main活动的影响。
*否则,bmp将在我们的MainActivity中为null*/
公共接口ImageLoaderListener{
已下载的图像无效(位图bmp);
}
@凌驾
受保护的void onPreExecute(){
进度=0;
pb.setVisibility(View.VISIBLE);
百分比设置可见性(视图可见);
//Toast.makeText(c,“加载图像”,Toast.LENGTH_SHORT).show();
super.onPreExecute();
}
@凌驾
受保护的Void doInBackground(Void…arg0){
bmp=getBitmapFromURL(url);
while(进度!=0){
进度+=100;
出版进度(progress);
/*---图像下载通常发生得非常快,所以您不会注意到
*进度条如何从0%跳到100%。您可以使用下面的方法
*以可视化方式“减慢”下载速度并查看更新的进度---*/
}
save.setEnabled(true);
返回null;
}
@凌驾
受保护的void onProgressUpdate(整型…值){
/*---显示主UI线程上的下载进度---*/
pb.setProgress(值[0]);
百分比。setText(“”);
super.onProgressUpdate(值);
}
@凌驾
受保护的void onPostExecute(void结果){
if(侦听器!=null){
下载的listener.onimage(bmp);
}
//位图b=位图.createScaledBitmap(bmp,200,200,false);
设置图像位图(bmp);
save.setEnabled(true);
//Toast.makeText(c,“下载完成”,Toast.LENGTH_SHORT.show();
super.onPostExecute(结果);
}
公共静态位图getBitmapFromURL(字符串链接){
/*---此方法从给定URL下载图像,
*然后解码并返回位图对象
---*/
试一试{
URL=新的URL(链接);
HttpURLConnection连接=(HttpURLConnection)url
.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream输入=连接。getInputStream();
位图myBitmap=BitmapFactory.decodeStream(输入);
返回我的位图;
}捕获(IOE异常){
e、 printStackTrace();
Log.e(“getBmpFromUrl错误:”,e.getMessage().toString());
返回null;
}
}
}

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

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

看看这个链接:它可能会帮助你

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

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

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

在emulator上运行时不会出现错误。因为它有更多堆大小。但在设备上,我面临此问题。请检查此链接,我认为我的设备堆大小小于24。