How to refresh a ContainerList - codenameone

What is the best way to update a ContainerList in runtime. My addPullToRefresh in my ContainerList was just called, I go & fetch new data but how do I refresh the data to show in the ContainerList. How do I force it to rebuild itself with a new model?
I tried rebuilding a new ContainerList and replacing it in the Form, doing it all in a separate thread and doing it within a Display.getInstance().invoke... (tried all types of invoke), but I get a NullPointerException here
at
com.codename1.ui.plaf.DefaultLookAndFeel$1.animate(DefaultLookAndFeel.java:1599)
at com.codename1.ui.Form.loopAnimations(Form.java:1295)
at com.codename1.ui.Form.repaintAnimations(Form.java:1280)
at com.codename1.ui.Display.edtLoopImpl(Display.java:1075)
at com.codename1.ui.Display.mainEDTLoop(Display.java:994)
at com.codename1.ui.RunnableWrapper.run(RunnableWrapper.java:120)
at com.codename1.impl.CodenameOneThread.run(CodenameOneThread.java:176)
Learned more about the issue, so here is the actual question:
I have a container (WatchList) that has in it a ContainerList (LikeListView). When the ContainerList addPullToRefresh is called it makes a call to contentChanged() on its parent component (WatchList). The contentChanged creates a new LikeListView and replaces the old one with the new one. This is how the code looks like:
public void contentChanged()
{
final WatchList self = this;
Display.getInstance().scheduleBackgroundTask(new Runnable ()
{
public void run ()
{
CloudData.refreshLikeList();
Display.getInstance().callSerially(new Runnable()
{
public void run()
{
LikeListView lv = new LikeListView (self);
self.replace (myListView, lv, null);
myListView = lv;
}
});
}
});
}
It runs with no problem, but after it is done, there is a NullPointerException
com.codename1.ui.plaf.DefaultLookAndFeel$1.animate(DefaultLookAndFeel.java:1599)
at com.codename1.ui.Form.loopAnimations(Form.java:1295)
at com.codename1.ui.Form.repaintAnimations(Form.java:1280)
at com.codename1.ui.Display.edtLoopImpl(Display.java:1075)
at com.codename1.ui.Display.mainEDTLoop(Display.java:994)
at com.codename1.ui.RunnableWrapper.run(RunnableWrapper.java:120)
at com.codename1.impl.CodenameOneThread.run(CodenameOneThread.java:176)
It looks as if the old LikeListView is being called to animate by the look and feel, and it fails on line 1599 in DefaulrLookAdnFeel
cmp.getComponentForm().deregisterAnimated(this);
as cmp.getComponentForm() returns null for the removed component.
So, the old component is held somewhere in the DefaultLookAndFeel animated list? How do I get it out of there?
Thanks
-Yishai

Make the code that you used to create the initial list model and build ContainerList a method.
If you're using Netbeans, Highlight the block of code -> Right click -> Refactor -> Introduce -> Method and give it a name or press Alt + Shift + M.
Call that method inside the run() method of your addPullToRefresh.
Another thing you can do is call reloadForm();

Related

PageInit does not work when on different class

As the title says I am using PageFactory to initialize my elements.
When I use PageFactory.initElements on the page I want to use my elements everything is fine and works correctly, but when I try to create a new class with PageFactory to have it initialize all elements there I get a null pointer exception.
Below you will find the code I am using:
Actions.java
TestIds testIds = new TestIds();
public void initElements(WebDriver driver) {
PageFactory.initElements(driver, cashierIds);
}
The above lines work when included in my Actions class but when I create a new Class called ElementInitialization.java, move everything in it and then call it my elements throw nullPointerException.
Is there a different way to call the specific faction to work everywhere?

How use waits in Html Elements framework

