2015-05-13 18 views
0

我從數據庫中獲取圖像以便將自定義的ListView放入圖像。Android獲取Blob自定義ListView

我的應用程序不崩潰,但圖像不衝擊片雷管。我從日誌中得到了這個錯誤:

E/BitmapFactory﹕ Unable to decode stream: java.io.FileNotFoundException: /[[email protected]: open failed: ENOENT (No such file or directory) 

對不起,我會嘗試清楚我的問題。

哪裏是我的代碼:

DBhelper.java

該函數返回我MatrixCursor的所有數據。

public MatrixCursor retriveCntDetails() throws SQLException { 

     MatrixCursor mMatrixCursor = new MatrixCursor(new String[]{"_id", "name", "number", "photo"}); 
     Cursor cur = mDb.rawQuery("select * from " + CONTACT_TABLE + "", null); 

     if (cur.moveToFirst()) { 
      do { 
       mMatrixCursor.addRow(new Object[]{Long.toString(cur.getLong(cur.getColumnIndex(CNT_ID))), 
         cur.getString(cur.getColumnIndex(CNT_NAME)), 
         cur.getString(cur.getColumnIndex(CNT_NUMBER)), 
         cur.getBlob(cur.getColumnIndex(CNT_PHOTO)) 
       }); 
      } while (cur.moveToNext()); 
     } 
     cur.close(); 

     return mMatrixCursor; 
    } 

HomeActivity.java

在該功能我填寫我的自定義的ListView。

public void FillListView() { 

     SimpleCursorAdapter adap; 

     // Getting reference to listview 
     ListView lstContacts = (ListView) findViewById(R.id.lst_contacts); 

     DBhelper dh = new DBhelper(this); 
     dh.open(); 
     MatrixCursor Mcursor = dh.retriveCntDetails(); 
     dh.close(); 

     adap = new SimpleCursorAdapter(getBaseContext(), 
       R.layout.lv_layout, 
       null, 
       new String[]{"name", "number", "photo"}, 
       new int[]{R.id.tv_name, R.id.tv_number, R.id.iv_photo}, 0); 


     // Setting the adapter to listview 
     lstContacts.setAdapter(adap); 

     // Setting the cursor containing contacts to listview 
     adap.swapCursor(Mcursor); 
    } 
+0

請看看'SimpleCursorAdapter'源... defualt ImageViews(在行佈局)只能加載URL(如果列是字符串)或加載資源的id(如果列是int) ...你需要使用自定義的'SimpleCursorAdapter.ViewBinder'(這很簡單,你應該通過簡單的谷歌搜索找到一些資源)...... **編輯:**爲什麼你使用'MatrixCursor'而不是光標'mDb。 rawQuery'返回? – Selvin

+0

@Selvin謝謝你的建議,我會試着找到一些東西。 – Azazel

+0

'new SimpleCursorAdapter.ViewBinder(){@Override public boolean setViewValue(View view,Cursor cursor,int columnIndex){if(view.getId()== R.id.iv_photo){byte [] data = cursor.getBlob( columnIndex);/*然後從「數據」解碼位圖(在不同的線程上執行此操作會很好......但爲了測試原因,您可以嘗試不使用它),將「視圖」投射到ImageView並將位圖設置爲它* /返回true ; } return false;/*其他視圖使用默認實現* /}' – Selvin

回答

1

感謝@Selvin這個答案 - 我只是要詳細一點,以使其更清晰,爲您和將來的用戶不熟悉的Android。

Cursor對象,在您的示例中爲MatrixCursor,是數據行的容器。 Adapter對象(在您的示例中爲SimpleCursorAdapter)會將這些行/數據「綁定」到可以在屏幕上顯示的視圖。適配器的聲明是:

adap = new SimpleCursorAdapter(
    getBaseContext(), 
    R.layout.lv_layout, 
    null, 
    new String[]{"name", "number", "photo"}, 
    new int[]{R.id.tv_name, R.id.tv_number, R.id.iv_photo}, 
    0 
); 

這意味着:

製作將使用「lv_layout」爲每行一個適配器。內 每一行中,「號碼」列中的「照片」列綁定「名稱」欄與 ID「tv_name」視圖的值,對ID爲「tv_number」視圖和 與ID的視圖「 iv_photo」。

你的問題是,它的SimpleCursorAdapter類嘗試做這個「結合」爲ImageView情況下,當被綁定的值是一個網址,而不是當它的二進制數據的BLOB只能默認的方式。這就是爲什麼你得到一個java.io.FileNotFoundException,默認的適配器試圖使用你的blob數據作爲圖像文件的URL。

你需要做的是自定義綁定步驟。要做到這一點,請與適配器的setViewBinder方法是這樣的:

adap.setViewBinder(new SimpleCursorAdapter.ViewBinder() { 
    @Override 
    public boolean setViewValue(View view, Cursor cursor, int i) { 
     if (view.getId() == R.id.iv_photo) { 
      byte[] data = cursor.getBlob(i); 

      Bitmap bitmap = null; 
      // TODO: decode blob data - should be done off UI thread. 

      ((ImageView) view).setImageBitmap(bitmap); 
      // Return true to signal that the value was bound to a view 
      // successfully. 
      return true; 
     } else { 
      // Return false for all other views and let the default 
      // binder deal with them. 
      return false; 
     } 
    } 
}); 

在上面的代碼中,我還沒有介紹如何真正做到位圖解碼。正如@Selvin指出的,理想情況下應該在UI線程之外完成。檢查出:Processing Bitmaps Off the UI Thread | Android Developers

+0

感謝您的幫助,但您可以將該代碼應用於我的代碼?會更容易理解,因爲我以前從未使用過。謝謝。 – Azazel

+0

我想你可以在'lstContacts.setAdapter(adap);'之前聲明'adap'後複製整個第二個代碼片段。但是你仍然需要填寫'TODO:解碼blob數據' - 我不確定如何去查看。 –

+0

當我填充MatrixCursor時,它的possivel插入你的代碼? – Azazel