2012-09-08 15 views
5

Sunucudan görüntü indirmek ve listview olarak göstermek için kullanılan bir uygulama oluşturmaya çalışıyorum. Yaptığım sorun, bellek sızıntısıydı ve uygulamamın çökmesine neden oldu. Android blogunda bu link gibi arama yapıyordum, bu harika bir fikir ama yine de birden fazla iş parçacığı ile yapmak için yeterli değil. Android'in bazı aygıtları bununla çalışabilir, ancak bazı aygıtlar yalnızca tek iş parçacığında işleyebilir ve bazen hiç çalışamaz.Sunucudan resim indir ve BitmapFactory kullanmadan sdcard'a kaydet

Uygulamamın birçok etkinliği var ve her birinin görüntüyü olabildiğince hızlı görüntülemesi gereken bir Liste Görünümü var. Google IO 2012 sayesinde orijinal görüntüyü SD karta kaydetmek için arabellek kullanırlar ve Leak belleği sorununu çözer, ancak indirmesi gereken görüntü çok büyük olduğundan yükleme yavaşlatır.

Soruma soru sormak istiyorum: Görüntüyü SD karta yazma görüntüsüyle birlikte ölçeklendirmenin herhangi bir yolu var mı? Bazı olası çözüm, giriş akışı nesnesinde Atlama baytını kullanmanın bir yolunu bulmaya çalışıyorum ve görebilmem için resmin Genişlik ve Yüksekliğini de buldum.

Aşağıdaki kod Google IO 2012'de kullanıldı ve çok sayıda iş parçacığıyla iyi çalışıyor, benim durumumda arka planda 4 iş parçacığı var.

private void downloadAndWriteFile(final String url, final File file) throws OutOfMemoryError { 
    BufferedOutputStream out = null; 

    try { 
     HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection(); 
     conn.setDoInput(true); 
     conn.connect(); 

     final InputStream in = new BufferedInputStream(conn.getInputStream(), IO_BUFFER_SIZE_BYTES); // buffer size 1KB 
     out = new BufferedOutputStream(new FileOutputStream(file), IO_BUFFER_SIZE_BYTES); 

     int b; 
     while ((b = in.read()) != -1) { 
      out.write(b); 
     } 
     out.close(); 
     conn.disconnect(); 
    } 
    catch (Exception e) { 
     Log.e(TAG, "!!downloadAndWriteFile " + e.getMessage()); 
     file.delete(); 
    } 
} 

cevap

1

1) Bu Bitmap ile ilişkili yerli nesneyi serbest bırakıp piksel verilere atıfta temizlemek için resimlerinizi ayarlamadan önce aşağıdaki kodu kullanabilirsiniz. Başka referans yoksa çöp toplanmasını sağlar.

BitmapDrawable drawable = (BitmapDrawable) myImage.getDrawable(); 
Bitmap bitmap = drawable.getBitmap(); 
if (bitmap != null) 
{ 
    bitmap.recycle(); 
} 

2) bellekte bitmap'in boyutunu azaltmak için bu yöntemi kullanın:

/** 
* decodes image and scales it to reduce memory consumption 
* 
* @param file 
* @param requiredSize 
* @return 
*/ 
public static Bitmap decodeFile(File file, int requiredSize) { 
    try { 

     // Decode image size 
     BitmapFactory.Options o = new BitmapFactory.Options(); 
     o.inJustDecodeBounds = true; 
     BitmapFactory.decodeStream(new FileInputStream(file), null, o); 

     // The new size we want to scale to 

     // Find the correct scale value. It should be the power of 2. 
     int width_tmp = o.outWidth, height_tmp = o.outHeight; 
     int scale = 1; 
     while (true) { 
      if (width_tmp/2 < requiredSize 
        || height_tmp/2 < requiredSize) 
       break; 
      width_tmp /= 2; 
      height_tmp /= 2; 
      scale *= 2; 
     } 

     // Decode with inSampleSize 
     BitmapFactory.Options o2 = new BitmapFactory.Options(); 
     o2.inSampleSize = scale; 

     Bitmap bmp = BitmapFactory.decodeStream(new FileInputStream(file), 
       null, o2); 

     return bmp; 

    } catch (FileNotFoundException e) { 
    } finally { 
     System.gc(); 
    } 
    return null; 
} 
+0

Cevabınız için teşekkür ederim, bu durumda zaten vardı, ancak JNI'nin daha fazla bellek ayırmasına izin vermeyen bazı aygıtlar için birden fazla iş parçacığı ile hala bellek sızıyor. Google IO 2012'nin kodu, tüm cihazları destekleyen birden fazla iş parçacığı ile çalışmasını sağlayabilir, ancak görüntünün çok büyük olması durumunda bu kadar yavaştır. Her nasılsa kullanıcı hızlı bir şekilde aktivitede geziniyor, bu yüzden ilk kez yükleme yapıyor, hiç de iyi değil. – vsatkh

0

Bunu kullanabilir.

