Memory crash due to imagestoring - ios

This method takes images from the in-built gallery and submits them to the screen in form of a Texture. I also store their choosen image in a file to be presented everytime the user enters that screen. The issue is that when I upload, lets say 3 images in a row I receive memory warning in console, later leading to the app crashing due to memory error:
AppLauncher failed with an exception:
java.lang.RunTimeException: The app crashed: Terminated due to Memory Error
It's hard to pinpoint the exact reason for this. But I've debugged and logged a bit and it doesn't seem that the writing of the image to a file is causing it. It's more related to the action of removing an already existing Image and then uploading a replacement. When I let the user delete their image, the whole file is deleted and the texture is disposed. I also noticed that when the user have uploaded some images and exit the screen, it crashes with that memory error.
FileHandle fileIOS1 = Gdx.files.external("iosImage1.png");
FileHandle fileIOS2 = Gdx.files.external("iosImage2.png");
FileHandle fileIOS3 = Gdx.files.external("iosImage3.png");
FileHandle fileIOS4 = Gdx.files.external("iosImage4_.png");
FileHandle fileIOS5 = Gdx.files.external("iosImage5.png");
FileHandle fileIOS6 = Gdx.files.external("iosImage6.png");
FileHandle fileIOS7 = Gdx.files.external("iosImage7.png");
FileHandle fileIOS8 = Gdx.files.external("iosImage8.png");
FileHandle fileIOS9 = Gdx.files.external("iosImage9.png");
FileHandle fileIOS10 = Gdx.files.external("iosImage10.png");
FileHandle fileIOS11 = Gdx.files.external("iosImage11.png");
FileHandle fileIOS12 = Gdx.files.external("iosImage12.png");
public GalleryScreen(MainClass game) {
if(game.isIOS()){
if(fileIOS1.exists()) {
imageSelected1 = new Texture(fileIOS1);
}
if(fileIOS2.exists()) {
imageSelected2 = new Texture(fileIOS2);
}
if(fileIOS3.exists()) {
imageSelected3 = new Texture(fileIOS3);
}
if(fileIOS4.exists()) {
imageSelected4 = new Texture(fileIOS4);
}
if(fileIOS5.exists()) {
imageSelected5 = new Texture(fileIOS5);
}
if(fileIOS6.exists()) {
imageSelected6 = new Texture(fileIOS6);
}
if(fileIOS7.exists()) {
imageSelected7 = new Texture(fileIOS7);
}
if(fileIOS8.exists()) {
imageSelected8 = new Texture(fileIOS8);
}
if(fileIOS9.exists()) {
imageSelected9 = new Texture(fileIOS9);
}
if(fileIOS10.exists()) {
imageSelected10 = new Texture(fileIOS10);
}
if(fileIOS11.exists()) {
imageSelected11 = new Texture(fileIOS11);
}
if(fileIOS12.exists()) {
imageSelected12 = new Texture(fileIOS12);
}
}
#Override
public void show() {
if(game.isIOS()){
if(fileIOS1.exists()) {
selected1 = new TextureRegionDrawable(new TextureRegion(imageSelected1));
style2.up = skin.newDrawable(skin.newDrawable(selected1));
style2.down = skin.newDrawable(skin.newDrawable(selected1));
}
if(!fileIOS1.exists()){
style2.up = skin.newDrawable(skin.newDrawable(temp));
style2.down = skin.newDrawable(skin.newDrawable(temp));
}
if(fileIOS2.exists()) {
selected2 = new TextureRegionDrawable(new TextureRegion(imageSelected2));
style3.up = skin.newDrawable(skin.newDrawable(selected2));
style3.down = skin.newDrawable(skin.newDrawable(selected2));
}
if(!fileIOS2.exists()){
style3.up = skin.newDrawable(skin.newDrawable(temp));
style3.down = skin.newDrawable(skin.newDrawable(temp));
}
if(fileIOS3.exists()){
selected3 = new TextureRegionDrawable(new TextureRegion(imageSelected3));
style4.up = skin.newDrawable(skin.newDrawable(selected3));
style4.down = skin.newDrawable(skin.newDrawable(selected3));
}
if(!fileIOS3.exists()){
style4.up = skin.newDrawable(skin.newDrawable(temp));
style4.down = skin.newDrawable(skin.newDrawable(temp));
}
Gdx.app.log("HERE:", "6");
if(fileIOS4.exists()){
selected4 = new TextureRegionDrawable(new TextureRegion(imageSelected4));
style5.up = skin.newDrawable(skin.newDrawable(selected4));
style5.down = skin.newDrawable(skin.newDrawable(selected4));
}
Gdx.app.log("HERE:", "7");
if(!fileIOS4.exists()){
style5.up = skin.newDrawable(skin.newDrawable(temp));
style5.down = skin.newDrawable(skin.newDrawable(temp));
}
if(fileIOS5.exists()){
selected5 = new TextureRegionDrawable(new TextureRegion(imageSelected5));
style6.up = skin.newDrawable(skin.newDrawable(selected5));
style6.down = skin.newDrawable(skin.newDrawable(selected5));
}
if(!fileIOS5.exists()){
style6.up = skin.newDrawable(skin.newDrawable(temp));
style6.down = skin.newDrawable(skin.newDrawable(temp));
}
if(fileIOS6.exists()){
selected6 = new TextureRegionDrawable(new TextureRegion(imageSelected6));
style7.up = skin.newDrawable(skin.newDrawable(selected6));
style7.down = skin.newDrawable(skin.newDrawable(selected6));
}
if(!fileIOS6.exists()){
style7.up = skin.newDrawable(skin.newDrawable(temp));
style7.down = skin.newDrawable(skin.newDrawable(temp));
}
if(fileIOS7.exists()){
selected7 = new TextureRegionDrawable(new TextureRegion(imageSelected7));
style8.up = skin.newDrawable(skin.newDrawable(selected7));
style8.down = skin.newDrawable(skin.newDrawable(selected7));
}
if(!fileIOS7.exists()){
style8.up = skin.newDrawable(skin.newDrawable(temp));
style8.down = skin.newDrawable(skin.newDrawable(temp));
}
if(fileIOS8.exists()){
selected8 = new TextureRegionDrawable(new TextureRegion(imageSelected8));
style9.up = skin.newDrawable(skin.newDrawable(selected8));
style9.down = skin.newDrawable(skin.newDrawable(selected8));
}
if(!fileIOS8.exists()){
style9.up = skin.newDrawable(skin.newDrawable(temp));
style9.down = skin.newDrawable(skin.newDrawable(temp));
}
if(fileIOS9.exists()){
selected9 = new TextureRegionDrawable(new TextureRegion(imageSelected9));
style10.up = skin.newDrawable(skin.newDrawable(selected9));
style10.down = skin.newDrawable(skin.newDrawable(selected9));
}
if(!fileIOS9.exists()){
style10.up = skin.newDrawable(skin.newDrawable(temp));
style10.down = skin.newDrawable(skin.newDrawable(temp));
}
if(fileIOS10.exists()){
selected10 = new TextureRegionDrawable(new TextureRegion(imageSelected10));
style11.up = skin.newDrawable(skin.newDrawable(selected10));
style11.down = skin.newDrawable(skin.newDrawable(selected10));
}
if(!fileIOS10.exists()){
style11.up = skin.newDrawable(skin.newDrawable(temp));
style11.down = skin.newDrawable(skin.newDrawable(temp));
}
if(fileIOS11.exists()){
selected11 = new TextureRegionDrawable(new TextureRegion(imageSelected11));
style12.up = skin.newDrawable(skin.newDrawable(selected11));
style12.down = skin.newDrawable(skin.newDrawable(selected11));
}
if(!fileIOS11.exists()){
style12.up = skin.newDrawable(skin.newDrawable(temp));
style12.down = skin.newDrawable(skin.newDrawable(temp));
}
if(fileIOS12.exists()){
selected12 = new TextureRegionDrawable(new TextureRegion(imageSelected12));
style13.up = skin.newDrawable(skin.newDrawable(selected12));
style13.down = skin.newDrawable(skin.newDrawable(selected12));
}
if(!fileIOS12.exists()){
style13.up = skin.newDrawable(skin.newDrawable(temp));
style13.down = skin.newDrawable(skin.newDrawable(temp));
}
}boxImage1.addListener(new ChangeListener() {
#Override
public void changed(ChangeEvent event, Actor actor) {
if(!fileIOS1.exists()) {
new Thread(new Runnable() {
#Override
public void run() {
gallery.iosPickImage1();
Gdx.app.postRunnable(new Runnable() {
#Override
public void run() {
imageSelected1 = new Texture(fileIOS1);
selected1 = new TextureRegionDrawable(new TextureRegion(imageSelected1));
style2.up = skin.newDrawable(skin.newDrawable(selected1));
style2.down = skin.newDrawable(skin.newDrawable(selected1));
}
});
}
}).start();
}
if(!fileIOS2.exists()) {
new Thread(new Runnable() {
#Override
public void run() {
gallery.iosPickImage2();
Gdx.app.postRunnable(new Runnable() {
#Override
public void run() {
Gdx.app.log("CREATING IMAGE" , "1");
imageSelected2 = new Texture(fileIOS2);
Gdx.app.log("CREATING IMAGE" , "2");
selected2 = new TextureRegionDrawable(new TextureRegion(imageSelected2));
Gdx.app.log("CREATING IMAGE" , "3");
style3.up = skin.newDrawable(skin.newDrawable(selected2));
style3.down = skin.newDrawable(skin.newDrawable(selected2));
}
});
}
}).start();
}

First of all fix your typo public GalleryScreen(MainClass gam**e** ), secondary you are doing like 12 times the same thing which is memory consuming depending on the image size. Imagine you load 12 Images of 12mb each. Sure this will need alot of memory especially if you decode them to a drawable. If you would just load them as they are you would already consume 144mb of ram which is alot! Decoded they might be way bigger!
Here are some hints which should help
First of write a clean method, which loads an image and resizes
it to a thumbnail to show. Use a final local variable for the huge image, may call the GC manually after you loaded some pictures and resized them. Try to avoid the GC call but sometimes it may be needed. Take a look into: why-is-it-bad-practice-to-call-system-gc
Clean your code write methods. You are checking if the image exists
but why do you check it doulbe? If it exist its loaded so if its
loaded you don’t need to check it again since it's in memory as an
object. Why don’t you load it directly into a TextureRegionDrawable?
Moreover don’t do 12 member variables of the same type. Use a
ArrayList and write dynamic code. Else you'll have to check the whole
Code again if you change something to the picture count.
libgdx is not threadsafe. Spawn a runnable in a runnable might not be a good choice. The runnable in libgdx get started before the next frame. So nothing parallele here so there is no need to spawn a thread to post a runnable. Take a look into the desktop backend app: Dektop backend Frame method
Do not spawn threads on a mobile device if you do not need to. You got the pictures loaded in memory and still spawn a thread to put them to the box. This doesn‘t make sense if they are loaded.

Related

System.OutOfMemoryException when tried with 70 files SharpZipLib

I have tried zipping 70 pdf documents but ended up having a System.OutOfMemoryException.
Please look into the following code and let me know whats wrong with it.
Please note that I have posted issue on GitHub as well.
public byte[] DownloadPaperList()
{
try
{
PaperDAO paperDAO = new PaperDAO();
List<PaperModel> papers = paperDAO.GetPaperListByPaperIds(paperIDs);
using (MemoryStream outputMemoryStream = new MemoryStream())
{
using (var zipOutputStream = new ZipOutputStream(outputMemoryStream))
{
papers = papers.OrderBy(x => x.Order).ToList();
foreach (PaperModel paper in papers)
{
byte[] decryptedPaper
= CryptoServices.DecryptFile(paper.FileData, paperDAO.GenerateCloseOpenFile(paper, string.Empty), paper.SEVersion);
ZipEntry zipFileEntry = new ZipEntry(paper.DocName + ".pdf")
{
Size = decryptedPaper.Length
};
zipOutputStream.SetLevel(3);
zipOutputStream.PutNextEntry(zipFileEntry); //EXCEPTION THROWS HERE!!!
StreamUtils.Copy(new MemoryStream(decryptedPaper), zipOutputStream, new byte[4096]);
}
zipOutputStream.CloseEntry();
// Stop ZipStream.Dispose() from also Closing the underlying stream.
zipOutputStream.IsStreamOwner = false;
outputMemoryStream.Position = 0;
}
return outputMemoryStream.ToArray();
}
}
catch (Exception)
{
throw;
}
}

How to get around the memory leak issue in Box2D for javascript port?

As I understand now the Box2D version for web is leaking memory, bodies are not deleted, contacts neither. So how do I solve this problem?
See my related question here explaining how is leaking: How to properly delete a box2d body in version: Box2dWeb-2.1.a.3, Box2D_v2.3.1r3? Box2D bug?
it is possible that this post described how to patch this issue
http://devizgl.blogspot.com/2012/03/box2d21a.html
You have to patch file Box2dWeb-2.1.a.3.js
Step 1
Add method Destroy() to the class b2Body:
b2Body.prototype.Destroy = function () {
this.m_userData = null;
this.m_sweep = null;
this.m_xf = null;
this.m_linearVelocity = null;
this.m_force = null;
this.m_world = null;
this.m_prev = null;
this.m_next = null;
this.m_fixtureList = null;
this.m_controllerList = null;
this.m_jointList = null;
this.m_contactList = null;
}
Step 2
Add code to the end of the method DestroyBody of class b2World:
...
--this.m_bodyCount;
b.Destroy();
}
Step 3
Add this field to the class b2Contact:
...
this.m_swaped = false;
Step 4
Add code to the method Destroy of class b2ContactFactory:
...
var reg = null;
if (contact.m_swaped) {
reg = this.m_registers[type2][type1];
}
else {
reg = this.m_registers[type1][type2];
}
contact.Reset();
...
Step 5
Add code to the method Create of class b2ContactFactory:
...
if (reg.pool) {
c = reg.pool;
reg.pool = c.m_next;
reg.poolCount--;
// <---------------------
if (c.m_swaped) {
c.Reset(fixtureB, fixtureA);
}
else {
c.Reset(fixtureA, fixtureB);
}
// <---------------------
return c;
}
var createFcn = reg.createFcn;
if (createFcn != null) {
if (reg.primary) {
c = createFcn(this.m_allocator);
c.Reset(fixtureA, fixtureB);
c.m_swaped = false; // <------------------
return c;
}
else {
c = createFcn(this.m_allocator);
c.Reset(fixtureB, fixtureA);
c.m_swaped = true; // <------------------
return c;
}
}
...

MonoTouch Load image in background

I am having a problem trying to load an image and display it using System.Threading.Task
My Code is as follows
Task DownloadTask { get; set; }
public string Instrument { get; set; }
public PriceChartViewController(string Instrument) {
this.Instrument = Instrument;
DownloadTask = Task.Factory.StartNew(() => { });
}
private void LoadChart(ChartType chartType) {
NSData data = new NSData();
DownloadTask = DownloadTask.ContinueWith(prevTask => {
try {
UIApplication.SharedApplication.NetworkActivityIndicatorVisible = true;
NSUrl nsUrl = new NSUrl(chartType.Uri(Instrument));
data = NSData.FromUrl(nsUrl);
}
finally {
UIApplication.SharedApplication.NetworkActivityIndicatorVisible = false;
}
});
DownloadTask = DownloadTask.ContinueWith(t => {
UIImage image = new UIImage(data);
chartImageView = new UIImageView(image);
chartImageView.ContentScaleFactor = 2f;
View.AddSubview(chartImageView);
this.Title = chartType.Title;
}, CancellationToken.None, TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.FromCurrentSynchronizationContext());
}
The second Continue with does not seem to be being called?
Initially my code looked like the following without the background processing and it worked perfectly.
private void oldLoadChart(ChartType chartType) {
UIApplication.SharedApplication.NetworkActivityIndicatorVisible = true;
NSUrl nsUrl = new NSUrl(chartType.Uri(Instrument));
NSData data = NSData.FromUrl(nsUrl);
UIImage image = new UIImage(data);
chartImageView = new UIImageView(image);
chartImageView.ContentScaleFactor = 2f;
View.AddSubview(chartImageView);
this.Title = chartType.Title;
UIApplication.SharedApplication.NetworkActivityIndicatorVisible = false;
}
Does anyone know what I am doing wrong?
Your first part of the thread is crashing, that's why it is never getting to the second:
You are calling UIApplication.SharedApplication.NetworkActivityIndicatorVisible = true;
from a non-UI thread. Setting the network activity indicator is a UI operation and may only be executed on the main thread. You'll have to wrap it in InvokeOnMainThread().
If you add a try-catch, you'll see the exception.
Add catch before finally. Maybe you just have an exception so workflow doesn't go any further.

How to reuse j2me kxml parser?

I am useing kxml parser for my j2me application. I am reading the file from phone memory and parsing the xml file to display the data(have various level of filter). On each filter i need to read the data from this file. For first time i created the parser and every time i re-assign this parser1(reference-original) to the paerser2(used to parse data). For first time i got the correct answer, but second time i haven't got the file content it shows null as data.
Here is my code:
FileConnection fc = (FileConnection)Connector.open(rmsObj.rmsData.elementAt(0).toString());
InputStream in = fc.openInputStream();
InputStreamReader is = new InputStreamReader(in);
commonAppObj.externParser = new XmlParser(is);
commonAppObj class file.
protected void fileread() {
try {
if(externParser != null){
parser = externParser;
fileparser(parser);
}else{
InputStream in = this.getClass().getResourceAsStream(this.dataBase);
InputStreamReader is = new InputStreamReader(in);
parser = new XmlParser(is);
fileparser(parser);
}
} catch (IOException ioe) {
} finally {
parser = null;
}
}
private void fileparser(XmlParser parser){
try {
ParseEvent event = null;
dataflag = 0;
dataflagS = 0;
System.out.println("findtags = " + findtags);
while (((event = parser.read()).getType() != Xml.END_DOCUMENT) && (dataflag != 1)) {
if (event.getType() == Xml.START_TAG) {
String name = event.getName();
if (name != null && name.equals(findtags)) {
dataflag = 0;
parseAddressTag(parser);
}
name = null;
}
event = null;
}
} catch (IOException ioe) {
} finally {
parser = null;
}
}
}
If your InputStream returns true in a call to markSupported you may reset it at the end of fileparser method, but first you need to call mark right after creating it.
if (in.markSupported()) {
in.mark(in.available());
}

Entity Framework Newbie - Save to DB

I have 3 joined tables; ValidationRun has many Result which has many Error
The following code succeeds in saving to the Result and Error tables but not the ValidationRun.
Can you see the problem please?
private void WriteResultsToDB(SqlDataReader dr, XMLValidator validator)
{
using (var context = new ValidationResultsEntities())
{
var run = new ValidationRun { DateTime = DateTime.Now, XSDPath = this.txtXsd.Text };
//loop through table containing the processed XML
while (dr.Read())
{
var result = new Result
{
AddedDateTime = (DateTime)dr["Added"],
CustomerAcc = (string)dr["CustomerAcc"],
CustomerRef = (string)dr["CustomerRef"]
};
if (this.rdoRequest.Checked)
{
result.XMLMsg = (string)dr["RequestMSG"];
}
else
{
result.XMLMsg = (string)dr["ReplyMSG"];
}
if (validator.Validate(result.XMLMsg))
{
foreach (string error in validator.Errors)
{
result.Errors.Add(new Error { ErrorDescription = error });
}
}
else
{
//validator caught an error
result.Errors.Add(new Error { ErrorDescription = "XML could not be parsed" });
}
if (result.Errors.Count == 0) result.ValidFile = true; else result.ValidFile = false;
context.AddToResults(result);
context.SaveChanges();
}
}
You don't appear to be adding the run to any part of the context. If it were referenced by the result you are adding, perhaps, the change tracker would know it was supposed to be saved, but as it is written it is just some orphaned object that doesn't get attached anywhere.

Resources