2012-07-21 2 views
0

아래 클래스는 RSS 피드를 구문 분석하고 AsyncTask를 사용하여 화면에 이미지/텍스트를 그립니다. 나는 NASA RSS 피드를 사용하고있었습니다. 어젯밤에 나는 동일한 피드로 전환했지만 더 큰 이미지로 전환했습니다. 이제 새로 고침 버튼을 누르면 메모리가 부족합니다. 어떻게 처리 할 수 ​​있습니까? 이미지가 너무 커서 (약 6MB, 다른 이미지의 36kb와 비교할 때) 나는 정적이라는 것을 읽었습니다. 정적 인 것처럼 보이지는 않지만, 이미지로 배경 화면을 설정할 때 클래스의 별도 인스턴스로 final_image를 검색해야합니다. 그래서 아래의 모든 것은 작은 이미지로 작동합니다. 큰 이미지를 사용하면 한 번 작동하지만 새로 고침 버튼 (그냥 RssParseSync.execute()가 실행 됨)을 푸시하면 새로 고침에 실패하고 아래 오류가 표시됩니다. 작은 이미지가 배경 화면으로 설정 될 때 정말 나빠 보이기 때문에 큰 이미지를 원합니다.OutOfMemory AsyncTask 및 큰 이미지 사용 중

public class RssParseSync extends AsyncTask<String,String,Bitmap>{ 

     private Activity parent; 
     private ProgressDialog dialog; 
     private static Bitmap final_image; //must be static because a new instance is required to access getFinalImage(); 


     public RssParseSync(Activity parent){this.parent =parent;}//constructor to pass parent activity, need this to call findViewById 

       private XmlPullParser makeParser(){ 

       } 

       @Override 
       protected Bitmap doInBackground(String... info){ 

        URL iotd; 
        int count=info.length; 
        String title="",link="",description="",date=""; 

        System.out.println("Number of params is "+count); 

        try{ 

         iotd = new URL("http://www.nasa.gov/rss/lg_image_of_the_day.rss");//set URl 
         BufferedReader in;//new BufferedReader 
         in = new BufferedReader(new InputStreamReader(iotd.openStream()));//get rss 

         XmlPullParserFactory factory; 
         factory = XmlPullParserFactory.newInstance();//new factory 


         factory.setNamespaceAware(true); 
         XmlPullParser xpp; 
         xpp = factory.newPullParser(); 
         xpp.setInput(in); 

         //rss is now parsed, free to use XmlPullParser functions to move around and evaulate the rss 

         int eventType; 
         eventType = xpp.getEventType();//returns an int which mean different things (START_DOCUMENT,START_TAG,etc) 


        while(eventType!=XmlPullParser.END_DOCUMENT){//while the document has words 

        switch(eventType){ 

         case XmlPullParser.START_DOCUMENT://beginning of xml 
          break; 
         case XmlPullParser.START_TAG://case : at beginning of new tag 
          String tagName=xpp.getName(); 
          System.out.println(tagName+" "+xpp.getDepth()); 

          if(tagName.equals("title")&& xpp.getDepth()==4){//depth is specific to this certain rss feed, there are multiple tags with the same names 
           info[0]=xpp.nextText(); 
           title=info[0]; 

          } 

          if(tagName.equals("description")&& xpp.getDepth()==4){//depth is specific to this certain rss feed, there are multiple tags with the same names 
           info[1]=xpp.nextText(); 
           description=info[1];  
           StringBuilder tabbed=new StringBuilder(description); 
           tabbed.insert(0, "\t"); 
           description=tabbed.toString(); 
           //info[1]=description; 
          } 

          if(tagName.equals("pubDate")){//no depth needed, only one tag is named pubDate 
           info[2]=xpp.nextText(); 
           date=info[2];       
          } 

          if(tagName.equals("enclosure")&&xpp.getDepth()==4){//this is where our image url is. this url is an attribute of the "enclosure" tag 
           //System.out.println("Enclosure has "+xpp.getAttributeCount()); 
           for(int i=0; i<=xpp.getAttributeCount()-1; i++){ 
            System.out.println("in for"); 
            if(xpp.getAttributeName(i).equals("url")){ 
             link=xpp.getAttributeValue(i); 
             info[3]=link; 
             //System.out.println(link); 
            } 
           } 
          } 
          break; 

         } 
         eventType=xpp.next(); 
        }//switch 

         publishProgress(title,description,date,link); 

         in.close();//close BufferedReader 
        } catch (MalformedURLException e){ 
         e.printStackTrace(); 
        }catch(XmlPullParserException e1){ 
         e1.printStackTrace(); 
        }catch(IOException e2){ 
         e2.printStackTrace(); 
        }   
        Bitmap image=getBitmapFromURL(info[3]); 

        return image; 
       } 
       @Override 
       protected void onProgressUpdate(String... progress){ 
        try { 
         System.out.println("onProgressUpdate"); 
         resetDisplay(progress[0],progress[1],progress[2],progress[3]);//feeding parsed rss values, title, description, date, and link 
        } catch (MalformedURLException e) {//both exceptions are thrown by resetDisplay 
         e.printStackTrace(); 
        } catch (IOException e) { 
         e.printStackTrace(); 
        } 

       } 

