Получить изображение из базы данных SQLite и показать в ListView - PullRequest
0 голосов
/ 04 декабря 2018

Застрял с проблемой.Я новичок в разработке Android.Моя проблема в том, что у меня есть база данных SQLite, в которой я сохраняю изображение и некоторые данные, но когда я получаю эти данные, изображение не отображается в виде списка.Другие данные выводятся на экран.

Это мой пользовательский макет списка

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">


<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <ImageView
        android:id="@+id/petImageView"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="true"
        android:layout_marginStart="5dp"
        android:layout_marginTop="0dp"
        android:src="@drawable/cat1"/>

    <TextView
        android:id="@+id/petNameTextView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="50dp"
        android:layout_marginTop="22dp"
        android:layout_marginRight="50dp"
        android:layout_toEndOf="@id/petImageView"
        android:layout_toRightOf="@id/petImageView"
        android:background="@android:color/background_light"
        android:textAlignment="center"
        android:textSize="35sp"
        android:textStyle="bold" />

    </RelativeLayout>

Это мой пользовательский адаптер

public class CustomAdapter extends BaseAdapter {

private int layout;
private ArrayList<DataList> recordList;
private Context context;

public CustomAdapter(Context context, int layout, ArrayList<DataList> recordList) {
    this.context = context;
    this.recordList = recordList;
    this.layout=layout;
}

public int getCount() {
    return recordList.size();
}

public Object getItem(int position) {
    return recordList.get(position);
}

public long getItemId(int position) {
    return position;
}

private class ViewHolder{

    ImageView petImageView;
    TextView petNameTextView;
}


public View getView(int position, View convertView, ViewGroup parent) {

    View v = convertView;
    ViewHolder holder = new ViewHolder();
    if (v == null) {
        LayoutInflater layoutInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        v = layoutInflater.inflate(layout, null);
        holder.petImageView =  v.findViewById(R.id.petImageView);
        holder.petNameTextView = v.findViewById(R.id.petNameTextView);
        v.setTag(holder);
    }else{
        holder = (ViewHolder)v.getTag();
    }



    DataList datalist = recordList.get(position);
    holder.petNameTextView.setText(datalist.getName());

    byte[] recordImage = datalist.getImage();
    Bitmap bitmap = BitmapFactory.decodeByteArray(recordImage, 0, recordImage.length);
    holder.petImageView.setImageBitmap(bitmap);


    return v;
}

}

А это и есть Активность

public class myPetsActivity extends AppCompatActivity {

ListView myPetList;
ArrayList<DataList> petList = new ArrayList<DataList>();
CustomAdapter customAdapter;
ImageView petImageView;
DatabaseHelper mDatabaseHelper;

String name;
byte[] image;
int id;

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_my_pets);


    myPetList = findViewById(R.id.petsListView);
    petList = new ArrayList<>();
    customAdapter = new CustomAdapter(this, R.layout.custom_list_layout, petList);
    myPetList.setAdapter(customAdapter);

    mDatabaseHelper = new DatabaseHelper(this);

    Cursor data = mDatabaseHelper.getData("SELECT * FROM pet_table");
    petList.clear();
    while(data.moveToNext()) {

        id = data.getInt(0);
        name = data.getString(1);
        image = data.getBlob(2);

        petList.add(new DataList(id, name, image));
        Log.i("image",String.valueOf(image));
    }
    customAdapter.notifyDataSetChanged();
    }
    }

А это и есть DataList

    public class DataList {

private int id;
private byte[] image ;
private String name;

public DataList(int id, String name, byte[] image){

    this.id=id;
    this.name=name;
    this.image=image;
}

public int getId() {
    return id;
}

public void setId(int id) {
    this.id = id;
}

public byte[] getImage() {
    return image;
}

public void setImage(byte[] image) {
    this.image = image;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}
}

Ответы [ 3 ]

0 голосов
/ 05 декабря 2018

Рассматривали ли вы сохранение изображения в виде строки в базе данных (Base64)?И просто преобразовать его обратно после чтения из БД.Здесь у вас есть методы для этого: Как преобразовать захваченное изображение или изображение, выбранное из галереи, в base64?

