ScrollViewer ChangeView - AccessViolationException one out of the thousand times - windows-runtime

I have FlipView (it's virtualized with Mode="Standard") with ScrollViewer, Image (inside ScrollViewer as DataTemplate). I set ImageOpened event handler on Image with such code:
private void Image_ImageOpened(object sender, RoutedEventArgs e)
{
var image = sender as Image;
double width = image.ActualWidth;
double height = image.ActualHeight;
var sv = image.Parent as ScrollViewer;
if (sv != null && width != 0 && height != 0)
{
var properZoom = ZoomUtilities.CalculateZoomFactor(width, height);
sv.MinZoomFactor = 0.3f;
sv.ChangeView(null, null, properZoom);
sv.MinZoomFactor = properZoom;
}
}
properZoom is always correct value. One out of the thousand times when I change item (swipe) or load page with this FlipView application crash with breakpoint on sv.ChangeView(..) and AccessViolationException exception is thrown. Does anyone know what could be the reason of such behaviour? Are there any restriction when I can call ChangeView method?
EDIT:
Forgot to mention - there is also DoubleTapped event handler on ScrollViewer which also calls ChangeView

I had the same AccessViolationException using .ChangeView(..). I noticed the exception was thrown when the ScrollViewer I wanted to manipulate had focus. For example when a user was dragging through the list or controlling the scrollbar with his mouse.
Disabling animations solved my problems. If you want to keep the animations you should look for a way to remove focus on the controls before changing the view. I guess the animated ChangeView tries to change a property that is locked because of the user input.
Hope this helps.

I had the same problem.
Solution to me: call inverse, from image object to parent got error.
Call normal path: objectscroolviewer.changeview, works no error.
Then:
var sv = image.Parent as ScrollViewer;
change to
var sv = ScrollViewerObject;
Get object to variable externally, not by internal reference of parent, and ignores sender parameter.

Related

How to disable button in libgdx?

I have an image button and I want to be disabled when the program starts and upon certain condition, it needs to be enabled.
Here is my code,
public Screen( ) { //constructor
ImageButton hints;
ImageButton.ImageButtonStyle hintsstyle = new ImageButton.ImageButtonStyle();
hintsstyle.up = skin.getDrawable("newrightbut");
hintsstyle.down = skin.getDrawable("newrightbut");
hintsstyle.pressedOffsetX = 1;
hints = new ImageButton(hintsstyle);
hints.setPosition(650, 35);
hints.setHeight(70);
hints.setWidth(70);
stage.addActor(hints);
hints.setTouchable(Touchable.disabled);
}
public void update() {
hints.setTouchable(Touchable.enabled);
}
But, the button is not getting disabled when the program starts and I even tested with button.setDisabled(true) method. It also doesn't work. Any idea why? Any help would be great!! Thanks
This issue is 5 months old now but I try to answer regardless.
ImageButton hints is declared within your constructor (So its scope is limited to the constructor).
The only way that you don't get a compilation error calling it from a method outside the constructor is if you have also declared it somewhere else within your class.
Conclusion: you must have declared it somewhere else in your application and any default, it is enabled.

Any ways to detect Cocos2d-x: CCScrollView is scrolling or not?

I'm seeking a way to get the scrolling state of CCScrollView.
It seems not to be a rare requirement, but do I need to implement it?
Thanks:)
Edit: Following is my two 'brute force' ways, but they seems work.
The goal is to get the scroll condition of a CCScrollView s from a cocos2d::Layer l.
Way #1
In each iteration of update() function of l, get the content offset of s by
ScrollView::getContentOffset()
if it stays the same, we can assume that the ScrollView is not scrolling.
Way #2
Create class S which inherits CCScrollView and CCScrollViewDelegate, then in the override of the delegate's function
void scrollViewDidScroll(ScrollView* view)
(which seems to be called every time the ScrollView scrolls.) use a variable to save current time
/*uint64_t*/ lastScrollTime = mach_absolute_time();
then in the update() function of l, assume the ScrollView is not scrolling by a time threshold
curTime = mach_absolute_time();
if (GlobalUtils::machTimeToSecs(curTime - lastScrollTime) > 0.1)
Hope that works :)
So, in your's initScroll() method you should set:
scrollView = ScrollView::create();
// initialisation scrollview
scrollView->addEventListener(CC_CALLBACK_2(YourScene::testScroll, this));
this->addChild(scrollView);
and make bool variable isScrolled. Then in method testScroll() you need to check listener's event type and depending from it set the variable isScrolled:
void YourScene::testScroll(Ref* sender, ui::ScrollView::EventType type)
{
if (type == ui::ScrollView::EventType::SCROLLING)
isScrolling = true;
else
isScrolling = false;
}
You can see other values EventType here
One way without modifying the source code of CCScrollView is to check the flag of ScrollView::isDragging() and whether one of the scrolling selectors of ScrollView is scheduled.
bool isDeaccelerateScrolling = scrollView->getScheduler()->isScheduled(CC_SCHEDULE_SELECTOR(ScrollView::deaccelerateScrolling));
bool isPerformedAnimatedScroll = scrollView->getScheduler()->isScheduled(CC_SCHEDULE_SELECTOR(ScrollView::performedAnimatedScroll));
bool isScrolling = scrollView->isDragging() || isDeaccelerateScrolling || isPerformedAnimatedScroll;