private void downloadImagesToSdCard(String downloadUrl,String imageName) { 
try { 
    URL url = new URL(downloadUrl); //you can write here any link 

    File myDir = new File("/sdcard"+"/"+Constants.imageFolder); 
    //Something like ("/sdcard/file.mp3") 


    if (!myDir.exists()) { 
     myDir.mkdir(); 
     Log.v("", "inside mkdir"); 

    } 

    Random generator = new Random(); 
    int n = 10000; 
    n = generator.nextInt(n); 
    String fname = imageName; 
    File file = new File (myDir, fname); 
    if (file.exists()) file.delete(); 

     /* Open a connection to that URL. */ 
     URLConnection ucon = url.openConnection(); 
     InputStream inputStream = null; 
     HttpURLConnection httpConn = (HttpURLConnection)ucon; 
     httpConn.setRequestMethod("GET"); 
     httpConn.connect(); 

     if (httpConn.getResponseCode() == HttpURLConnection.HTTP_OK) { 
     inputStream = httpConn.getInputStream(); 
     } 

     /* 
     * Define InputStreams to read from the URLConnection. 
     */ 
     // InputStream is = ucon.getInputStream(); 
     /* 
     * Read bytes to the Buffer until there is nothing more to read(-1). 
     */ 

     FileOutputStream fos = new FileOutputStream(file); 
     int size = 1024*1024; 
     byte[] buf = new byte[size]; 
     int byteRead; 
     while (((byteRead = inputStream.read(buf)) != -1)) { 
      fos.write(buf, 0, byteRead); 
      bytesDownloaded += byteRead; 
     } 
     /* Convert the Bytes read to a String. */ 

     fos.close(); 

} catch(IOException io) { 
    networkException = true; 
    continueRestore = false; 
} catch(Exception e) { 
    continueRestore = false; 
    e.printStackTrace(); 
} 

}

0

Bu kod indir, herhangi android telefonlar kullanmak, onun emülatörü çalışmıyor,

package com.example.filedownload; 


import org.apache.http.util.ByteArrayBuffer; 

import android.os.Bundle; 
import android.app.Activity; 
import android.util.Log; 
import android.view.Menu; 
import android.view.View; 
import android.widget.Button; 
import android.content.*; 
import android.app.*; 
import android.net.*; 
import android.app.DownloadManager.Request; 
import android.os.Environment; 
public class MainActivity extends Activity { 
    public long reference; 
    BroadcastReceiver receiver; 
    @Override 
     protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 


     Button button=(Button)findViewById(R.id.button1); 
       button.setOnClickListener(new View.OnClickListener() { 
       public void onClick(View v) { 


           String file = "http://tmacfitness.com/wp-content/uploads/2013/04/Beauty-of-nature-random-4884759-1280-800.jpg"; 
           String serviceString = Context.DOWNLOAD_SERVICE; 
           DownloadManager downloadManager; 
           downloadManager = (DownloadManager)getSystemService(serviceString); 
           Uri uri = Uri.parse(file); 
           DownloadManager.Request request ; 
           request = new Request(uri); 
           request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "accel.jpg"); 
           reference = downloadManager.enqueue(request); 



       } 

     }); 

     IntentFilter filter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE); 
     receiver = new BroadcastReceiver() { 
     @Override 
     public void onReceive(Context context, Intent intent) { 
     long ref = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1); 
     if (reference == ref) { 
     setContentView(R.layout.finalscreen); 
     unregister(); 
     } 
     } 
     }; 
     registerReceiver(receiver, filter); 
    } 
     public void unregister(){ 
      unregisterReceiver(receiver); 

    } 
} 

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    tools:context=".MainActivity" > 

    <TableLayout 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_alignParentBottom="true" 
     android:layout_alignParentLeft="true" 
     android:layout_alignParentRight="true" 
     android:layout_alignParentTop="true" > 

     <TableRow 
      android:id="@+id/tableRow1" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" > 
     </TableRow> 

     <TableRow 
      android:id="@+id/tableRow2" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" > 

      <CheckedTextView 
       android:id="@+id/checkedTextView1" 
       android:layout_width="wrap_content" 
       android:layout_height="wrap_content" 
       android:text="Accel" /> 

     </TableRow> 

     <TableRow 
      android:id="@+id/tableRow3" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" > 

      <Button 
       android:id="@+id/button1" 
       android:layout_width="wrap_content" 
       android:layout_height="wrap_content" 
       android:text="Button" /> 

     </TableRow> 

     <TableRow 
      android:id="@+id/tableRow4" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" > 
     </TableRow> 
    </TableLayout> 

</RelativeLayout> 

finalscreen bitmap fabrika kullanmadan görüntüleri .xml

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:orientation="vertical" > 

    <TextView 
     android:id="@+id/textView1" 
     android:layout_width="270dp" 
     android:layout_height="wrap_content" 
     android:layout_weight="2.12" 
     android:text="DOWNLOAD COMPLETED" /> 

</LinearLayout>