0 голосов
/ 06 декабря 2018

По сути, нет ничего плохого в вашем коде, как показано.Таким образом, проблема, вероятно, связана с хранением изображения в базе данных.

  • Примечание См. Комментарий относительно сохранения изображений в базе данных.

Рабочий пример

Следующий рабочий пример, с незначительными изменениями в вашем коде, а затем только с предложениями (за исключением того, что myPetsActivity было названо MyPetsActivity , которому нужно следоватьобщие соглашения).Однако DatabaseHelper.java написан полностью и, вероятно, не будет полностью отражать ваше DatabaseHelper.java

Одно отличие состоит в том, что сами изображения были помещены впапку assets и извлекаются из этой папки для хранения в таблице pet_table , см. метод addPetWithImageFromAssets в классе DatabaseHelper.java.

Другое отличие состоит в том, что приведенное вышеЭтот метод использовался для заполнения базы данных некоторыми данными тестирования (см. метод addSomeData в MyPetsActivity.java ).Один ряд для питомца по имени Мистер.Невидимому питомцу присвоено несуществующее изображение (что приведет к тому, что BLOB будет использовать для изображения значение по умолчанию x'00 ', это нормально, так как оно не отображается).

custom_list_layout.xml удалил ненужный RelativeLayout (он все еще работает, если он не удален).Для правильного соответствия моему тестированию (с использованием устройства Android 4.1.1) к нему также добавлены 2 атрибута marginLeft и alignParentLeft.

Изображения

Я только что скопировал несколько небольших доступных изображений JPG в папку ресурсов, котораявыглядит так: -

enter image description here

  • Названия примечаний актуальны, реальные изображения не (как я уже сказал, некоторые из них быливаляется)

Код

DatabaseHelper.java

public class DatabaseHelper extends SQLiteOpenHelper {

    public static final String DBNAME = "mypets.db";
    public static final int DBVERSION = 1;
    public static final String TABLE_PET = "pet_table";
    public static final String COLUMN_PET_ID = BaseColumns._ID;
    public static final String COLUMN_PET_NAME = "name";
    public static final String COLUMN_PET_IMAGE = "image";
    public static final String COLUMN_PET_IMAGEPATH = "imagepath";

    SQLiteDatabase mDB;
    Context mContext;

    public DatabaseHelper(Context context) {
        super(context, DBNAME, null, DBVERSION);
        mContext = context;
        mDB = this.getWritableDatabase();
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        String crt_pet_table = "CREATE TABLE IF NOT EXISTS " + TABLE_PET + "(" +
                COLUMN_PET_ID + " INTEGER PRIMARY KEY, " +
                COLUMN_PET_NAME + " TEXT," +
                COLUMN_PET_IMAGE + " BLOB DEFAULT x'00'," +
                COLUMN_PET_IMAGEPATH + " TEXT DEFAULT ''" +
                ")";
        db.execSQL(crt_pet_table);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int i, int i1) {
    }

    /**
     * NOT USED
     * @param petname
     * @return
     */
    public long addPet(String petname) {
        ContentValues cv = new ContentValues();
        cv.put(COLUMN_PET_NAME,petname);
        return mDB.insert(TABLE_PET,null,cv);
    }

    public long addPetWithImageFromAssets(String petname, String petimagename)  {
        byte[] petimage = new byte[0];
        int image_size = 0;

        try {
            InputStream is = mContext.getAssets().open(petimagename);
            image_size = is.available();
            petimage = new byte[image_size];
            is.read(petimage);
            is.close();

        } catch (IOException e) {
        }
        ContentValues cv = new ContentValues();
        cv.put(COLUMN_PET_NAME,petname);
        if (image_size > 0) {
            cv.put(COLUMN_PET_IMAGE,petimage);
        }
        return mDB.insert(TABLE_PET,null,cv);
    }

    public Cursor getData(String query) {
        return mDB.rawQuery(query,null);
    }
}
  • Примечание !!! Вы должны будете адаптировать вышеупомянутое для соответствия.