Optimize ItemRenderer For Flex Mobile Application

I made this class, which is an ItemRenderer class, used in a DataGroup ( mobile application ),
and I am not entirely sure if I did the right thing or not, my issues are :
Is there a better way to show the image, which is 80x80 and directly loaded from the server;
How to make the height of the row dynamic, I mean, depending on the height of the 3 StyleableTextFeild
Is this the right way to add the listener on the image, that will trigger a simple HTTPService,
Here is the functions from the class, Any help would be much appreciated !!
Image
Declared it as a simple image :
var logo:Image;
On override createChildren
logo = new Image();
addChild(logo);
And I added on set Data
logo.source = "http://192.168.0.15:3000/"+value.logo_thumb_url;
Size
override protected function measure():void {
measuredWidth = measuredMinWidth = stage.fullScreenWidth;
measuredHeight = measuredMinHeight = 100;
}
Listener
override public function set data(value:Object):void {
tel.text = String(value.Tel);
description.text = String(value.Descricao);
nome.text = String(value.Nome);
logo.addEventListener(MouseEvent.CLICK, function():void{
var service:HTTPService = new HTTPService();
service.url = value.targer;
service.method = "GET";
// setting headers and other variables ...
service.send();
});
}
You can use URLLoader or Loader for loading the image if you are planning to cache the image on the client side, if you cache the image, it wil help you not load the image again when the users scrolls through the list. (What you have done is Ok, but you will hit performance issues)
For variable row height, if Datagroup does not work, use List. find it here Flex 4: Setting Spark List height to its content height
There should be a buttonMode property for some items, make it buttonMode for the logo, for variable row height, find something related to wordWrap and variableRowHeight properties on the datagroup.
There are a few suggestions, what you have coded is good, but, instead of adding the listeners on set data, add it in creation complete, as it is more appropriate. Also, the event listeners has to be weak referenced, http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/events/EventDispatcher.html#addEventListener()

A function that deletes an instance by removing it from stage and nulling it does not remove it from memory