       protected void onPostExecute(Bitmap image){//error when doing this in resetDisplay.... onPostExecute is invoked by the ui thread so this may be why it works here and not in resetDisplay 
        ImageView imageView=(ImageView) parent.findViewById(R.id.imageDisplay); 
        imageView.setImageBitmap(image); 
        final_image=image; 
        dialog.dismiss(); 

       } 

       protected void onPreExecute(){ 
        dialog=ProgressDialog.show(parent, "Loading", "Loading the image of the day"); 
       } 

       private void resetDisplay(String title, String description,String date, String link) throws MalformedURLException, IOException{ 

        TextView titleView=(TextView) parent.findViewById(R.id.imageTitle); 
        titleView.setText(title); 

        TextView dateView=(TextView) parent.findViewById(R.id.imageDate); 
        dateView.setText(date); 

        TextView descriptionView=(TextView) parent.findViewById(R.id.imageDescription); 
        descriptionView.setText(description); 

       } 

       public Bitmap getBitmapFromURL(String url) { 
        try { 
        Bitmap bitmap=null; 
        InputStream input = new java.net.URL(url).openStream(); 
        bitmap = BitmapFactory.decodeStream(input);//Decode an input stream into a bitmap. If the input stream is null, or cannot be used to decode a bitmap, the function returns null. 
        input.close(); 
        return bitmap; 
        } catch (IOException ioe) { return null; } 

       } 

       public Bitmap getFinalImage(){ 
        return final_image; 
       }; 


    }//class 

가 매우 큰 경우 이미지의 크기를 조정해야

