UI update on widget stops after a few hours with no error or exception - android-widget

I created a widget that uses a service with wakelock to update and parse data from an xml and update the widget's UI so that items would "rotate every few seconds (standard news feed widget).
The problem is that the UI stops updating after a few hours although the data keeps updating.
Here's the code I am using to update the UI:
mUpdateTimeTask = null;
mUpdateTimeTask = new Runnable()
{
public void run()
{
if(which_item+1 < Widget_titles.length)
which_item++;
else
which_item = 0;
if(Widget_which_item_ed != null)
{
Widget_which_item_ed.putInt("WIDGET_WHICH_ITEM", which_item);
Widget_which_item_ed.commit();
}
else
{
Widget_which_item = context.getSharedPreferences("WIDGET_WHICH_ITEM", Context.MODE_WORLD_WRITEABLE);
Widget_which_item_ed = Widget_which_item.edit();
Widget_which_item_ed.putInt("WIDGET_WHICH_ITEM", which_item);
Widget_which_item_ed.commit();
}
updateViews.setTextViewText(R.id.WidgetText, Widget_titles[which_item]);
updateViews.setTextViewText(R.id.WidgetPostTime, rightNow.get(Calendar.MONTH)+"/"+rightNow.get(Calendar.DATE)+"/"+rightNow.get(Calendar.YEAR));
manager = AppWidgetManager.getInstance(context);
manager.updateAppWidget(WidgetId, updateViews);
mHandler.removeCallbacks(mUpdateTimeTask);
mHandler.postDelayed(this, widget_interval * 1000);
}
};
mHandler.postDelayed(mUpdateTimeTask, widget_interval * 1000);
Log.i(TAG, "sliding update handler was configed");
I am really stuck and could really use help.
Edit:
i managed to go around this problem by implementing the BroadCastReciever for the screen on/off intents as shown in a tutorial here: http://thinkandroid.wordpress.com/2010/01/24/handling-screen-off-and-screen-on-intents/
and therefore the amount of time that the widget needs to run is much smaller.

Edit:
i managed to go around this problem by implementing the BroadCastReciever for the screen on/off intents as shown in a tutorial here: http://thinkandroid.wordpress.com/2010/01/24/handling-screen-off-and-screen-on-intents/ and therefore the amount of time that the widget needs to run is much smaller.

Related

Wicket 6 - Feedback message not showing until request after the request in which it happened

I have an AjaxButton. The event fires, and I'm testing a scenario where I need to add a feedback and return without committing the change. I add the feedback at the page level (our feedback only shows page level messages...others are showing on component level feedback panels). I add the WebMarkupContainer that contains the feedback panel to the target. This exact thing works on every other button on the page.
But for this button, which happens to be the only one where defaultformprocessing is not false, the feedback doesn't show. To the user's view, nothing happens except our processing veil appears and then disappears. If I hit submit again, THEN the message and feedback are shown. I stuck a timestamp on it to see if it was showing the one from the 2nd request or the 1st. It's from the 1st.
What's more, a breakpoint in the feedback's filter shows that the filter was never called in the 1st request, but is called BEFORE the event processing on the 2nd request. It accepts the message as intended.
I set defaultformprocessing to FALSE on this button as a test, and in fact, messages suddenly work. But of course, that also means the form doesn't get processed. Can someone help me square this circle?
AjaxButton:
add(new AjaxButton("btnCreateRequest", getForm()) {
#Override
public void onSubmit(AjaxRequestTarget target, Form<?> form) {
//stuff happens
target.add(getFeedbackPanelForAjax());
String date = new Date().toGMTString();
System.out.println("ADDING MESSAGE - " + date);
getPage().error("This is a message! " + date);
return;
}
#Override
public void onError(AjaxRequestTarget target, Form<?> form) {
getPage().error("There was an error processing your request");
target.add(getFeedbackPanelForAjax());
target.add(form);
}
}.setVisible(enabled));
UPDATE:
getFeedbackPanelForAjax returns the web markup container that the feedback resides in. I've also tried adding the feedback directly to the target.
public Component getFeedbackPanelForAjax() {
return (Component) getForm().get("feedbackWmc");
}
Where the feedback is added:
feedback = new FRFeedbackPanel("feedback") {
#Override
public boolean isVisible() {
if(anyMessage()){
return true;
} else {
return false;
}
}
};
// feedback container
WebMarkupContainer feedbackWmc = new WebMarkupContainer("feedbackWmc");
getForm().add(feedbackWmc.setOutputMarkupId(true).setOutputMarkupPlaceholderTag(true));
feedbackWmc.add(feedback.setOutputMarkupId(true).setOutputMarkupPlaceholderTag(true));
I can say that through debugging, I put a breakpoint in anyMessage() and it returns false in this case at the same time that getPage().getFeedbackMessages() returns the message correctly. I commented out this override of isVisible() and indeed, the message shows. The problem is, that it means the artifacts of the feedback panel show when there are no messages as well, which is not what we want.
This anyMessage() solution works perfectly when I'm in an event that is defaultformprocessing=false. I suppose I could do an anyMessage() || getPage().getFeedbackMessages(), but my understanding was that anyMessage was supposed to find if there was ANY message in the hierarchy for this panel. Is that not so?
I assume you cannot replicate the problem in a small quickstart?
One idea: I've seen similar problems when the FeedbackPanel collects its messages too early, i.e. before you add the error to the page.
FeedbackMessagesModel keeps the messages to render until the end of the request - maybe some of your code triggers this by accessing the messages model.

