ADF Mobile : Implementing the “Pull to Refresh” Pattern

One very common pattern in Mobile Apps is the use of “pull” to refresh a list of data in an App.

For one of my projects I suggested to use this pattern and I had to figure out a way to implement this in ADF Mobile. In this post I show you a way to implement this. If you are only interested in the refresh part, you might want to skip the first 5 steps. These explain in short the webservice and the basic ADF Mobile app. From step 6 on I explain how to implement the pattern

1. The webservice

For this example I use a simple webservice that returns a List of Locations. The webservice is a service enabled Application Module. I simply created Business Component (EO and VO) on the Locations table from the HR schema. I exposed the Locations view object as AllLocations, and added a method called getCurrentCount() on the Application Module Impl class. This method simply invokes the getEstimatedRowCount() to find out the number of rows. Next I created a new Service Interface on the Application Module. And that is about it for the service.

This all resides in a separate application and is deployed on a remote weblogic server. The mobile app will use this webservice.

2. The Mobile App

Create a simple ADF Mobile Application. In this application I need to call out to the webservice. For that I use a webservice datacontrol. Simply invoke the “create webservice” dialog, give the webservice a name and enter the URL of the WSDL.

In the second part of the wizard, I simply select the two operations that I need.

The webservice datacontrol is now finished. Both operations are now available from the datacontrol. The datacontrol looks like this:

3. The custom model

For the application I want to use a custom object model in order to be independent of the webservice data structure. This is common practice and recommended approach. The class that I use for this is called MyLocation.

Now I create a new class that I use in my mobile application to provide the app with data. This class is called LocationInfoDC. In this class I create a list of locations that I can display in the mobile app.

The AdfmfJavaUtilities.invokeDataControlMethod() returns a GenericType. This response needs to be “converted” to the custom object model described in step 3.

// The Return wraps the findAllLocations Result, so get that out of the Result
s_locationsList.clear();
for (int i = 0; i < result.getAttributeCount(); i++)
{
GenericType row = (GenericType)result.getAttribute(i);
MyLocation locationInformation = (MyLocation)
GenericTypeBeanSerializationHelper.fromGenericType(MyLocation.class, row);
AddLocation(locationInformation);
}

Another important part is the invocation of the client page refresh. The ProviderChangeSupport class is used for sending notifications relating to collection elements, so that components update properly when a change occurs in a Java bean data control. I refresh the collection delta, using the ProviderChangeSupport class. Since the provider change is required only when you have a dynamic collection exposed by a data control wrapped bean, there are only a few types of provider change events to fire:

fireProviderCreate—when a new element is added to the collection fireProviderDelete—when an element is removed from the collection fireProviderRefresh—when multiple changes are done to the collection at one time and you decide it is better to simply ask for the client to refresh the entire collection (this should only be used in bulk operations)

I use the fireProviderRefresh, asking for the client to refresh the entire collection.

The trick that does the magic:

providerChangeSupport.fireProviderRefresh("allLocations");

For this class I also generate a datacontrol so I can use it on the mobile page.

5. The Mobile Page

The view for the list is a simple amx page.

Create the page and drag the AllLocations collection from the datacontrol onto the page. In the popup menu pick “ADF Mobile List View”.

Actually that is all that needs to be done. Now after deploying, the app looks like this.

Now it is time to implement the “pull to refresh”.

6. Implementing the pull to refresh: Calling the service

In order to refresh the list, I need to know if there are actually new records available in the database.

This information is provided by the getCurrentCount webservice operation. First I create a new pageflowscoped backing bean to hold all logic involved in this functionality. In this bean I have one property. This is used to store the latest record count. This count is used to make sure that the findAllLocations webservice is only invoked if necessary.

To call the webservice that returns the current record count (getCurrentCount) I also use AdfmfJavaUtilities.invokeDataControlMethod().

The returned value (= the current number of rows in the database table) is compared to the previous amount returned by this service call. If there are more rows in the database table, I want to refresh the List. To do that, I simply call out to the “findAllLocations” service. After successful invocation, the count is updated to the new value.

I want to refresh the list with Locations whenever the list is pulled down.

For this I use the amx:actionlistener component. This component allows you to declaratively invoke an action. This component is meant to be a child component of any tag that has some kind of listener attribute like actionListener, or valueChangeListener, etc. The type attribute defines which listener of the parent this actionListener should be fired for. These methods fire before the listener on the parent component fires.

In the actionListener I invoke the checkForUpdates method that was described earlier.

The component has two attributes: type and binding. Type is set to swipeDown and in the binding attribute I use the checkForUpdates method that is implemented in the locationsbean.

After deploying the app it is time to test the behavior. After starting the app and the list shows some Locations.

Now add 1 or 2 Locations to the database and commit these changes.

Swipe the list down, release and see what happens…….

The new Locations are displayed.

9. Some Final Notes

This example (and actually the pattern) works for lists that show rather static data (no update or deletes). Every “pull down” gesture checks the server for new rows. That is, it checks if there are more rows then during the last call, and if so, the new rows are returned and added to the list. So whenever there are deleted or changed rows, this is not reflected in this sample. I could have implemented a service only returning the new Locations and add those to the list, but for this example I decided to simply fetch all Locations and rebuild the list. One other improvement is to only invoke the webservices if the “pull down” is invoked on the first row in the list. This post was initially posted on lucbors.blogspot.com

About Author

Luc Bors is Expertise Lead ADF and technical specialist/architect at AMIS, Nieuwegein (The Netherlands). He developed several Workshops and training on ADF and also is an ADF and JHeadstart instructor. Luc is a member of the ADF Methodology group and publishes articles on ADF in oracle technology related magazines, on the AMIS technology blog, (http://technology.amis.nl/blog).

Luc Bors

Luc Bors is Expertise Lead ADF and technical specialist/architect at AMIS, Nieuwegein (The Netherlands). He developed several Workshops and training on ADF and also is an ADF and JHeadstart instructor. Luc is a member of the ADF Methodology group and publishes articles on ADF in oracle technology related magazines, on the AMIS technology blog, (http://technology.amis.nl/blog).

meta

Subscribe to Blog via Email

Enter your email address to subscribe to this blog and receive notifications of new posts by email.

Join 206 other subscribers

Email Address

About

AMIS is internationally recognized for its deep technological insight in Oracle technology. This knowledge is reflected in the presentations we deliver at international conferences such as Oracle OpenWorld, Hotsos and many user conferences around the world. Our AMIS Technology Blog, the most referred Oracle technology knowledge base outside the oracle.com domain. However you arrived here, we appreciate your interest in AMIS. Link to our Google+ Profile AMIS