07-20 17:44:18.470: I/System.out(7581): onProgressUpdate 
07-20 17:44:18.770: D/dalvikvm(7581): GC_FOR_ALLOC freed 190K, 3% free 26538K/27299K, paused 46ms 
07-20 17:44:18.770: I/dalvikvm-heap(7581): Forcing collection of SoftReferences for 24107536-byte allocation 
07-20 17:44:18.790: D/dalvikvm(7581): GC_BEFORE_OOM freed 18K, 3% free 26519K/27299K, paused 23ms 
07-20 17:44:18.790: E/dalvikvm-heap(7581): Out of memory on a 24107536-byte allocation. 
07-20 17:44:18.790: I/dalvikvm(7581): "AsyncTask #2" prio=5 tid=13 RUNNABLE 
07-20 17:44:18.790: I/dalvikvm(7581): | group="main" sCount=0 dsCount=0 obj=0x40d6cac8 self=0x2412840 
07-20 17:44:18.790: I/dalvikvm(7581): | sysTid=7646 nice=10 sched=0/0 cgrp=default handle=32889544 
07-20 17:44:18.790: I/dalvikvm(7581): | schedstat=(0 0 0) utm=7 stm=0 core=1 
07-20 17:44:18.790: I/dalvikvm(7581): at android.graphics.BitmapFactory.nativeDecodeStream(Native Method) 
07-20 17:44:18.800: I/dalvikvm(7581): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:719) 
07-20 17:44:18.800: I/dalvikvm(7581): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:791) 
07-20 17:44:18.800: I/dalvikvm(7581): at com.wajumbie.nasadailyimage.RssParseSync.getBitmapFromURL(RssParseSync.java:162) 
07-20 17:44:18.800: I/dalvikvm(7581): at com.wajumbie.nasadailyimage.RssParseSync.doInBackground(RssParseSync.java:116) 
07-20 17:44:18.800: I/dalvikvm(7581): at com.wajumbie.nasadailyimage.RssParseSync.doInBackground(RssParseSync.java:1) 
07-20 17:44:18.800: I/dalvikvm(7581): at android.os.AsyncTask$2.call(AsyncTask.java:264) 
07-20 17:44:18.800: I/dalvikvm(7581): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305) 
07-20 17:44:18.800: I/dalvikvm(7581): at java.util.concurrent.FutureTask.run(FutureTask.java:137) 
07-20 17:44:18.800: I/dalvikvm(7581): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:208) 
07-20 17:44:18.800: I/dalvikvm(7581): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076) 
07-20 17:44:18.800: I/dalvikvm(7581): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569) 
07-20 17:44:18.800: I/dalvikvm(7581): at java.lang.Thread.run(Thread.java:864) 
07-20 17:44:18.800: E/dalvikvm(7581): Out of memory: Heap Size=34019KB, Allocated=26519KB, Limit=49152KB 
07-20 17:44:18.800: E/dalvikvm(7581): Extra info: Footprint=27299KB, Allowed Footprint=34019KB, Trimmed=1212KB 
07-20 17:44:18.800: D/skia(7581): --- decoder->decode returned false 
07-20 17:44:18.800: W/dalvikvm(7581): threadid=13: thread exiting with uncaught exception (group=0x40aa3a08) 
07-20 17:44:18.810: E/AndroidRuntime(7581): FATAL EXCEPTION: AsyncTask #2 
07-20 17:44:18.810: E/AndroidRuntime(7581): java.lang.RuntimeException: An error occured while executing doInBackground() 
07-20 17:44:18.810: E/AndroidRuntime(7581):  at android.os.AsyncTask$3.done(AsyncTask.java:278) 
07-20 17:44:18.810: E/AndroidRuntime(7581):  at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273) 
07-20 17:44:18.810: E/AndroidRuntime(7581):  at java.util.concurrent.FutureTask.setException(FutureTask.java:124) 
07-20 17:44:18.810: E/AndroidRuntime(7581):  at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307) 
07-20 17:44:18.810: E/AndroidRuntime(7581):  at java.util.concurrent.FutureTask.run(FutureTask.java:137) 
07-20 17:44:18.810: E/AndroidRuntime(7581):  at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:208) 
07-20 17:44:18.810: E/AndroidRuntime(7581):  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076) 
07-20 17:44:18.810: E/AndroidRuntime(7581):  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569) 
07-20 17:44:18.810: E/AndroidRuntime(7581):  at java.lang.Thread.run(Thread.java:864) 
07-20 17:44:18.810: E/AndroidRuntime(7581): Caused by: java.lang.OutOfMemoryError: (Heap Size=34019KB, Allocated=26519KB) 
07-20 17:44:18.810: E/AndroidRuntime(7581):  at android.graphics.BitmapFactory.nativeDecodeStream(Native Method) 
07-20 17:44:18.810: E/AndroidRuntime(7581):  at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:719) 
07-20 17:44:18.810: E/AndroidRuntime(7581):  at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:791) 
07-20 17:44:18.810: E/AndroidRuntime(7581):  at com.wajumbie.nasadailyimage.RssParseSync.getBitmapFromURL(RssParseSync.java:162) 
07-20 17:44:18.810: E/AndroidRuntime(7581):  at com.wajumbie.nasadailyimage.RssParseSync.doInBackground(RssParseSync.java:116) 
07-20 17:44:18.810: E/AndroidRuntime(7581):  at com.wajumbie.nasadailyimage.RssParseSync.doInBackground(RssParseSync.java:1) 
07-20 17:44:18.810: E/AndroidRuntime(7581):  at android.os.AsyncTask$2.call(AsyncTask.java:264) 
07-20 17:44:18.810: E/AndroidRuntime(7581):  at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305) 
07-20 17:44:18.810: E/AndroidRuntime(7581):  ... 5 more 
07-20 17:44:19.061: D/OpenGLRenderer(7581): Flushing caches (mode 0) 
07-20 17:44:19.061: D/memalloc(7581): ion: Unmapping buffer base:0x52738000 size:2088960 
07-20 17:44:19.061: D/memalloc(7581): ion: Unmapping buffer base:0x52f7c000 size:2088960 
07-20 17:44:19.061: D/memalloc(7581): ion: Unmapping buffer base:0x53477000 size:2088960 
07-20 17:44:19.081: D/OpenGLRenderer(7581): Flushing caches (mode 0) 
07-20 17:44:19.111: D/memalloc(7581): ion: Unmapping buffer base:0x52bea000 size:524288 
07-20 17:44:19.121: D/memalloc(7581): ion: Unmapping buffer base:0x5367d000 size:524288 
07-20 17:44:19.121: D/memalloc(7581): ion: Unmapping buffer base:0x53326000 size:524288 
07-20 17:44:19.141: D/OpenGLRenderer(7581): Flushing caches (mode 2) 
07-20 17:44:19.181: E/WindowManager(7581): Activity com.wajumbie.nasadailyimage.NasaAppActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView[email protected] that was originally added here 
07-20 17:44:19.181: E/WindowManager(7581): android.view.WindowLeaked: Activity com.wajumbie.nasadailyimage.NasaAppActivity has leaked window [email protected] that was originally added here 
07-20 17:44:19.181: E/WindowManager(7581): at android.view.ViewRootImpl.<init>(ViewRootImpl.java:380) 
07-20 17:44:19.181: E/WindowManager(7581): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:372) 
07-20 17:44:19.181: E/WindowManager(7581): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:320) 
07-20 17:44:19.181: E/WindowManager(7581): at android.view.WindowManagerImpl$CompatModeWrapper.addView(WindowManagerImpl.java:152) 
07-20 17:44:19.181: E/WindowManager(7581): at android.view.Window$LocalWindowManager.addView(Window.java:557) 
07-20 17:44:19.181: E/WindowManager(7581): at android.app.Dialog.show(Dialog.java:301) 
07-20 17:44:19.181: E/WindowManager(7581): at android.app.ProgressDialog.show(ProgressDialog.java:116) 
07-20 17:44:19.181: E/WindowManager(7581): at android.app.ProgressDialog.show(ProgressDialog.java:99) 
07-20 17:44:19.181: E/WindowManager(7581): at android.app.ProgressDialog.show(ProgressDialog.java:94) 
07-20 17:44:19.181: E/WindowManager(7581): at com.wajumbie.nasadailyimage.RssParseSync.onPreExecute(RssParseSync.java:142) 
07-20 17:44:19.181: E/WindowManager(7581): at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:561) 
07-20 17:44:19.181: E/WindowManager(7581): at android.os.AsyncTask.execute(AsyncTask.java:511) 
07-20 17:44:19.181: E/WindowManager(7581): at com.wajumbie.nasadailyimage.NasaDailyImage.onRefresh(NasaDailyImage.java:57) 
07-20 17:44:19.181: E/WindowManager(7581): at com.wajumbie.nasadailyimage.NasaAppActivity$1.run(NasaAppActivity.java:48) 
07-20 17:44:19.181: E/WindowManager(7581): at com.wajumbie.nasadailyimage.NasaAppActivity.onRefreshClicked(NasaAppActivity.java:51) 
07-20 17:44:19.181: E/WindowManager(7581): at java.lang.reflect.Method.invokeNative(Native Method) 
07-20 17:44:19.181: E/WindowManager(7581): at java.lang.reflect.Method.invoke(Method.java:511) 
07-20 17:44:19.181: E/WindowManager(7581): at android.view.View$1.onClick(View.java:3066) 
07-20 17:44:19.181: E/WindowManager(7581): at android.view.View.performClick(View.java:3538) 
07-20 17:44:19.181: E/WindowManager(7581): at android.view.View$PerformClick.run(View.java:14330) 
07-20 17:44:19.181: E/WindowManager(7581): at android.os.Handler.handleCallback(Handler.java:607) 
07-20 17:44:19.181: E/WindowManager(7581): at android.os.Handler.dispatchMessage(Handler.java:92) 
07-20 17:44:19.181: E/WindowManager(7581): at android.os.Looper.loop(Looper.java:156) 
07-20 17:44:19.181: E/WindowManager(7581): at android.app.ActivityThread.main(ActivityThread.java:5008) 
07-20 17:44:19.181: E/WindowManager(7581): at java.lang.reflect.Method.invokeNative(Native Method) 
07-20 17:44:19.181: E/WindowManager(7581): at java.lang.reflect.Method.invoke(Method.java:511) 
07-20 17:44:19.181: E/WindowManager(7581): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784) 
07-20 17:44:19.181: E/WindowManager(7581): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551) 
07-20 17:44:19.181: E/WindowManager(7581): at dalvik.system.NativeStart.main(Native Method) 

