Late last week Chen finally committed one of our long outstanding promises to the LWUIT community, a rewrite of the aging TabbedPane. When we initially released LWUIT 1.0, the tabbed pane was one of the more complex components since it depended on several different LWUIT components to provide its functionality and was limited by missing features in LWUIT.
When the tabbed pane was written there was only one style per component, there was no Border object, no z-ordering. Eventually we chose an architecture for the TabbedPane that revolved around a list component coupled with a container and rather elaborate border drawing. The biggest drawback was the tedious customization process requiring manually deriving the look and feel to customize the renderer logic of the tabs.
The final push we needed to "just do it" was from Thorsten who took my swipe demo code and just turned it into a more real world demo using actual components... Very cool stuff. This inspired Chen to truly revolutionize the component and create a completely new touch optimized tabbed pane implementation that still works with the regular keyboard although differently (you now have to press fire to actually switch a tab).
Since the changes are so huge we decided to create a whole new drop in component called Tabs which is a drop in replacement for TabbedPane (just change all references to Tabs). For the next version of LWUIT we will probably remove TabbedPane entirely and have now deprecated its usage.
In the video you can see a very simple demo, the component supports allot of functionality that isn't demoed such as hidden tabs (for just a gesture based UI), full customization of the tabs etc. To make this demo I just changed the tabbed pane references in the LWUIT demo to Tabs.
Sunday, August 22, 2010
Wednesday, August 11, 2010
Basic Usage of LWUIT4IO
Last week I wrote about LWUIT4IO but didn't really explain how to utilize it properly and what makes it completely different from just using the GCF (Generic Connection Framework: Connector.open etc.).
Normally in MIDP you would just connect to the internet using Connector.open(String, ?) and get a connection object or a stream. The process seems simple enough but there are lots of hidden caveats in this process. For instance you would need to handle errors in case they happen (and they often do on a mobile device), in which case you need to show an error dialog (which is usually very uniform for all the connections you have in your application.
You also need to conduct the networking in a separate thread that is neither the LWUIT nor the default MIDP thread since these threads will block the UI from updating. After finishing every operation or in case of an exception it is critical in MIDP to cleanup all the connections/streams appropriately. Developers often forget to do this because the GC often removes that need, but with the GCF it is often critical to invoke close() otherwise native resources won't be freed and might cause issues on some devices (very common issue in feature phones).
LWUIT4IO tries to solve all of these by hiding the entire process of networking behind a component API, e.g. to connect to a URL and fetch its content in LWUIT4IO one could do just:
NetworkManager.getInstance().addToQueue(myRequest);
You do first need to initialize LWUIT4IO by invoking (similar to the need of invoking Display.init once):
NetworkManager.getInstance().start();
The request object is a callback class that includes the URL/arguments and request method (get/post). The network thread will perform the connection and invoke the proper callback methods within the request object e.g.:
ConnectionRequest myRequest = new ConnectionRequest();
myRequest.setUrl("http://mysite.com/");
myRequest.addArg("arg", "value");
addResponseListener(new ActionListener() {
public void actionEvent(ActionEvent ev) {
NetworkEvent n = (NetworkEvent)ev;
// gets the data from the server as a byte array...
byte[] data = (byte[])n.getMetaData();
}
});
Alternatively one can override the code to read/write the request values e.g.:
ConnectionRequest myRequest = new ConnectionRequest() {
protected void readResponse(InputStream input) throws IOException {
// read from the input stream...
}
};
Besides the advantages of the more generic code, the true advantages you gain in using this approach is quite remarkable:
Normally in MIDP you would just connect to the internet using Connector.open(String, ?) and get a connection object or a stream. The process seems simple enough but there are lots of hidden caveats in this process. For instance you would need to handle errors in case they happen (and they often do on a mobile device), in which case you need to show an error dialog (which is usually very uniform for all the connections you have in your application.
You also need to conduct the networking in a separate thread that is neither the LWUIT nor the default MIDP thread since these threads will block the UI from updating. After finishing every operation or in case of an exception it is critical in MIDP to cleanup all the connections/streams appropriately. Developers often forget to do this because the GC often removes that need, but with the GCF it is often critical to invoke close() otherwise native resources won't be freed and might cause issues on some devices (very common issue in feature phones).
LWUIT4IO tries to solve all of these by hiding the entire process of networking behind a component API, e.g. to connect to a URL and fetch its content in LWUIT4IO one could do just:
NetworkManager.getInstance().addToQueue(myRequest);
You do first need to initialize LWUIT4IO by invoking (similar to the need of invoking Display.init once):
NetworkManager.getInstance().start();
The request object is a callback class that includes the URL/arguments and request method (get/post). The network thread will perform the connection and invoke the proper callback methods within the request object e.g.:
ConnectionRequest myRequest = new ConnectionRequest();
myRequest.setUrl("http://mysite.com/");
myRequest.addArg("arg", "value");
addResponseListener(new ActionListener() {
public void actionEvent(ActionEvent ev) {
NetworkEvent n = (NetworkEvent)ev;
// gets the data from the server as a byte array...
byte[] data = (byte[])n.getMetaData();
}
});
Alternatively one can override the code to read/write the request values e.g.:
ConnectionRequest myRequest = new ConnectionRequest() {
protected void readResponse(InputStream input) throws IOException {
// read from the input stream...
}
};
Besides the advantages of the more generic code, the true advantages you gain in using this approach is quite remarkable:
- You don't need to write threading code - LWUIT callbacks (e.g. actionPerformed) are on the LWUIT EDT seamlessly. Everything else automatically goes to the network thread...
- Exceptions are caught and handled without any need to do anything.
- You don't need to close streams or connections ever!
- All streams are buffered so you don't need to worry abound efficiency of reading from a data input stream.
- You can utilize inheritance and reuse code far more extensively
- Cookies, redirects work pretty much like you would expect without any additional code.
Thursday, August 5, 2010
LWUIT 1.4 Finally Released
Its taken some time since our intended release date and by not allot has changed in the SVN but the 1.4 binary release is finally official! Get it here.
This release is very important since it marks our first release under Oracle which will hopefully make the next LWUIT release smoother now that we understand the process.
This is mostly a stability and bug fix release with the major feature being the new XHTML component which includes CSS support. Besides that we finally have a multi-line text field, allowing lightweight customizable input to span more than one line. We also added tools to customize the LWUIT VKB for some advanced use cases. Last but not least we introduced some more advanced animations than the previous static animation support.
This release is very important since it marks our first release under Oracle which will hopefully make the next LWUIT release smoother now that we understand the process.
This is mostly a stability and bug fix release with the major feature being the new XHTML component which includes CSS support. Besides that we finally have a multi-line text field, allowing lightweight customizable input to span more than one line. We also added tools to customize the LWUIT VKB for some advanced use cases. Last but not least we introduced some more advanced animations than the previous static animation support.
Monday, August 2, 2010
Introducing LWUIT For IO (LWUIT4IO)
When Chen started LWUIT he limited his ambitions to solving the UI portability issues and with those limited ambitions we were able to over deliver by providing a framework that delivered an easier, faster & better UI while still maintaining the portability advantage.
The limited scope of LWUIT is one of its strengths allowing us to focus on the issues at hand and not stray too much.
IO (storage, filesystem & network) is probably the biggest and most common portability stumbling block after UI & with LWUIT4IO we aim to simplify the process of working with these API's across platforms/devices without sacrificing portability or vendor specific features. The underlying API's are given the "LWUIT treatment" where we abstract lots of the thread related heavy lifting behind and component like unified API and try to make the whole process reasonably fool proof.
LWUIT4IO is fully optional, at it depends on LWUIT but the reverse isn't true. LWUIT has no dependency on LWUIT4IO and we intend to keep it this way since we assume many of you have written elaborate IO frameworks of your own and might not be ready to switch.
If you do decide to switch here are some of the things we worked on for LWUIT4IO and some of the features we have in our pipeline (notice that LWUIT4IO being brand new is still labeled as alpha quality software):
Default Connectors - e.g. File download connector
The limited scope of LWUIT is one of its strengths allowing us to focus on the issues at hand and not stray too much.
IO (storage, filesystem & network) is probably the biggest and most common portability stumbling block after UI & with LWUIT4IO we aim to simplify the process of working with these API's across platforms/devices without sacrificing portability or vendor specific features. The underlying API's are given the "LWUIT treatment" where we abstract lots of the thread related heavy lifting behind and component like unified API and try to make the whole process reasonably fool proof.
LWUIT4IO is fully optional, at it depends on LWUIT but the reverse isn't true. LWUIT has no dependency on LWUIT4IO and we intend to keep it this way since we assume many of you have written elaborate IO frameworks of your own and might not be ready to switch.
If you do decide to switch here are some of the things we worked on for LWUIT4IO and some of the features we have in our pipeline (notice that LWUIT4IO being brand new is still labeled as alpha quality software):
- Component based connections - Network connections are made with objects and callback events. When a response finishes its processing on the network thread it seamlessly transitions to an event on the LWUIT thread.
- LWUIT Component integration - currently the new slider component seamlessly shows progress indication in the IO framework. We plan to seamlessly integrate the HTML component as well making it both more efficient and easier to use.
- Buffering - all network connections in LWUIT4IO are seamlessly buffered providing easier programming (no need to manually buffer) and faster downloads.
- Timeout support - GCF (MIDP's Generic Connection Framework) doesn't support thread timeouts. LWUIT4IO compensates for that by providing timeouts on platforms that support them and "faking" timeouts on platforms that don't (such as MIDP) by abandoning the network thread and creating a new one seamlessly.
- Cookies - server cookies are managed seamlessly by LWUIT4IO.
- Filesystem - the LWUIT4IO portable filesystem API is simpler and more portable than JSR75.
- Storage - LWUIT4IO supports named storage streams to place data within application specific named streams. This is based on RMS when running on MIDP but provides an easier to use stream based API.
- Serialization - LWUIT4IO supports a simple object serialization API for application state saving.
- Access Point - LWUIT4IO provides an API for detecting the available internet access points for the device and picking the right one. This is device specific and works seamlessly on devices that support it such as newer Symbian devices and RIM devices.
- Unified Error Handling - LWUIT4IO supports error handling as LWUIT events as well as a single point error handler.
- JSON Parser - LWUIT4IO ships with a simple JSON parser. We plan to expose the existing LWUIT HTML XML parser in future versions of LWUIT to make REST programming easier in LWUIT.
- Caching Framework - LWUIT4IO contains a smart caching system that keeps frequently used elements in RAM and optionally reverts to using storage cache.
- Mutli-threaded networking (experimental) - LWUIT4IO supports seamless integration with many network threads while assigning specific duties to specific threads if so desired.
- Default connectors - simple web services are already implemented for convenience and reference in LWUIT4IO such as Google REST search, Twitter & image download service.
Default Connectors - e.g. File download connector
Subscribe to:
Posts (Atom)