2012-06-11 43 views
2

我正在開發一個應用程序,它將從相機拍攝的圖像首先保存在sqlite3數據庫中,然後將其恢復爲將其設置爲imageview。我在vm中出現了知名的內存不足錯誤。我試着在各種其他問題找到像不同的方式:奇怪的行爲,同時在Android設置imageview位圖

protected void onDestroy() { 
     // TODO Auto-generated method stub 
     super.onDestroy(); 
     unbindDrawables(findViewById(R.id.showDataViewRoot)); 
     System.gc(); 

    } 

他們奇怪的是沒有相當的工作 1)

So you

either need to encourage the imageView to recycle the previous bitmap - possibly with setImageView("") 
or get the bitmap from the URI and use setImageBitmap(android.graphics.Bitmap) instead; then you can do 

setImageBitmap(null) and bitmap.recycle().

2)

((BitmapDrawable)imageView.getDrawable()).getBitmap().recycle(); 

3),並且誤差保持出現。主要是因爲錯誤在第一次嘗試顯示圖像本身(所以沒有機會回收我猜)。當搜索,我發現以下鏈接: http://www.vogella.com/articles/AndroidCamera/article.html#example 從那裏以提示我做了以下變化:

imageView.setImageBitmap(BitmapFactory.decodeStream(new FileInputStream(path))); 

Compelete修改後的代碼爲我的ShowData.java(帶有註釋以前的​​嘗試)。在fillImage()中設置圖像的代碼:

package org.dheeraj.imnci; 

import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.util.ArrayList; 

import android.app.Activity; 
import android.database.Cursor; 
import android.database.sqlite.SQLiteDatabase; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.graphics.drawable.BitmapDrawable; 
import android.net.Uri; 
import android.os.Bundle; 
import android.util.Log; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.AdapterView; 
import android.widget.AdapterView.OnItemSelectedListener; 
import android.widget.ArrayAdapter; 
import android.widget.ImageView; 
import android.widget.Spinner; 
import android.widget.TableLayout; 
import android.widget.TableRow; 
import android.widget.TextView; 