I have an issue with a function I use to delete an instance and replace it with another. Basically, it keeps the item in memory no matter what. Inside the object I have weak listeners and I null everything after it gets removed, but the function I run to check if it is still active tells me that it is (just an Event.ENTER_FRAME tracing some text, with a weak link).
Even when I removed everything from the instances I am loading, it still seems to stay in memory, according to my trace it still is. How do I completely delete something from memory more thoroughly than nulling it out after removing it from the stage? Am I not seeing something?
This is the function:
private function loadArea(inputArea:String)
{
//This is for a checker to make sure that areas only get loaded once.
currentRoom = inputArea;
//If the area currently loaded is not null, make it null now.
if(selectedArea != null) selectedArea = null;
//Null any data inside of the reference used to create the name of the new area.
areaReference = null;
//Grab the class using the input.
areaReference = getDefinitionByName(inputArea + "Area") as Class;
//Null the sprite used to house the class
areaSprite = null;
//Set the holder as a new instance of the desired class.
areaSprite = new areaReference() as Sprite;
//If the selected area is still not null for some reason,
if(selectedArea != null)
{
//Remove the area from the container...
areaContainer.removeChild(selectedArea);
//...and nullify it.
selectedArea = null;
}
//Set the current area as the newly created instance.
selectedArea = areaSprite;
//If the area is not the "Game", load in the assets one way,
if(inputArea != "Game") selectedArea.construct(areaAssets);
//otherwise do it another way.
else selectedArea.construct(newScreenData,apiServer,cdnServer,areaAssets);
//This is for a checker that fades out the screen, which it needs to fade back in soon.
newScreenData = null;
//While the container for areas has any areas inside of it, remove them.
while(areaContainer.numChildren) areaContainer.removeChildAt(0);
//...then add the new instance area to the container.
areaContainer.addChild(selectedArea);
//...then let all the parts of the game know that a new area has been laoded in.
Global.echoEvent.echo("gameBootUp","playAreaIn");
}
The memory is actually released when Garbage Collector will find and erase an orphaned instance of yours. Before that, your memory usage will state there is an instance in memory. There is no way to force garbage collection, calling System.gc() only "instructs" Flash to run it, it might not obey. So, you have done what you had to, let it be.
Removing all references including stage and nulling an object is all it takes to free up memory.
If the object is not being released then you are missing something or doing something incorrectly or out of sequence.
Carefully go through your code, making sure you identify where objects are being referenced so you can remove them.
Looking at your example code:
if(selectedArea != null) selectedArea = null;
Here you are making sure that the selectedArea is null.
But immediately after you are testing selectedArea again
(you know it is null so this block is never used)
if(selectedArea != null){
//Remove the area from the container...
areaContainer.removeChild(selectedArea);
//...and nullify it.
selectedArea = null;
}
In every language its VERY DIFFICULT to "clear" memory... even HTML. That being said... try to reduce your memory footprint.
Correct Null:
1. remove all event listeners
2. remove all children
3. remove all mapped/referenced methods/parameters
4. set the class object to null
In most cases this is all you need to do, the WAY you do it will determine if the object gets cleared. Consider the following situation.
You have a custom sprite class (MEMORY FOOTPRINT #1) that has a mapped property (mapping happen when one class object references another). Once you map/reference one object to another = MEMORY FOOTPRINT #2. Adding events = MEMORY FOOTPRINT #3, etc and so on.
Custom Sprite
import flash.display.Sprite;
class CustomSprite extends Sprite{
private var _mappedProperty:Object;
public function addMapping(map:Object):void{
_mappedProperty = map;
}
public function finalize():void{
_mappedProperty = null;
}
}
Assuming we're using CustomSprite in many other methods, lets look at some common ways of removing the ojbect.
INCORRECT - in this situation [objToRemove] was not set to null to free its memory:
var objToRemove:CustomSprite = new CustomSprite;
function doSomething(referenceObj:CustomSprite):void{
var methodObj:CustomSprite = referenceObj;
//CRAZY LINES OF CODE
methodObj = null; //frees memory from [doSomething::methodObj]
referenceObj = null; //frees memory from [doSomething::referenceObj]
//objToRemove is not cleared and will remain in memory
}
INCORRECT - in this situation [objToRemove] has a reference object so it will not clean until the reference is removed:
var objToRemove:CustomSprite = new CustomSprite;
var mappedObject:Sprite = new Sprite;
objToRemove.addMapping(mappedObject);
objToRemove.addEventListener(Event.ENTER_FRAME,onEnterFrame);
//CRAZY LINES OF CODE
//remove all children
while(objToRemove.numChildren > 0){
objToRemove.removeChildAt(0);
}
//remove all event listeners
objToRemove.removeEventListener(Event.ENTER_FRAME,onEnterFrame);
//this will NOT work
objToRemove = null;
//reason is objToRemove has a reference object of [mappedObject]
//[mappedObject] is not a child so it needs to be removed manually
//from WHITIN the CustomSprite class using [CustomSprite::finalize()]
Ok... breath... the correct way is actually simple.
CORRECT - here we are using [Dynamic] objects rather than [Static] class objects, this is considered Object Mapping:
//think of this as a global list of objects
var objPool:Dictionary = new Dictionary;
//create a pool reference
objPool['poolObj'] = new CustomSprite;
//CRAZY LINES OF CODE;
//do the normal [null] process
//both of these will work
objPool['poolObj'] = null;
//or
delete objPool['poolObj'];
SUPER ADVANCED CORRECT - no example provided, I have to get back to work lol...
1. Take a ByteArray clone of the class
2. User a Loader to construct the ByteArray as the class, rather than using "new"
3. When finished... unload/remove the loader
4. EVERYTHING will clear... thats how a Loader works!
(Not getting into why and how... too long of an explanation)
Although this works flawlessly... its not generally accepted or suggested in a work environment.

DependencyProperty PropertyChangedCallback causes NullReferenceException in XAML

I've got a subclassed UserControl that is the content for my main window. I added a DepedencyProperty to my usercontrol, of type ResizeMode, and the PropertyChanged callback sets the ResizeMode of the main window to the value correctly. It runs fine. I can set it from the code behind, or from the XAML, and it works correctly.
However, when I set it from XAML, the designer throws an Object reference not set to an instance of an object exception, on the code in the PropertyChanged callback that sets the window's resize.
<classes:MyUserControl ResizeMode="NoResize">
<...>
</classes:MyUserControl>
This is the callback. MainWindow is a reference to the parent window.
private static void OnResizeModeChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
(o as MyUserControl).MainWindow.ResizeMode = (ResizeMode) e.NewValue;
}
public ResizeMode ResizeMode
{
get { return (ResizeMode) GetValue(ResizeModeProperty); }
set { SetValue(ResizeModeProperty, value); }
}
public static readonly DependencyProperty ResizeModeProperty =
DependencyProperty.Register("SizeToFit", typeof(ResizeMode), typeof(MyUserControl),
new UIPropertyMetadata(ResizeMode.CanResize, new PropertyChangedCallback(OnResizeModeChanged)));
I could ignore it, or set it in the code behind, but I don't really understand the reason for this error, and I would prefer to set it in XAML.
Can anyone shed some light?
Do you know exactly where the NullReferenceExceptoin is being thrown? For example, if you try this instead:
var uc = o as MyUserControl;
var mw = uc.MainWindow;
mw.ResizeMode = (ResizeMode)e.NewValue;
... then is the exception raised on the second line or the third?
My feeling is that MainWindow has not been assigned by the time ResizeMode is first given a value, so accessing MainWindow.ResizeMode is causing the error.
If that's the case, it's safe to ignore:
var mw = (o as MyUserControl).MainWindow;
if (mw == null) return;
But you might want to cache the value somewhere, and then assign it to MainWindow.ResizeMode when MainWindow gets assigned later.
OK, I think I found the culprit.
The MainWindow is set by App.Current.MainWindow.
Now from what I've read, the Current.MainWindow doesn't exist in Design time, and then when the OnResizeModeChanged methods fire during designtime, MainWindow.ResizeMode, boom! Exception!
I added this line to my methods:
if ((bool) (DesignerProperties.IsInDesignModeProperty.GetMetadata(typeof(DependencyObject)).DefaultValue)) return;
I encountered another problem where my XAML suddenly couldn't load my usercontrol, due to me setting some properties on MainWindow in the constructor, added this:
if (DesignerProperties.GetIsInDesignMode(this))
return;