DataList.java

public class DataList {

    /**
     * NOTE changed id to use long rather than int
     */

    private long id;
    private byte[] image ;
    private String name;

    public DataList(int id, String name, byte[] image){

        this.id=id;
        this.name=name;
        this.image=image;
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public byte[] getImage() {
        return image;
    }

    public void setImage(byte[] image) {
        this.image = image;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
  • Это было изменено только наиспользуйте long для идентификатора, так как int может быть слишком маленьким, если строк много тысяч миллионов.

MyPetsActivity.java

public class MyPetsActivity extends AppCompatActivity {

    ListView myPetList;
    ArrayList<DataList> petList = new ArrayList<DataList>();
    CustomAdapter customAdapter;
    ImageView petImageView;
    DatabaseHelper mDatabaseHelper;

    String name;
    byte[] image;
    int id;

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my_pets);


        myPetList = findViewById(R.id.petsListView);
        petList = new ArrayList<>();
        customAdapter = new CustomAdapter(this, R.layout.custom_list_layout, petList);
        myPetList.setAdapter(customAdapter);

        mDatabaseHelper = new DatabaseHelper(this);
        addSomeData(); //<<<<<<<<<< FOR DEMO

        Cursor data = mDatabaseHelper.getData("SELECT * FROM pet_table");
        petList.clear();
        while(data.moveToNext()) {

            id = data.getInt(0);
            name = data.getString(1);
            image = data.getBlob(2);

            petList.add(new DataList(id, name, image));
            Log.i("image",String.valueOf(image));
        }
        data.close(); //<<<<<<<<<< SHOULD ALWAYS CLOSE CURSOR WHEN DONE WITH IT
        customAdapter.notifyDataSetChanged();
    }


    private void addSomeData() {
        mDatabaseHelper.getWritableDatabase().delete(DatabaseHelper.TABLE_PET,null,null); //<<<<<<<<<< Delete all pets
        mDatabaseHelper.addPetWithImageFromAssets("Fluffy","mypet001.JPG");
        mDatabaseHelper.addPetWithImageFromAssets("Not Fluffy","mypet002.JPG");
        mDatabaseHelper.addPetWithImageFromAssets("Petty","mypet003.JPG");
        mDatabaseHelper.addPetWithImageFromAssets("Mr. Invisible Pet","noimageforthispet"); //<<<<<<< ooops!!!!!
    }
}
  • Примечание добавлен метод addSomeData некоторые данные тестирования, включая изображения (кроме последней добавленной строки, в которой указаны несуществующие файлы изображений (ресурс)).

CustomAdapter.java

  • Без изменений.

activity_my_pets.xml

  • очень простой, но предполагаемый.

.

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

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!" />
    <ListView
        android:id="@+id/petsListView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    </ListView>
</LinearLayout>

custom_list_layout.xml

  • незначительные незначительные изменения

    <TextView
        android:id="@+id/petNameTextView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="50dp"
        android:layout_marginTop="22dp"
        android:layout_marginRight="50dp"
        android:layout_toEndOf="@id/petImageView"
        android:layout_toRightOf="@id/petImageView"
        android:background="@android:color/background_light"
        android:textAlignment="center"
        android:textSize="35sp"
        android:textStyle="bold" />
    

Результат

enter image description here

0 голосов
/ 05 декабря 2018

Попытайтесь использовать обзор рециркулятора вместо просмотра списка, который устарел: developer.android.com / guide / themes / ui / layout / recyclerview Если изображение показывается, но не правильное, оно, вероятно, находится вкод вашего адаптера.

Вы можете создать экземпляр адаптера и после цикла while.

Удалить эту строку кода:

View v = convertView;

В Java, когда вы назначаете объекты каждомуДругое это не значит, что это одно и то же, они просто указывают на одну и ту же ссылку в памяти.Java обрабатывает примитивные объекты и другие немного по-другому.

Следуйте этому примеру: https://www.javacodegeeks.com/2013/09/android-viewholder-pattern-example.html

...