2017-03-15 44 views
0

我有一個活動,顯示像8個圖像,所以我不得不使用這個代碼,以避免outOfMemory在一些情況下工作正常。decodeSizedBitmap避免outOfMemory沒有工作

public static 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) { 
     final int halfHeight = height/2; 
     final int halfWidth = width/2; 

     // Calculate the largest inSampleSize value that is a power of 2 and keeps both 
     // height and width larger than the requested height and width. 
     while ((halfHeight/inSampleSize) >= reqHeight 
       && (halfWidth/inSampleSize) >= reqWidth) { 
      inSampleSize *= 2; 
     } 
    } 

    return inSampleSize; 
} 
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, 
                int reqWidth, int reqHeight) { 

    // First decode with inJustDecodeBounds=true to check dimensions 
    final BitmapFactory.Options options = new BitmapFactory.Options(); 
    options.inJustDecodeBounds = true; 
    BitmapFactory.decodeResource(res, resId, options); 

    // Calculate inSampleSize 
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); 

    // Decode bitmap with inSampleSize set 
    options.inJustDecodeBounds = false; 
    return BitmapFactory.decodeResource(res, resId, options); 
} 

能正常工作在此佈局

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
xmlns:app="http://schemas.android.com/apk/res-auto" 
xmlns:tools="http://schemas.android.com/tools" 
android:weightSum="1" 
android:layout_width="match_parent" 
android:padding="10dp" 
android:layout_height="match_parent" 
app:layout_behavior="@string/appbar_scrolling_view_behavior" 
tools:context="com.fahrul.pesantrenbahrululum.FotoPerdivisi" 
android:orientation="vertical" 
tools:showIn="@layout/app_bar_foto_perdivisi"> 
<ScrollView 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:layout_alignParentTop="true" 
    android:layout_alignParentStart="true"> 
    <LinearLayout 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:orientation="horizontal"> 
     <LinearLayout 
      android:id="@+id/kiriFotoPerdivisi" 
      android:layout_width="150dp" 
      android:layout_height="wrap_content" 
      android:orientation="vertical"> 
     </LinearLayout> 
     <LinearLayout 
      android:id="@+id/kananFotoPerdivisi" 
      android:layout_width="150dp" 
      android:layout_height="wrap_content" 
      android:orientation="vertical"> 
     </LinearLayout> 
    </LinearLayout> 
</ScrollView> 
</LinearLayout> 

這裏是Java代碼

public class FotoPerdivisi extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener, ImageView.OnClickListener{ 
    LinearLayout kiriLay, kananLay; 
    public int[] imageIds={ 
      R.drawable.foto_perdivisi1,R.drawable.foto_perdivisi2,R.drawable.foto_perdivisi3,R.drawable.foto_perdivisi4, 
      R.drawable.foto_perdivisi5,R.drawable.foto_perdivisi6,R.drawable.foto_perdivisi7 
    }; 
    public int[] Ids={ 
      R.id.img1,R.id.img2,R.id.img3,R.id.img4,R.id.img5,R.id.img6,R.id.img7 
    }; 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_foto_perdivisi); 
     Toolbar toolbar = (Toolbar) findViewById(R.id.toolbarFotoPerdivisi); 
     setSupportActionBar(toolbar); 
     DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_foto_perdivisi); 
     ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
       this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); 
     drawer.setDrawerListener(toggle); 
     toggle.syncState(); 
     NavigationView navigationView = (NavigationView) findViewById(R.id.nav_foto_perdivisi); 
     navigationView.setNavigationItemSelectedListener(this); 
     kiriLay = (LinearLayout)findViewById(R.id.kiriFotoPerdivisi); 
     kananLay = (LinearLayout)findViewById(R.id.kananFotoPerdivisi); 