public class ShowData extends Activity { 
    private Spinner spinnerId; 
    private DbHelper dbHelper; 
    private SQLiteDatabase dbReader; 
    private Cursor cursor; 
    private ArrayList<String> idList; 
    private ArrayAdapter<String> adapter; 
    private String id; 
    private TableLayout dataTable; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     // TODO Auto-generated method stub 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.show_data); 
     dbHelper = new DbHelper(this); 
     spinnerId = (Spinner) findViewById(R.id.spinnerData); 
     dataTable = (TableLayout) findViewById(R.id.tableShowData); 
     fillSpinner(); 

    } 

    private void fillData(String id) { 
     String tableNames[] = { "mother_reg", "anc_02", "anc_03", "anc_04", 
       "tt1", "tt2", "ttb", "abortions", "po", "pnc", "ifa" }; 
     for (String table : tableNames) { 
      getDataFromTable(table, id); 
     } 
    } 

    private void getDataFromTable(String table, String id) { 
     // TODO Auto-generated method stub 

     getTableTitle(table); 
     getTableColumns(table, id); 
    } 

    private void getTableColumns(String table, String id) { 
     // TODO Auto-generated method stub 
     SQLiteDatabase dbReader; 
     Cursor cursor; 
     TableRow colRow; 
     TextView labelView; 
     TextView valueView; 
     String label; 
     String value; 

     dbReader = dbHelper.getReadableDatabase(); 
     try { 
      if (table.equals("mother_reg")) 
       cursor = dbReader.query(table, null, "mid=" + id, null, null, 
         null, null, null); 
      else 
       cursor = dbReader.query(table, null, "ID=" + id, null, null, 
         null, null, null); 

      Log.d("getTableColumns", table); 
      if (cursor.moveToFirst()) { 
       do { 
        Log.d("in cursor", "" + cursor.getColumnCount()); 
        for (int i = 0; i < cursor.getColumnCount(); i++) { 
         label = cursor.getColumnName(i); 
         value = cursor.getString(i); 

         labelView = new TextView(this); 
         valueView = new TextView(this); 
         colRow = new TableRow(this); 

         labelView.setText(label); 
         valueView.setText(value); 
         colRow.addView(labelView); 
         colRow.addView(valueView); 
         dataTable.addView(colRow); 
        } 

       } while (cursor.moveToNext()); 

      } 
      cursor.close(); 
     } finally { 
      if (dbReader != null) 
       dbReader.close(); 
     } 
    } 

    private void getTableTitle(String table) { 
     // TODO Auto-generated method stub 
     TableRow tabRow; 
     TextView tv; 
     String title = table.replace('_', ' ').toUpperCase(); 
     tabRow = new TableRow(this); 
     tv = new TextView(this); 
     tv.setText(title); 
     tv.setTextSize(20); 
     tabRow.addView(tv); 
     dataTable.addView(tabRow); 
    } 

    private void fillImage(String id) { 
     // TODO Auto-generated method stub 

     ImageView imageView; 
     boolean picFound; 

     SQLiteDatabase dbReader; 
     Cursor cursor; 

     String path = null; 

     imageView = (ImageView) findViewById(R.id.showDataImage); 

     picFound = false; 
     dbReader = dbHelper.getReadableDatabase(); 
     try { 
      String tableName = "pictures"; 
      String[] columns = { "mid", "uri" }; 
      Log.d("id value", "" + id); 
      cursor = dbReader.query(tableName, columns, "mid=" + id, null, 
        null, null, null, null); 
      Log.d("gotCursor", "foundcursor"); 
      if (cursor.moveToFirst()) { 

       Log.d("in cursor", "" + cursor.getColumnCount()); 
       path = cursor.getString(cursor.getColumnIndex("uri")); 
       Log.d("show_data:imagepath", path); 
       if (path != null) 
        picFound = true; 
       // imgUri = Uri.parse(new File(path).toString()); 
       /* 
       * bmpImage = BitmapFactory.decodeFile(path); 
       * 
       * 
       * 
       * scaledBmp = Bitmap.createScaledBitmap(bmpImage, 100, 150, 
       * true); bmpImage.recycle(); bmpImage = null; 
       */ 

      } 
      cursor.close(); 
     } finally { 
      if (dbReader != null) 
       dbReader.close(); 
     } 

     if (!picFound) 
      imageView.setImageResource(R.drawable.default_user); 
     else { 
      // Log.d("inimageview", imgUri.toString()); 

      try { 
       imageView.setImageBitmap(BitmapFactory.decodeStream(new FileInputStream(path))); 
      } catch (FileNotFoundException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 

     } 
     // LayoutParams lv = new LayoutParams(200, 300); 
     // imgRow.setLayoutParams(lv); 

    } 

    @Override 
    protected void onDestroy() { 
     // TODO Auto-generated method stub 
     super.onDestroy(); 
     unbindDrawables(findViewById(R.id.showDataViewRoot)); 
     System.gc(); 

    } 

    private void unbindDrawables(View view) { 
     if (view.getBackground() != null) { 
      view.getBackground().setCallback(null); 
     } 
     if (view instanceof ViewGroup && !(view instanceof AdapterView)) { 
      for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) { 
       unbindDrawables(((ViewGroup) view).getChildAt(i)); 
      } 
      ((ViewGroup) view).removeAllViews(); 
     } 
    } 

    @Override 
    protected void onPause() { 
     // TODO Auto-generated method stub 
     super.onDestroy(); 
     unbindDrawables(findViewById(R.id.showDataViewRoot)); 
     System.gc(); 
    } 

    void fillSpinner() { 
     dbReader = dbHelper.getReadableDatabase(); 
     String columns[] = { "mid" }; 

     try { 
      cursor = dbReader.query("mother_reg", columns, null, null, null, 
        null, "mid DESC"); 
      if (cursor.moveToFirst()) { 
       idList = new ArrayList<String>(); 
       do { 
        idList.add(cursor.getString(cursor.getColumnIndex("mid"))); 
       } while (cursor.moveToNext()); 
       cursor.close(); 

       adapter = new ArrayAdapter<String>(this, 
         android.R.layout.simple_spinner_item, idList); 
       adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 
       spinnerId.setAdapter(adapter); 
       spinnerId 
         .setOnItemSelectedListener(new OnItemSelectedListener() { 

          @Override 
          public void onItemSelected(AdapterView<?> arg0, 
            View arg1, int arg2, long arg3) { 
           // TODO Auto-generated method stub 
           id = arg0.getItemAtPosition(arg2).toString(); 
           // dataTable.removeAllViews(); 
           unbindDrawables(dataTable); 
           fillImage(id); 
           fillData(id); 
          } 

          @Override 
          public void onNothingSelected(AdapterView<?> arg0) { 
           // TODO Auto-generated method stub 

          } 
         }); 
      } 
     } finally { 
      if (dbReader != null) 
       dbReader.close(); 
     } 
    } 
} 