I have tried to use Html Elements framework. Here are one of my blocks:
#Block(#FindBy(id = "test"))
public class FirstBlock extends HtmlElement {
#FindBy(id = "nameS")
private TextInput id;
#FindBy(id = "saveBt")
private Button add;
public void addNewClient(String idText) {
add.click();
id.sendKeys(idText);
}
}
I have initialized page factory like:
PageFactory.initElements(new HtmlElementDecorator(driver), this);
Now I want to wait after add.click(); until next element is present.
As I found out where is possibility to use AjaxElementLocatorFactory
But how can I make this using Html Elements framework?
HtmlElements use AjaxElementLocatorFactory by default, so you don't need any explicit waits in your code. It will try to find your id element until succeed and then executes sendKeys() on it. In case element wait timeout will be reached, it'll throw ElementNotFound exception.

Delegate with Objects Solution WPF

We found follwing solution to this Problem
Following code might help you solve the issue of updating a gui element from another thread
Module level
delegate void updateCallback(string tekst);
This is the method to update your element :
private void UpdateElement(string tekst)
{
if (element.Dispatcher.CheckAccess() == false)
{
updateCallback uCallBack = new updateCallback(UpdateElement);
this.Dispatcher.Invoke(uCallBack, tekst);
}
else
{
//update your element here
}
}
This is Working fine with primitive Types like String Int ... but we want to use a Instance of a Class.
Our delegate declaration Looks like this example:
delegate void updateCallback(Maps newMap)
We want to use it to update a Window which is created in a diffrent thread.
Howerever when we using objects we get:
The calling thread cannot access this object because a diffrent thread owns it.

How to figure out which SQLDependency triggered change function?

I'm exploring query notifications with the SQLDependency class. Building a simple working example is easy, but I feel like I'm missing something. Once I step past a simple one-table/one-dependency example I'm left wondering how can I figure out which dependency triggered my callback?
I'm having a bit of trouble explaining, so I included the simple example below. When AChange() is called I cannot look at the sql inside the dependency, and i don't have a reference to the associated cache object.
So what's a boy to do?
Option 1 - create a distinct function for each object i want to track and hard code the cache-key (or relevant information) in the callback. This feels dirty & eliminates the posibility of adding new cache items without deploying new code--ewww.
Option 2 - Use the Dependency Id property and a parallel tracking structure
Am I just missing something? Is this a deficiency in the SQLDependency structure? I've I've looked at 20 different articles on the topic and all of them seem to have the same hole. Suggestions?
Code Sample
public class DependencyCache{
public static string cacheName = "Client1";
public static MemoryCache memCache = new MemoryCache(cacheName);
public DependencyCache() {
SqlDependency.Start(connString);
}
private static string GetSQL() {
return "select someString FROM dbo.TestTable";
}
public void DoTest() {
if (memCache["TEST_KEY"] != null ) {
Debug.WriteLine("resources found in cache");
return;
}
Cache_GetData();
}
private void Cache_GetData() {
SqlConnection oConn;
SqlCommand oCmd;
SqlDependency oDep;
SqlDataReader oRS;
List<string> stuff = new List<string>();
CacheItemPolicy policy = new CacheItemPolicy();
SqlDependency.Start(connString);
using (oConn = new SqlConnection(connString) ) {
using (oCmd = new SqlCommand(GetSQL(), oConn) ) {
oDep = new SqlDependency(oCmd);
oConn.Open();
oRS = oCmd.ExecuteReader();
while(oRS.Read() ) {
resources.Add( oRS.GetString(0) );
}
oDep.OnChange += new OnChangeEventHandler (AChange);
}
}
memCache.Set("TEST_KEY", stuff, policy);
}
private void AChange( object sender, SqlNotificationEventArgs e) {
string msg= "Dependency Change \nINFO: {0} : SOURCE {1} :TYPE: {2}";
Debug.WriteLine(String.Format(msg, e.Info, e.Source, e.Type));
// If multiple queries use this as a callback how can i figure
// out WHAT QUERY TRIGGERED the change?
// I can't figure out how to tell multiple dependency objects apart
((SqlDependency)sender).OnChange -= Cache_SqlDependency_OnChange;
Cache_GetData(); //reload data
}
}
First and foremost: the handler has to be set up before the command is executed:
oDep = new SqlDependency(oCmd);
oConn.Open();
oDep.OnChange += new OnChangeEventHandler (AChange);
oRS = oCmd.ExecuteReader();
while(oRS.Read() ) {
resources.Add( oRS.GetString(0) );
}
Otherwise you have a window when the notification may be lost and your callback never invoked.
Now about your question: you should use a separate callback for each query. While this may seem cumbersome, is actually trivial by using a lambda. Something like the following:
oDep = new SqlDependency(oCmd);
oConn.Open();
oDep.OnChange += (sender, e) =>
{
string msg = "Dependency Change \nINFO: {0} : SOURCE {1} :TYPE: {2}";
Debug.WriteLine(String.Format(msg, e.Info, e.Source, e.Type));
// The command that trigger the notification is captured in the context:
// is oCmd
//
// You can now call a handler passing in the relevant info:
//
Reload_Data(oCmd, ...);
};
oRS = oCmd.ExecuteReader();
...
And remember to always check the notification source, info and type. Otherwise you run the risk of spinning ad-nauseam when you are notified for reasons other than data change, like invalid query. As a side comment I would add that a good cache design does not refresh the cache on invalidation, but simply invalidates the cached item and lets the next request actually fetch a fresh item. With your 'proactive' approach you are refreshing cached items even when not needed, refresh multiple times before they are accessed etc etc. I left out from the example error handling and proper thread synchronization (both required).
Finally, have a look at LinqtoCache which does pretty much what you're trying to do, but for LINQ queries.