//  NavigationView navigationView = (NavigationView) findViewById(R.id.nav_foto_perdivisi); 
//  navigationView.setNavigationItemSelectedListener(this); 
//  RecyclerView recyclerView = (RecyclerView)findViewById(R.id.foto_perdivisiGrid); 
//  recyclerView.setHasFixedSize(true); 
//  RecyclerView.LayoutManager layoutManager = new GridLayoutManager(getApplicationContext(),2); 
//  recyclerView.setLayoutManager(layoutManager); 
//  ArrayList<CreateList> createLists = prepareData(); 
//  MyAdapter adapter = new MyAdapter(getApplicationContext(),createLists); 
//  recyclerView.setAdapter(adapter); 
     prepareLayout(); 
    } 
    public static 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) { 

      final int halfHeight = height/2; 
      final int halfWidth = width/2; 

      // Calculate the largest inSampleSize value that is a power of 2 and keeps both 
      // height and width larger than the requested height and width. 
      while ((halfHeight/inSampleSize) >= reqHeight 
        && (halfWidth/inSampleSize) >= reqWidth) { 
       inSampleSize *= 2; 
      } 
     } 

     return inSampleSize; 
    } 
    public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, 
                 int reqWidth, int reqHeight) { 

     // First decode with inJustDecodeBounds=true to check dimensions 
     final BitmapFactory.Options options = new BitmapFactory.Options(); 
     options.inJustDecodeBounds = true; 
     BitmapFactory.decodeResource(res, resId, options); 

     // Calculate inSampleSize 
     options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); 

     // Decode bitmap with inSampleSize set 
     options.inJustDecodeBounds = false; 
     return BitmapFactory.decodeResource(res, resId, options); 
    } 

    public void prepareLayout(){ 
     for(int i = 0; i < imageIds.length;i++) { 
      ImageView img = new ImageView(this); 
      LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, (int) (150 * getResources().getDisplayMetrics().density)); 
      img.setLayoutParams(params); 
      img.setScaleType(ImageView.ScaleType.CENTER_CROP); 
      img.setOnClickListener(this); 
      img.setImageBitmap(decodeSampledBitmapFromResource(getResources(),imageIds[i],params.width/2,params.height/2)); 
      img.setId(Ids[i]); 
      if (i % 2==0) { 
       kiriLay.addView(img); 
      } else{ 
       kananLay.addView(img); 
      } 
     } 
    } 
    @Override 
    public void onBackPressed() { 
     DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_foto_perdivisi); 
     if (drawer.isDrawerOpen(GravityCompat.START)) { 
      drawer.closeDrawer(GravityCompat.START); 
     } else { 
      super.onBackPressed(); 
     } 
    } 

    @SuppressWarnings("StatementWithEmptyBody") 
    @Override 
    public boolean onNavigationItemSelected(MenuItem item) { 
     // Handle navigation view item clicks here. 
     int id = item.getItemId(); 

     if (id == R.id.nav_home) { 
      Intent intent = new Intent(getApplicationContext(),MainActivity.class); 
      intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
      startActivity(intent); 
     } else if (id == R.id.nav_daftar) { 
      Intent intent = new Intent(getApplicationContext(),DaftarIsiActivity.class); 
      intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
      startActivity(intent); 
     } else if (id == R.id.nav_foto) { 
      Intent intent = new Intent(getApplicationContext(),Gallery.class); 
      intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
      startActivity(intent); 
     } else if (id == R.id.nav_info) { 
      Intent intent = new Intent(getApplicationContext(),InfoActivity.class); 
      intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
      startActivity(intent); 
     } else if (id == R.id.nav_exit) { 
      System.exit(0); 
     } 

     DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_foto_perdivisi); 
     drawer.closeDrawer(GravityCompat.START); 
     return true; 
    } 

    @Override 
    public void onClick(View view) { 
     Intent intent = new Intent(getApplicationContext(),ImageViewer.class); 
     intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
     ImageView img = (ImageView)view; 
     for(int i = 0; i < Ids.length; i++){ 
      if(img.getId() == Ids[i]) { 
       intent.putExtra("position", i); 
      } 
     } 
     intent.putExtra("curUse",1); 
     startActivity(intent); 
    } 
} 

,但如果我改變線性佈局參數 的android:layout_width = 「0dp」 android:layout_weight =「0.5」 該代碼沒有工作,我認爲它是因爲在layoutParams的寬度是0,這導致了arithmati cal錯誤。 如何避免outOfMemoryException並將佈局參數保持爲android:layout_width =「0dp」 android:layout_weight =「0.5」? 感謝任何迴應

回答

0

的我不得不使用這個代碼,以避免內存不足,在某些情況下, 工作正常。

我也遇到了很多關於圖像緩存和加載的問題。也用於decodeSampledBitmapFromResource。但相信我Glide/Picasso是超級簡單。您只需添加3或4行,而不是使用複雜方法calculateInSampleSizedecodeSampledBitmapFromResource

GLIDE添加到您的項目:

首先加入應用gradle這個依賴:然後在你的prepareLayout()方法

dependencies { 
    compile 'com.github.bumptech.glide:glide:3.7.0' 
} 

替換以下行

img.setImageBitmap(decodeSampledBitmapFromResource(getResources(),imageIds[i],params.width/2,params.height/2)); 
      img.setId(Ids[i]); 

附:

Glide.with(this).load(R.id.img1).into(imageView); //As example 

使用GLIDE看看here

希望這會有所幫助。

+1

謝謝,我不知道這是一個外部庫 –

+0

歡迎,很高興它幫助 – tahsinRupam

0

你的問題是視圖還沒有佈局,所以沒有它的最終尺寸(getHeight()和getWidth()將返回0)。
decodeSampledBitmapFromResource需要這些尺寸來確定它應該加載位圖的大小。

解決的辦法是等待佈局傳遞發生之前解碼圖像:

// place a runnable at the end of the message queue, after the layout pass. 
    getWindow().getDecorView().post(new Runnable() { 
     @Override 
     public void run() { 
      prepareLayout(); 
     } 
    }); 

還要確保真正正確的尺寸傳遞給decodeSampledBitmapFromResource。例如,不是MATCH_PARENT常量,而是父級的實際高度。

相關問題