답변

3

로그인 로그 캣

public void onRefresh(){ 
    System.out.println("in onRefresh"); 
    new RssParseSync(getActivity()).execute(title,description,date,link); 
} 

새로 고침 방법.

다음과 같이 : 나는 그것을 알아 낸

BitmapFactory.Options options = new BitmapFactory.Options(); 
options.inJustDecodeBounds = true; 
BitmapFactory.decodeStream(new URL(imageUrl).openStream(),null,options); 
//use your required height and width in place of 80 (size of imageview maybe) 
options.inSampleSize = calculateInSampleSize(options,80, 80); 
options.inJustDecodeBounds = false; 
Bitmap bmp = BitmapFactory.decodeStream(new URL(imageUrl).openStream(),null,options); 


public int calculateInSampleSize(BitmapFactory.Options options, 
     int reqWidth, int reqHeight) { 
    // Raw height and width of image 
    final int height = options.outHeight; 
    final int width = options.outWidth; 
    int inSampleSize = 1; 

    if (height > reqHeight || width > reqWidth) { 
     if (width > height) { 
      inSampleSize = Math.round((float) height/(float) reqHeight); 
     } else { 
      inSampleSize = Math.round((float) width/(float) reqWidth); 
     } 
    } 
    return inSampleSize; 
} 
+0

나는 커다란 이미지를 원한다. –

+0

그런 다음 배경 화면의 크기에 따라 크기를 조절할 수 있습니다. 여전히 선명하게 보입니다. 액티비티의 getWindowManager() 함수를 사용하여 화면의 크기를 가져올 수 있습니다. – dharmin007

+0

우수, 고맙습니다. –

0

, 난 그냥 onPreExecute에서 bitmap.recycle() 메소드를 사용했다. 이렇게 할 수있는 더 좋은 방법이있을 것이라고 확신합니다.하지만이 방법이 효과적입니다.

protected void onPreExecute(){ 
    if(final_image!=null){ 

     final_image.recycle(); 

    } 

    dialog=ProgressDialog.show(parent, "Loading", "Loading the image of the day"); 
       }