Does the WPF DocumentPaginator keep all DocumentPages in memory until it finishes a print job?

Strictly theoretical question concerning WPF's DocumentPaginator:
When using the WPF DocumentPaginator class to print a multi-page document, does the paginator keep all of the DocumentPages it requests over the history of the print job in memory until the document finishes printing? Or does it ever dispose of any DocumentPages it no longer needs before the print job is finished (i.e. to free up memory)? Is there a way to manually tell the paginator to free old/unneeded DocumentPages in the course of printing without hitting an exception?
Many thanks for your help with this!
I had exactly the same problem as you have.
It doesnt dispose the Pages which got loaded earlier. What I did to solve this issue was to hold a reference to the loaded page at the end of the GetPage() Method and dispose the last loaded page in the beginning of the GetPage Method.
here the answer to your aditional question:
I have the impression the implementation of System.Windows.Controls.PrintDialog.Print(DocumentPaginator, title) is something like that:
Public void PrintDocument(DocumentPaginator paginator, string title)
{
Dictionary<int, DocumentPage> pages = new Dictionary<int DocumentPage>();
for(int i=0; i<paginator.PageCount(); i++)
{
pages.Add(i, paginator.GetPage(i));
UnknownPrinterEngine.SendPageToPrinter(pages(i)); //this is just imagination
}
}
if the implementation is really something like that, a local reference to each processed page stays alive (in the dictionary) until the method execution finished. --> No memory will get freed.
What i did to avoid that (GetPage implementation in the class which extends DocumentPaginator):
DocumentPage lastLoadedPage = null;
public DocumentPage GetPage(int pageNumber)
{
if(lastLoadedPage != null)
{
lastLoadedPage.Dispose()
}
//MyPrintControl should be your custom UserControl which represents the page to print
myPrintControl pageContent = new MyPrintControl();
pageContent.Width = PageSize.Width;
pageContent.Height = PageSize.Height;
pageContent.Measure(PageSize);
pageContent.Arrange(new Rect(new Point(0,0), PageSize));
DocumentPage actualPage = New DocumentPage(pageContent);
lastLoadedPage = actualPage;
return actualPage;
}
And at the end you should implement the IDisposable interface and in the Dispose Method clean up the lastLoadedPage field to free the memory of the last page too.
Look into System.Windows.Xps.VisualsToXpsDocument This fixes the problem I have running out of memory when creating large xps document. Also look into PrintQueue.CreateXpsDocumentWriter(somePrintQueue) . Sorry, I don't have enough reps to just make this a comment.

Resources