JavaFX - Service Task not always running

I have a slightly odd issue and unfortunately it's not one I can easily write a standalone class for.
Within my application I have a TableView (on a tab) which is clickable. Clicking on a row in this TableView opens a new Tab with a data relating to the clicked row in a new TableView.
The TableViews are bound to a custom class that extends ModifiableObservableListBase. This allows a Scrollbar to be used to request new data from the server based on the top and bottom rows of the viewport.
This all works well.
I also have a Service in my subclass of ModifiableObservableListBase that is used to improve the rendering of data under high load. It uses a LinkedBlockingQueue and countDownLatch so that only most recent view is updated to the UI preventing unnecessary redraws. Using the following:
setAll(list);
This also works well.
So far so good!
What I've noticed is that when I open and close these tabs multiple times (no fixed number), at some point the TableView will stop updating with data. The data is requested from the server and received but the Service which is used to control how data is added to the ModifiableObservableListBase fails to move out of the SCHEDULED state. This means that the Task that has been created never runs. I'm struggling to see why this would work correctly x times and then stop working.
Any help would be really welcomed, sorry I don't have a standaone application that replicates this issue. I will try to recreate it.
The following Service is constructed in the constructor of my subclass of ModifiableObservableListBase which is constructed each time a new tab(including the corresponding TableView which is bound to the ModifiableObservableListBase ) is added to the UI.
Service upDateService = new Service() {
#Override
protected Task createTask() {
//when the code fails it still calls to here.
return new Task() {
#Override
protected Object call() throws Exception {
//when the code fails it doesn't call the call() method
while (true) {
List<T> list = updateQueue.take();
updateLatch = new CountDownLatch(1);
//now put on the FX Application Thread
Platform.runLater(() -> {
if (list.size() > 0 && list.get(0) instanceof TableStructure) {
totalRowCount.set(((TableStructure) list.get(0)).getTotalDbRowCount());
}
setAll(list);
updateLatch.countDown();
});
try {
updateLatch.await(1, TimeUnit.MINUTES);
updateLatch = null;
}
catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
};
}
};
upDateService.start();

Setting min and max zoomLevels (GWT-OpenLayers)

I want to set a minimum and a maximum zoom level in my map.
My first idea was to listen to 'zoomstart' events, but the org.gwtopenmaps.openlayers.client.Map class doesn't implement any listener with such event type. Then I tried to listen to 'zoomend' events. My idea was to check the zoomlevel after the zoom event and if it is higher/lower than a threshold value than i zoom to that threshold value. Example code:
#Override
public void onMapZoom(MapZoomEvent eventObject) {
if (eventObject.getSource().getZoom() > 18) {
eventObject.getSource().zoomTo(18);
}
}
But i found, the zoomTo event doesn't fire in this case. Has anybody got a solution to this problem?
Great idea Imreking.
I have added this to the GWT-Openlayers library.
So if you download the latest version from github now you can do :
map.setMinMaxZoomLevel(6, 8);
And you no longer need some javascript method in your own code.
I actually also added a showcase but having difficulties uploading it to our website.
Uploading the new showcase has now succeeded.
See http://demo.gwt-openlayers.org/gwt_ol_showcase/GwtOpenLayersShowcase.html?example=Min%20max%20zoom%20example to see an example of newly added Map.setMinMaxZoomLevel(minZoom, maxZoom).
I don't think this is possible in OpenLayers (normal and GWT).
According to me two solutions are available.
Option 1
This is ugly for the user. As he sees the map getting zoomed, and just after this going back to the previous zoomlevel.
The Timer is needed to give OL the chance to animate the zoom.
map.addMapZoomListener(new MapZoomListener()
{
#Override
public void onMapZoom(final MapZoomEvent eventObject)
{
Timer t = new Timer()
{
#Override
public void run()
{
if (eventObject.getSource().getZoom() > 15)
{
map.zoomTo(15);
}
else if (eventObject.getSource().getZoom() < 10)
{
map.zoomTo(10);
}
}
};
t.schedule(500);
}
});
Option 2
Don't use the zoom default zoom control but create your own zoom buttons (using normal GWT), and putting these on top of the map. If you want you can style these buttons in the same way as the normal buttons. The trick 'create in normal GWT, and make it look like OL' is a trick I use a lot (for example to create a much more advanced layer switcher).
Note : I am one of the developers of GWT-OpenLayers, if you want I can add an example to our showcase displaying how to do 'Option 2'.
Knarf, thank you for your reply. I tried the 'Option 1' and it worked, but i found another solution which is maybe more acceptable for the users.
My solution is:
map.isValidZoomLevel = function(zoomLevel) {
return ((zoomLevel != null) &&
(zoomLevel >= minZoomLevel) &&
(zoomLevel <= maxZoomLevel) &&
(zoomLevel < this.getNumZoomLevels()));
}
I overrode the isValidZoomLevel method. The minZoomLevel and maxZoomLevel variables were set when the application started. I don't like calling javascript from GWT code, but here i didn't have any other opportunity.

GWT MAP 3.8 (Google API) - Is onResize() needed to hide the "grey background"?

My problem:
- I display a map inside a popup and I have unloaded tiles (grey background).
- If I zoom out or in, then the map will fill the entire space (no grey background anymore).
My question:
- Have you any idea about my problem (Should I need to resize to hide the "grey background") ?
- I do not know if I should call onResize() inside the Runnable callback (code is above) or not ?
Thanks you,
My actual code: (I am using the javaxLoaderAPI)
// ENTRY POINT
GoogleMap map;
#UiField LayoutPanel gmap;
public void AjaxLoader_MAP() {
AjaxLoaderOptions options = AjaxLoaderOptions.newInstance();
options.setOtherParms("key=***&sensor=false&language=es");
Runnable callback = new Runnable() {
public void run() {
gmap.onResize(); // Should I call onResize() here ?
map = GoogleMap.create(gmap.getElement());
};
}
AjaxLoader.loadApi("maps", "3", callback, options);
}
May be related to the following post - GWT Google Map Api V3 - broken when changing it
I just posted an answer to that unanswered post as well. I believe it answers and sheds insight on this one as well.
I know this is an old post, but let me know if helps!
When calling mapWidget.triggerResize(), it's important to call it with some delay (Timer.schedule()) so that all the widget have been reset and then the map is resized.
This is how I trigger it:
#Override
protected void onReset() {
super.onReset();
Timer timer = new Timer() {
#Override
public void run() {
triggerResize();
}
};
timer.schedule(100);
}
Without timer, I was still getting grey tiles. Hope someone still finds it useful.

GWT SimplePager LastButton issue

I am facing problem with lastButton of SimplePager.
I have 3 pages in celltable, Page size=11 (1 empty record + 10 records(with value)), Total record=26.
I used CustomerPager by extending SimplePager.
In 1st attempt 1+10 records display in celltable : Next & Last page button is enabled (First & Prev button disabled) which is correct.
But LastPage button not working... :( Dont know whats the issue... (event not fires)
Strange behavior:
#1 Last page button is working only when I visit to last page(3 page in my case).
#2 Assume I am on 1st page n I moved to 2nd page(Total 3 pages in celltable). that time all buttons are enabled which is correct.
In this case Last button is working but behave like Next Button
My GWT application integrated into one of our product so cant debug it from client side.
May be index value is improper in setPage(int index) method from AbstractPager
Code flow is as follows for Last button
//From SimplePager
lastPage.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
lastPage();
}
});
#Override
public void lastPage() {
super.lastPage();
}
// From AbstractPager
/**
* Go to the last page.
*/
protected void lastPage() {
setPage(getPageCount() - 1);
}
protected void setPage(int index) {
if (display != null && (!isRangeLimited || !display.isRowCountExact() || hasPage(index))) {
// We don't use the local version of setPageStart because it would
// constrain the index, but the user probably wants to use absolute page
// indexes.
int pageSize = getPageSize();
display.setVisibleRange(pageSize * index, pageSize);
}
}
or may be some conditions false from above code(from setPage())
actual record = 26 and 3 Empty record (1st Empty record/page)
May b problem with dataSize :|
How I can check number of pages based on the data size?
?
How can I solve this problem?
edit: I found out that the default constructor of the pager doesn't give you a "last" button, but a "fast forward 1000 lines" button instead (horrible, right?) .
call the following constructor like so, and see your problem solved:
SimplePager.Resources resources = GWT.create(SimplePager.Resources.class);
SimplePager simplePager = new SimplePager(TextLocation.CENTER, resources , false, 1000, true);
the first "false" flag turns off the "fastforward button" and the last "true" flag turns on the "last" button.
also the last button will work only if the pager knows the total amount of records you have.
you can call the table's setRowCount function to update the total like so:
int totalRecordsSize = 26; //the total amount of records you have
boolean isTotalExact = true; //is it an estimate or an exact match
table.setRowCount(totalRecordsSize , isTotalExact); //sets the table's total and updates the pager (assuming you called pager.setDisplay(table) before)
if you are working with an attached DataProvider, than all it's updateRowCount method instead (same usage).
Without seeing more of your code, this is a hard question to answer as there could be multiple places where things are going wrong.
I would make sure you call setDisplay(...) on your SimplePager so it has the data it needs calculate its ranges.
If you can't run in devmode, I recommend setting up some GWT logging in the browser (write the logs to a popup panel or something, see this discussion for an example).
I think the problem is related with condition in the setPage(). Try putting SOP before if condition or debug the code
Only added cellTable.setRowCount(int size, boolean isExact) in OnRange change method AsyncDataProvider. My problem is solved :)
protected void onRangeChanged(HasData<RecordVO> display) {
//----- Some code --------
cellTable.setRowCount(searchRecordCount, false);
//----- Some code --------
}