我不明白的是它是如何工作的。如同在imageview.setimageuri(Uri.parse(path))中直接使用文件一樣,採用inputstream是否會減小大小,或者它使用某種緩衝區?只是想知道出了什麼問題。請告訴我是否需要更多關於我的應用代碼的信息。但是這個奇怪的記憶問題讓我很困惑,而且我對在不同線索中提到的很多方法感到困惑。 有關我的應用程序的更多信息: 目標api:1.6 mid SDK版本:4

編輯1:我非常抱歉,但在使用ShowData進行一些試驗後,此方法也失敗。以下是Logcat的屏幕截圖: enter image description here 現在我真的很困惑。只是如何在我的imageview中顯示由SD卡中的相機保存的簡單圖像?我衷心感謝任何形式的幫助。

編輯2:嘗試在fillimage觀點方法一些變化:

 try { 
      if(((BitmapDrawable)imageView.getDrawable())!=null) 
      ((BitmapDrawable)imageView.getDrawable()).getBitmap().recycle(); 



      imageView.setImageBitmap(BitmapFactory.decodeStream(new FileInputStream(path))); 
     } catch (FileNotFoundException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

它現在工作順利進行。只有一次,它給了以下錯誤: enter image description here 我真的很想去這個問題的根源,現在。請提供任何指導。我對這麼多的編輯感到抱歉,但我想不斷告知任何進一步的進展。

回答

1

如果要全屏顯示單張圖像,請使用Intent開始活動。ACTION_VIEW:

Intent i = new Intent(Intent.ACTION_VIEW); 
i.setDataAndType(uri, "image/jpeg"); 
startActivity(i); 

如果你想顯示縮略圖,然後減少二次抽樣這些圖像的大小,只需將此選項添加到BitmapFactory: http://developer.android.com/reference/android/graphics/BitmapFactory.Options.html#inSampleSize

編輯1:

有很好的文檔:
按照你的第二個問題:

Bitmap oldBitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap(); 
imageView.setImageDrawable(null); //this should help 
oldBitmap.recycle(); 
imageView.setImageBitmap(newBitmap); 
+0

感謝@dziobas您的回覆。不過,我只想在特別的imageview中顯示數據表。以下是我使用的意圖:'intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); \t \t \t \t intent.putExtra(MediaStore.EXTRA_OUTPUT,imgURI); \t \t \t \t startActivityForResult(intent,REQ_CODE);'有沒有什麼問題。並感謝鏈接將通過並報告儘快。 – dheerajSuthar

+0

我剛編輯我的答案 – pawelzieba

+1

doc中的信息工作就像魅力!我現在也明白了原因。首先總結一下,我們必須通過設置合適的選項(inJustDecodeBounds)來獲取圖像的尺寸而不實際加載圖像(這就是'雞和雞蛋'問題所在的地方)。然後獲取縮放因子。再次取消設置選項標誌。然後重新採樣到所需大小的圖像並在imageview中使用。 doc鏈接中的@dziobas競爭細節。再次感謝先生。 – dheerajSuthar