I want to store images in my database. Also I want to check that if the image and title is already in the database. If so, it will not add them to the database. This is my class.
Attractions
public class Attractions extends ListActivity {
DataBaseHandler db = new DataBaseHandler(this);
ArrayList<Contact> imageArry = new ArrayList<Contact>();
List<Contact> contacts;
ContactImageAdapter adapter;
int ctr, loaded;
int [] landmarkImages={R.drawable.oblation,R.drawable.eastwood,R.drawable.ecopark,R.drawable.circle};
String []landmarkDetails = { "Oblation", "Eastwood", "Ecopark", "QC Circle"};
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_attractions);
ctr = db.checkContact(landmarkDetails[loaded]);
// get image from drawable
/**
* CRUD Operations
* */
// Inserting Contacts
Log.d("Insert: ", "Inserting ..");
for(loaded=0; loaded <landmarkDetails.length;loaded++){
Bitmap image = BitmapFactory.decodeResource(getResources(),
landmarkImages[loaded]);
// convert bitmap to byte
ByteArrayOutputStream stream = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 100, stream);
byte imageInByte[] = stream.toByteArray();
Log.d("Going to load images", "Image "+ loaded);
Log.d("Goind to load objects", "loading");
if(ctr == 0){
Log.d("Nothing Loaded", "Loading Now");
db.addContact(new Contact(landmarkDetails[loaded], imageInByte));}
Log.d(landmarkDetails[loaded], "Loaded!");
image.recycle();
}
loadFromDb();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.attractions, menu);
return true;
}
public void loadFromDb(){
// Reading all contacts from database
contacts = db.getAllContacts();
for (Contact cn : contacts) {
String log = "ID:" + cn.getID() + " Name: " + cn.getName()
+ " ,Image: " + cn.getImage();
// Writing Contacts to log
Log.d("Result: ", log);
//add contacts data in arrayList
imageArry.add(cn);
}
adapter = new ContactImageAdapter(this, R.layout.screen_list,
imageArry);
ListView dataList = (ListView) findViewById(android.R.id.list);
dataList.setAdapter(adapter);
}
public void onPause(){
super.onPause();
}
public void onResume(){
super.onResume();
}
}
It works fine on the emulator, but I tried testing on my S4 and then after 3 tries of going to this class, it forced stop. I tried it with usb debugging and the logcat showed java.lang.outofmemoryerror
. The logcat pointed the error in my contactimageadapter.
ContactImageAdapter
public class ContactImageAdapter extends ArrayAdapter<Contact>{
Context context;
int layoutResourceId;
// BcardImage data[] = null;
ArrayList<Contact> data=new ArrayList<Contact>();
public ContactImageAdapter(Context context, int layoutResourceId, ArrayList<Contact> data) {
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
ImageHolder holder = null;
if(row == null)
{
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
holder = new ImageHolder();
holder.txtTitle = (TextView)row.findViewById(R.id.txtTitle);
holder.imgIcon = (ImageView)row.findViewById(R.id.imgIcon);
row.setTag(holder);
}
else
{
holder = (ImageHolder)row.getTag();
}
Contact picture = data.get(position);
holder.txtTitle.setText(picture._name);
//convert byte to bitmap take from contact class
byte[] outImage=picture._image;
ByteArrayInputStream imageStream = new ByteArrayInputStream(outImage);
Bitmap theImage = BitmapFactory.decodeStream(imageStream);
holder.imgIcon.setImageBitmap(theImage);
return row;
}
static class ImageHolder
{
ImageView imgIcon;
TextView txtTitle;
}
}
And pointed to this line Bitmap theImage = BitmapFactory.decodeStream(imageStream);
I have little (almost none) knowledge on managing images and storing them. I also enable android:largeHeap
but still force closes on multiple tries. I hope someone can help me solving this issue, or at least show me a different way of storing text and images to sqlite db. Many thanks!
You have multiple places where whole image (assuming it is big) keeps in memory:
Contact object has it. All loaded images are in imageArry which is instance level variable.
public class Attractions extends ListActivity {
DataBaseHandler db = new DataBaseHandler(this);
ArrayList<Contact> imageArry = new ArrayList<Contact>();
in ContactImageAdapter.getView
method you create another copy of image as BMP in holder object and pass it out of method.
So, at some point you do not have enough memory to keep all of them. Also I sure that decodeStream
needs some more memory to perform.
After all it is not predictable when each new holder created in getView
will be cleaned by GC.
Usually for such situation when object created as new in some method, then passed back to the calling method, that object will be collected only by Full GC.
So, as "Software Sainath" said, do not store images in database… and do not keep them in memory either.
P.S. Then provide to the view a link to the external image file. That also will save time to load a view. Image will be in cache and if user at least once got it, it will not pass through the network again.
I guess images there are not frequently change them self. another image of Contact will be another file…
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With