I need a hand on pagerView. When I use the pagerview after a hundred pages the application gives me error 'out of memory'. I need a method to destroy the view because it keeps me in memory all (from first to last).
In view memorize 4 boxes made by me with an image (which does not change) and two buttons.
this is my adapter:
namespace ProvaViewPager
{
public class FragmentAdapter : FragmentStatePagerAdapter
{
int mCount;
private FragmentManager mFragmentManager;
public FragmentAdapter (FragmentManager fm) : base (fm)
{
mCount = 200;
mFragmentManager = fm;
}
public override Fragment GetItem (int position)
{
return new SwiftView (position);
}
public override int Count {
get {
return mCount;
}
}
use the method distroy? but how?
Message in debug:
Skipped 55 frames! The application may be doing too much work on its
main thread. Clamp target GC heap from 49.446MB to 48.000MB Clamp
target GC heap from 49.847MB to 48.000MB Clamp target GC heap from
49.860MB to 48.000MB Clamp target GC heap from 49.859MB to 48.000MB Forcing collection of SoftReferences for 712-byte allocation Clamp
target GC heap from 49.859MB to 48.000MB Out of memory on a 712-byte
allocation. Clamp target GC heap from 49.874MB to 48.000MB Clamp
target GC heap from 49.874MB to 48.000MB Forcing collection of
SoftReferences for 964-byte allocation Clamp target GC heap from
49.874MB to 48.000MB Out of memory on a 964-byte allocation.Mono.Debugging.Evaluation.EvaluatorException:
Java.Lang.OutOfMemoryError:
in Mono.Debugging.Soft.MethodCall.get_ReturnValue()
in
Mono.Debugging.Soft.SoftEvaluationContext.RuntimeInvoke(MethodMirror
method, Object target, Value[] values)
in
Mono.Debugging.Soft.SoftDebuggerAdaptor.CallToString(EvaluationContext
ctx, Object obj)
in
Mono.Debugging.Evaluation.ObjectValueAdaptor.TargetObjectToObject(EvaluationContext
ctx, Object obj)
in
Mono.Debugging.Soft.SoftDebuggerAdaptor.TargetObjectToObject(EvaluationContext
gctx, Object obj)
in
Mono.Debugging.Evaluation.ExpressionEvaluator.TargetObjectToExpression(EvaluationContext
ctx, Object obj)
in
Mono.Debugging.Evaluation.ObjectValueAdaptor.CreateObjectValueImpl(EvaluationContext
ctx, IObjectValueSource source, ObjectPath path, Object obj,
ObjectValueFlags flags)
in
Mono.Debugging.Evaluation.ObjectValueAdaptor.CreateObjectValue(EvaluationContext
ctx, IObjectValueSource source, ObjectPath path, Object obj,
ObjectValueFlags flags) Clamp target GC heap from 49.874MB to 48.000MB
Clamp target GC heap from 49.874MB to 48.000MB Forcing collection of
SoftReferences for 964-byte allocation Clamp target GC heap from
49.874MB to 48.000MB Out of memory on a 964-byte allocation. Clamp target GC heap from 49.874MB to 48.000MB
Sorry for the bad English
Then create a ViewPager containing a box, composed of an image and written ..... each page is composed of 4 box.
This is my code for create box:
namespace ProvaViewPager.Widget.CatalogoBox
{
public class CatalogoBox : RelativeLayout
{
private LayoutInflater _mInflater;
private LinearLayout _mBox;
private void Initialize ()
{
}
public CatalogoBox (IntPtr doNotUse, JniHandleOwnership transfer)
: base(doNotUse, transfer)
{
}
public CatalogoBox (Context context, IAttributeSet attrs)
: base(context, attrs)
{
InternalCtor (context, attrs);
}
public CatalogoBox (Context context, IAttributeSet attrs, int defStyle)
: base(context, attrs, defStyle)
{
InternalCtor (context, attrs);
}
~CatalogoBox ()
{
Dispose (false);
}
private void InternalCtor (Context context, IAttributeSet attrs)
{
_mInflater = (LayoutInflater)context.GetSystemService (Context.LayoutInflaterService);
_mBox = (LinearLayout)_mInflater.Inflate (Resource.Layout.CatalogoBox, null);
AddView (_mBox);
}
}
}
and here (class SwiftView : Fragment) we recall:
public override View OnCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
TextView TxtCDPAR;
TextView TxtDEPAR;
TextView TxtPrezzo;
TextView TxtPz;
ImageView ImageDisp;
ImageView ImgFreccia;
ImageView ImgIncrementa;
ImageView ImgDecrementa;
ImageView ImageItem;
EditText Quantita;
ImageView ImageProduct;
LinearLayout BoxAddProdotto;
View v = inflater.Inflate (Resource.Layout.PageViewXml, container, false);
if (v != null) {
#region BOX1
var BoxProdotto1 = v.FindViewById<ProvaViewPager.Widget.CatalogoBox.CatalogoBox> (Resource.Id.CatalogoBox1);
TxtCDPAR = BoxProdotto1.FindViewById<TextView> (Resource.Id.CAT_TxtCodiceProdotto);
TxtDEPAR = BoxProdotto1.FindViewById<TextView> (Resource.Id.CAT_DescrProdotto);
ImageView ImagetItem1 = BoxProdotto1.FindViewById<ImageView> (Resource.Id.CAT_ImageProduct) as ImageView;
TxtPz = BoxProdotto1.FindViewById<TextView> (Resource.Id.CAT_NumeroPezzi);
TxtPrezzo = BoxProdotto1.FindViewById<TextView> (Resource.Id.CAT_TxtPrezzo);
BoxAddProdotto = BoxProdotto1.FindViewById<LinearLayout> (Resource.Id.BoxAddProdotto);
ImageDisp = BoxProdotto1.FindViewById<ImageView> (Resource.Id.CAT_ImgDisp);
ImgFreccia = BoxProdotto1.FindViewById<ImageView> (Resource.Id.CAT_ImgFreccia);
ImgIncrementa = BoxProdotto1.FindViewById<ImageView> (Resource.Id.imageIncrementa);
ImgDecrementa = BoxProdotto1.FindViewById<ImageView> (Resource.Id.imageDecrementa);
Quantita = BoxProdotto1.FindViewById<EditText> (Resource.Id.editNumerico);
ImageProduct = BoxProdotto1.FindViewById<ImageView> (Resource.Id.CAT_ImageProduct);
TxtPz.Visibility = ViewStates.Invisible;
ImagetItem1.SetImageResource (Resource.Drawable.imagespiaggia);
#endregion
#region BOX2
var BoxProdotto2 = v.FindViewById<ProvaViewPager.Widget.CatalogoBox.CatalogoBox> (Resource.Id.CatalogoBox2);
TxtCDPAR = BoxProdotto2.FindViewById<TextView> (Resource.Id.CAT_TxtCodiceProdotto);
TxtDEPAR = BoxProdotto2.FindViewById<TextView> (Resource.Id.CAT_DescrProdotto);
ImageItem = BoxProdotto2.FindViewById<ImageView> (Resource.Id.CAT_ImageProduct) as ImageView;
TxtPz = BoxProdotto2.FindViewById<TextView> (Resource.Id.CAT_NumeroPezzi);
TxtPrezzo = BoxProdotto2.FindViewById<TextView> (Resource.Id.CAT_TxtPrezzo);
BoxAddProdotto = BoxProdotto2.FindViewById<LinearLayout> (Resource.Id.BoxAddProdotto);
ImageDisp = BoxProdotto2.FindViewById<ImageView> (Resource.Id.CAT_ImgDisp);
ImgFreccia = BoxProdotto2.FindViewById<ImageView> (Resource.Id.CAT_ImgFreccia);
ImgIncrementa = BoxProdotto2.FindViewById<ImageView> (Resource.Id.imageIncrementa);
ImgDecrementa = BoxProdotto2.FindViewById<ImageView> (Resource.Id.imageDecrementa);
Quantita = BoxProdotto2.FindViewById<EditText> (Resource.Id.editNumerico);
ImageProduct = BoxProdotto2.FindViewById<ImageView> (Resource.Id.CAT_ImageProduct);
TxtPz.Visibility = ViewStates.Invisible;
ImageItem.SetImageResource (Resource.Drawable.feliximage);
#endregion
This is Adapter:
namespace ProvaViewPager
{
public class FragmentAdapter : FragmentStatePagerAdapter
{
int mCount;
private FragmentManager mFragmentManager;
public FragmentAdapter (FragmentManager fm) : base (fm)
{
mCount = 200;
mFragmentManager = fm;
}
public override Fragment GetItem (int position)
{
return new SwiftView (position);
}
public override int Count {
get {
return mCount;
}
}
public override Java.Lang.Object InstantiateItem (ViewGroup container, int position)
{
return base.InstantiateItem (container, position);
}
public override void DestroyItem (ViewGroup collection, int position, Java.Lang.Object view)
{
base.DestroyItem(collection,position,view);
}
}
}
Related
Consider:
namespace WindowsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
//int[] val = { 0, 0};
int val;
if (textBox1.Text == "")
{
MessageBox.Show("Input any no");
}
else
{
val = Convert.ToInt32(textBox1.Text);
Thread ot1 = new Thread(new ParameterizedThreadStart(SumData));
ot1.Start(val);
}
}
private static void ReadData(object state)
{
System.Windows.Forms.Application.Run();
}
void setTextboxText(int result)
{
if (this.InvokeRequired)
{
this.Invoke(new IntDelegate(SetTextboxTextSafe), new object[] { result });
}
else
{
SetTextboxTextSafe(result);
}
}
void SetTextboxTextSafe(int result)
{
label1.Text = result.ToString();
}
private static void SumData(object state)
{
int result;
//int[] icount = (int[])state;
int icount = (int)state;
for (int i = icount; i > 0; i--)
{
result += i;
System.Threading.Thread.Sleep(1000);
}
setTextboxText(result);
}
delegate void IntDelegate(int result);
private void button2_Click(object sender, EventArgs e)
{
Application.Exit();
}
}
}
Why is this error occurring?
An object reference is required for the nonstatic field, method, or property 'WindowsApplication1.Form1.setTextboxText(int)
It looks like you are calling a non static member (a property or method, specifically setTextboxText) from a static method (specifically SumData). You will need to either:
Make the called member static also:
static void setTextboxText(int result)
{
// Write static logic for setTextboxText.
// This may require a static singleton instance of Form1.
}
Create an instance of Form1 within the calling method:
private static void SumData(object state)
{
int result = 0;
//int[] icount = (int[])state;
int icount = (int)state;
for (int i = icount; i > 0; i--)
{
result += i;
System.Threading.Thread.Sleep(1000);
}
Form1 frm1 = new Form1();
frm1.setTextboxText(result);
}
Passing in an instance of Form1 would be an option also.
Make the calling method a non-static instance method (of Form1):
private void SumData(object state)
{
int result = 0;
//int[] icount = (int[])state;
int icount = (int)state;
for (int i = icount; i > 0; i--)
{
result += i;
System.Threading.Thread.Sleep(1000);
}
setTextboxText(result);
}
More info about this error can be found on MSDN.
For this case, where you want to get a Control of a Form and are receiving this error, then I have a little bypass for you.
Go to your Program.cs and change
Application.Run(new Form1());
to
public static Form1 form1 = new Form1(); // Place this var out of the constructor
Application.Run(form1);
Now you can access a control with
Program.form1.<Your control>
Also: Don't forget to set your Control-Access-Level to Public.
And yes I know, this answer does not fit to the question caller, but it fits to googlers who have this specific issue with controls.
You start a thread which runs the static method SumData. However, SumData calls SetTextboxText which isn't static. Thus you need an instance of your form to call SetTextboxText.
Your method must be static
static void setTextboxText(int result)
{
if (this.InvokeRequired)
{
this.Invoke(new IntDelegate(SetTextboxTextSafe), new object[] { result });
}
else
{
SetTextboxTextSafe(result);
}
}
Credit to #COOLGAMETUBE for tipping me off to what ended up working for me. His idea was good but I had a problem when Application.SetCompatibleTextRenderingDefault was called after the form was already created. So with a little change, this is working for me:
static class Program
{
public static Form1 form1; // = new Form1(); // Place this var out of the constructor
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(form1 = new Form1());
}
}
I actually got this error because I was checking InnerHtml for some content that was generated dynamically - i.e. a control that is runat=server.
To solve this I had to remove the "static" keyword on my method, and it ran fine.
From my looking you give a null value to a textbox and return in a ToString() as it is a static method. You can replace it with Convert.ToString() that can enable null value.
Make the function static. This must solve your problem.
The essence, and solution, to your problem is this:
using System;
namespace myNameSpace
{
class Program
{
private void method()
{
Console.WriteLine("Hello World!");
}
static void Main(string[] args)
{
method();//<-- Compile Time error because an instantiation of the Program class doesnt exist
Program p = new Program();
p.method();//Now it works. (You could also make method() static to get it to work)
}
}
}
I am trying to use Mouse.GetState() for my menu selection. Currently, it will only highlight if I hover over a region left and up from where the menu is. I used DrawString to display the mouses coordinates and found that the 0,0 point wasn't in the top left of my monitor or in the top left of the game window. It was somewhere about 100,100 pixels from the top left of the screen. Also, the 0,0 point moves every time I run the programme.
I looked at others people who have had the same problem but wasn't able to solve it. I tried using Mouse.WindowHandle = this.Window.Handle; in my Initialize() but it didn't nothing. I have two monitors and when I forced the game in fullscreen it would open on my second monitor so I disabled it but the problem remains.
here is a link to my code http://pastebin.com/PNaFADqp
Game1 class:
public class Game1 : Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
SpriteFont spriteFont;
public const int WINDOW_HEIGHT = 800;
public const int WINDOW_WIDTH = 600;
public int tree;
public TitleScreen titleScreen;
public SATDemo satDemo;
public SeparatingAxisTest separatingAxisTest;
public SATWithAABB sATWithAABB;
GameState currentState;
public static Dictionary<string, Texture2D> m_textureLibrary = new Dictionary<string, Texture2D>();
public static Dictionary<string, SpriteFont> m_fontLibrary = new Dictionary<string, SpriteFont>();
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
graphics.PreferredBackBufferHeight = WINDOW_HEIGHT;
graphics.PreferredBackBufferWidth = WINDOW_WIDTH;
}
protected override void Initialize()
{
Mouse.WindowHandle = this.Window.Handle;
//enable the mousepointer
IsMouseVisible = true;
currentState = GameState.TitleScreen;
//sets the windows mouse handle to client bounds handle
base.Initialize();
}
public void RequestSATDemo()
{
currentState = GameState.RequestSATDemo;
}
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
m_textureLibrary.Add("Pixel", Content.Load<Texture2D>("White_Pixel"));
m_fontLibrary.Add("Font", Content.Load<SpriteFont>("MotorwerkOblique"));
titleScreen = new TitleScreen();
satDemo = new SATDemo();
separatingAxisTest = new SeparatingAxisTest();
sATWithAABB = new SATWithAABB();
}
public void RequestSeparatingAxisTest()
{
currentState = GameState.SeparatingAxisTest;
}
public void RequestSATWithAABB()
{
currentState = GameState.SATWithAABB;
}
protected override void Update(GameTime gameTime)
{
MouseTestState = Mouse.GetState();
switch (currentState)
{
case GameState.TitleScreen:
{
titleScreen.Update(gameTime);
break;
}
case GameState.SeparatingAxisTest:
{
separatingAxisTest.Update(gameTime);
break;
}
case GameState.SATWithAABB:
{
sATWithAABB.Update(gameTime);
break;
}
case GameState.Exit:
{
Exit();
break;
}
default:
{
titleScreen.Update(gameTime);
break;
}
}
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
spriteBatch.Begin();
spriteBatch.DrawString(m_fontLibrary["Font"], MouseTestState.ToString(), new Vector2(0, 0), Color.White);
switch (currentState)
{
case GameState.TitleScreen:
{
titleScreen.Draw(spriteBatch, spriteFont);
break;
}
case GameState.SeparatingAxisTest:
{
separatingAxisTest.Draw(gameTime, spriteBatch);
break;
}
case GameState.SATWithAABB:
{
sATWithAABB.Draw(gameTime, spriteBatch);
break;
}
case GameState.Exit:
{
Exit();
break;
}
default:
{
titleScreen.Update(gameTime);
break;
}
}
spriteBatch.End();
base.Draw(gameTime);
}
}
TitleScreen class:
public class TitleScreen : Screen
{
List<Button> buttonList = new List<Button>();
public Menu mainMenu;
public TitleScreen()
{
mainMenu = new Menu(new Vector2(200, 100), buttonList, 0);
buttonList.Add(new PushButton("Separating Axis Test"));
buttonList.Add(new PushButton("SAT With AABB"));
buttonList.Add(new PushButton("Awesome"));
buttonList.Add(new PushButton("Awesomere"));
buttonList.Add(new PushButton("Awesomere"));
}
public override void Update(GameTime gametime)
{
mainMenu.Update(gametime);
}
public void Draw(SpriteBatch sB, SpriteFont sF)
{
mainMenu.Draw(sB, sF);
}
}
PushButton class:
public class PushButton : Button
{
string m_text;
SpriteFont m_font;
Color m_static, m_onClick, m_onHover;
Texture2D m_sprite2D, m_onClick2D;
static public int Pbuttoncount;
//click processing
bool m_clickedInside = false,
m_releasedInside = false,
m_OnClicked = false,
selected = false;
Rectangle drawRectangle;
public PushButton(string Text)
{
m_text = Text;
drawRectangle = new Rectangle((int)Menu.m_position.X, (int)Menu.m_position.Y + (15 * Pbuttoncount), 200, 15);
ButtonRegion = new Rectangle((int)Position.X, (int)Position.Y, 200, 15);
Pbuttoncount++;
}
public PushButton(Rectangle ButtonRegion, SpriteFont Font, string Text, Color Static, Color OnClick, Color OnHover)
{
m_buttonRegion = ButtonRegion;
m_font = Font;
m_text = Text;
m_static = Static;
m_onClick = OnClick;
m_onHover = OnHover;
// drawRectangle = ButtonPosition(m_buttonRegion);
}
public PushButton(Rectangle ButtonRegion, Texture2D Sprite2D, Texture2D OnClick2D)
{
m_buttonRegion = ButtonRegion;
m_sprite2D = Sprite2D;
m_onClick2D = OnClick2D;
//drawRectangle = ButtonPosition(m_buttonRegion);
}
public override void Update(GameTime gameTime)
{
MouseState currentMouse = Mouse.GetState();
selected = MouseState(drawRectangle, currentMouse);
m_clickedInside = ClickInside(currentMouse, m_lastMouseState);
ReleaseInside(currentMouse, m_lastMouseState);
if (selected && m_clickedInside && m_releasedInside)
m_OnClicked = true;
else
m_OnClicked = false;
m_lastMouseState = currentMouse;
}
public override void Draw(SpriteBatch spriteBatch, SpriteFont spriteFont, int buttonCount, Vector2 Position)
{
spriteBatch.Draw(Game1.m_textureLibrary["Pixel"], new Rectangle((int)Position.X + 10, (int)(Position.Y + 15 * buttonCount), 180, 15), Color.Wheat);
if (selected)
spriteBatch.DrawString(Game1.m_fontLibrary["Font"], m_text, new Vector2(Position.X + 15, Position.Y + 15 * buttonCount), Color.Orange);
else
spriteBatch.DrawString(Game1.m_fontLibrary["Font"], m_text, new Vector2(Position.X + 15, Position.Y + 15 * buttonCount), Color.Black);
}
}
Menu class:
public class Menu
{
List<Button> m_buttonList;
float m_transparency;
public int n = 0;
public Rectangle buttonRegion, m_menuRegion, m_dimensions;
static public Vector2 m_position;
int m_WINDOW_HEIGHT = Game1.WINDOW_HEIGHT;
int m_WINDOW_WIDTH = Game1.WINDOW_WIDTH;
private Game1 m_managerClass;
public Menu(Vector2 Position, List<Button> ButtonList, float Transparency)
{
m_position = Position;
m_buttonList = ButtonList;
m_transparency = Transparency;
m_managerClass = new Game1();
}
public Rectangle MenuRegion
{
get { return m_menuRegion; }
set { m_menuRegion = value; }
}
static public Vector2 Position
{
get { return m_position; }
}
public void Update(GameTime gametime)
{
for (int i = 0; i < m_buttonList.Count; i++)
{
m_buttonList[i].Update(gametime);
if (m_buttonList[0].OnClicked)
{
SeperatingAxisTest();
}
}
}
public void Draw(SpriteBatch sB, SpriteFont sF)
{
sB.Draw(Game1.m_textureLibrary["Pixel"], new Rectangle((int)m_position.X - 5, (int)m_position.Y - 10, (m_buttonList[0].ButtonRegion.Width + 10), (m_buttonList[0].ButtonRegion.Height * m_buttonList.Count) + 20), Color.Blue);
for (int i = 0; i < m_buttonList.Count; i++)
{
m_buttonList[i].Draw(sB, sF, i, new Vector2(Position.X, Position.Y));
}
}
private void SeperatingAxisTest()
{
m_managerClass.RequestSeparatingAxisTest();
}
}
Program class:
public static class Program
{
[STAThread]
static void Main()
{
using (var game = new Game1())
game.Run();
}
}
Let me know if you need anything else. I'm still learning and will sell my soul to you for an answer.
Your Menu class is creating a new instance of Game1. This is, most likely, not what you want, since Game1 is instantiated in the entry point for you app. The Game1 instance has an instance of TitleScreen, which in turn has an instance of the Menu class, so a Menu should have no business creating its own game.
When this (other) instance is created, it invokes platform-specific (Windows) methods, creates an additional window handle (which is never shown) and configures the Mouse.WindowHandle.
And btw, setting WindowHandle manually does absolutely nothing in Monogame, so all these sources mentioning that are talking about XNA.
So, there are several remarks:
You should probably have a "screen manager" class which contains the current screen. It is strange to have a field of type TitleScreen in your game class, it should at least be of the base type (Screen), so that the game class draws and updates each screen transparently.
If you need a reference to the game class anywhere, don't instantiate a new one, but rather pass it along through the constructor.
m_managerClass is a bad name for a field which is actually a Game. Also google for C# naming conventions. Perhaps you even might want to download an existing monogame game template, e.g. check some of the samples online; the NetRumble sample seems to implement a screen manager.
Remove the Mouse.WindowHandle line, it should be set to your one-and-only game window by default.
tl;dr add the Game1 as a parameter wherever you might need it (but only where you need it).
abstract class Screen
{
private readonly Game1 _game;
public Game1 Game
{ get { return _game; } }
public Screen(Game1 game)
{
_game = game;
}
}
class TitleScreen : Screen
{
public TitleScreen(Game1 game)
: base(game)
{ ... }
}
class Menu
{
private readonly Screen _screen;
public Menu(Screen parentScreen, Vector2 pos, List<Button> list, float alpha)
{
_screen = parentScreen;
...
// if you need the game instance, just use _screen.Game
}
}
I'm a bit confused about JavaFx 8 and the listener memory leak problem. The official doc says:
The ObservableValue stores a strong reference to the listener which will prevent the listener from being garbage collected and may result in a memory leak.
I would like to have an example where the usage of ObservableValue<T> addListener method create a memory leak.
For example, if I have a class like this:
public class ConfigurationPane extends AnchorPane {
#FXML
private Label titleLabel;
public ConfigurationPane () {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("view/ConfigurationPane .fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException e) {
e.printStackTrace();
}
}
#FXML
private void initialize() {
titleLabel.sceneProperty().addListener(new MyListener());
}
}
Can I get memory leaks? When a ConfigurationPane object is garbage collected, the MyListener object is garbage collected too? I'm not able to see a scenario where
a strong reference to the listener will prevent the listener from being garbage collected
P.S. I see other S.O. questions about this but none of these helped me to understand the problem.
Thanks.
It means that map which store your listener is not using weak references, and you have to remove listeners youself to avoid memory leaks.
In the example below LeakingListener objects will never be freed although corresponding TextFields being removed from scene:
public class LeakListener extends Application {
private static class LeakingListener implements InvalidationListener {
private final TextField tf;
private final int[] placeHolder = new int[50000]; // to simplify monitoring
public LeakingListener(TextField tf) {
this.tf = tf;
}
public void invalidated(Observable i) {
tf.setText(tf.getText() + ".");
}
}
#Override
public void start(Stage primaryStage) {
final Pane root = new VBox(3);
final Button btnType = new Button("Type in all");
Button btnAdd = new Button("Add");
btnAdd.setOnAction((e) -> {
TextField tf = new TextField();
root.getChildren().add(tf);
// memory leaking listener which never gets cleaned
btnType.armedProperty().addListener(new LeakingListener(tf));
});
Button btnRemove = new Button("Remove");
btnRemove.setOnAction((ActionEvent e) -> {
// find random TextEdit element
Optional<Node> toRemove = root.getChildren().stream().filter((Node t) -> t instanceof TextField).findAny();
// if any, and remove it
if (toRemove.isPresent()) {
root.getChildren().remove(toRemove.get());
}
});
Button btnMemory = new Button("Check Memory");
btnMemory.setOnAction((e) -> {
System.gc();
System.out.println("Free memory (bytes): " + Runtime.getRuntime().freeMemory());
});
root.getChildren().addAll(btnAdd, btnRemove, btnType, btnMemory);
Scene scene = new Scene(root, 200, 350);
primaryStage.setScene(scene);
primaryStage.show();
}
}
If ObservableValue stores weak reference to a listener, you wouldn't have a problem. It can be mimicked by next example:
public class LeakListener extends Application {
private static class NonLeakingListener implements InvalidationListener {
// we need listener to don't hold reference on TextField as well
private final WeakReference<TextField> wtf;
private final int[] placeHolder = new int[10000];
public NonLeakingListener(TextField tf) {
this.wtf = new WeakReference<>(tf);
}
public void invalidated(Observable i) {
if (wtf.get() != null) {
wtf.get().setText(wtf.get().getText() + ".");
}
}
}
#Override
public void start(Stage primaryStage) {
final Pane root = new VBox(3);
final Button btnType = new Button("Type in all");
// Here is rough weak listeners list implementation
WeakHashMap<TextField, NonLeakingListener > m = new WeakHashMap<>();
btnType.armedProperty().addListener((e)-> {
for (TextField tf : m.keySet()) {
m.get(tf).invalidated(null);
}
});
Button btnAdd = new Button("Add");
btnAdd.setOnAction((e) -> {
TextField tf = new TextField();
root.getChildren().add(tf);
m.put(tf, new NonLeakingListener(tf));
});
Button btnRemove = new Button("Remove");
btnRemove.setOnAction((e) -> {
// find random TextEdit element
Optional<Node> toRemove = root.getChildren().stream().filter((Node t) -> t instanceof TextField).findAny();
// if any, and remove it
if (toRemove.isPresent()) {
root.getChildren().remove(toRemove.get());
}
});
Button btnMemory = new Button("Check Memory");
btnMemory.setOnAction((e)-> {
System.gc();
System.out.println("Free memory (bytes): " + Runtime.getRuntime().freeMemory());
});
root.getChildren().addAll(btnAdd, btnRemove, btnType, btnMemory);
Scene scene = new Scene(root, 200, 350);
primaryStage.setScene(scene);
primaryStage.show();
}
}
i am new to Xamarin monoandroid and i am facing a problem in adding a custom view to my layout. i have no idea what i am doing wrong. little help will be great full and this is my custom view class
onDraw method is called but i don't get the output and no errors.
class PositionDrawer : View
{
private int count;
private int position;
private IPositionDrawer cinterface;
private Activity cactivity;
private int container;
private int p;
private ScoreFeed scoreFeed1;
private ScoreFeed scoreFeed2;
public PositionDrawer(Activity context, int count, int positionr, Activity cactivity) :
base (context)
{
//Initialize ();
this.cactivity = cactivity;
this.cinterface = cinterface;
this.count = count;
this.position = positionr;
//this.OnDraw();
Initialize();
}
private void Initialize()
{
//this.Invalidate();
// this.SetMeasuredDimension(100, 100);
this.SetWillNotDraw(false);
Console.WriteLine(this.WillNotDraw());
}
protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
base.OnMeasure(widthMeasureSpec, heightMeasureSpec);
}
public void SetDrawer(int count, int positionr, Activity cactivity)
{
this.cactivity = cactivity;
this.cinterface = cinterface;
this.count = count;
this.position = positionr;
//base(cactivity);
}
protected override void OnDraw(Canvas canvas)
{
base.OnDraw(canvas);
Paint blue = new Paint();
blue.Color = Color.Red;
float screenwidth = cactivity.WindowManager.DefaultDisplay.Width;
canvas.DrawRect(screenwidth * position-1, 0, screenwidth * position, 20, blue);
Console.WriteLine("SW1:" + screenwidth + "pos1:" + position);
// LinearLayout can =cactivity.FindViewById<LinearLayout>(container);
//cinterface.getview(this);
}
}
and i use following code to add view to the layout.
View pd = new PositionDrawer(this, 3, position, this);
container = FindViewById<LinearLayout>(Resource.Id.position);
container.RemoveAllViews();
container.AddView(pd);
thanks in advance.
You need to implement the correct ctors.
When you implement the View class then you have to at least have the ctor with the following signature:
public PositionDrawer(IntPtr javaReference, JniHandleOwnership transfer)
: base(javaReference, transfer) { }
And if you are using the View in a AXML layout you also need the one with the following signature:
public PositionDrawer(Context context, IAttributeSet attrs, int defStyle)
: base(context, attrs, defStyle)
Otherwise when you create Views from code, you need to give them some LayoutParameters otherwise they do not know their own size.
How do I print in monomac? This is as far as I can get, but I can't seem to get a reference to the graphics context in the NSView. If I add a control to the PrintDoc that's fine, but I want to draw.
//Print Function
void Print(){
PrintDoc NewDoc = new PrintDoc ();
NewDoc.SetFrameSize(new SizeF(600,1000));
NSPrintOperation P = NSPrintOperation.FromView (NewDoc);
P.RunOperation ();
}
//NSView to be printed
class PrintDoc:NSView
{
public PrintDoc ()
{
}
public override void DrawRect (System.Drawing.RectangleF dirtyRect)
{
//NSPrintOperation.CurrentOperation.Context !! this is null
//NSGraphicsContext.CurrentContext !! this hangs
}
}
I've managed to get it working by getting the context manually, instead of using NSGraphicsContext.CurrentContext:
https://github.com/picoe/Eto/blob/feature/printing/Source/Eto.Platform.Mac/Forms/Printing/PrintDocumentHandler.cs#L39
Snippet:
static IntPtr selCurrentContext = Selector.GetHandle ("currentContext");
static IntPtr classNSGraphicsContext = Class.GetHandle ("NSGraphicsContext");
public override void DrawRect (System.Drawing.RectangleF dirtyRect)
{
var operation = NSPrintOperation.CurrentOperation;
var context = new NSGraphicsContext(Messaging.IntPtr_objc_msgSend (classNSGraphicsContext, selCurrentContext));
// this causes monomac to hang for some reason:
//var context = NSGraphicsContext.CurrentContext;
}