Filters sample (Android) (Eclipse)
The Filters Sample demonstrates how to filter data obtained from a Data Abstract Server, and how to selectively return only certain fields rather than all of them. The sample is a demonstration of using Dynamic Where and Dynamic Select which are a useful alternative to using DA SQL where you might not want to issue full SQL statements.
Getting Started
To get started with this sample you need to have Eclipse, the Eclipse ADT plugin and the Android SDK installed. Regarding the SDK you need a minimum of one of the Android API builds, the build tools and a system image if you wish to test the sample out in the simulator.
When you load the project in Eclipse you will need to copy the com.remobjects.dataabstract.jar
and com.remobjects.sdk.jar
from where you installed Data Abstract for Java (typically "c:\Program Files (x86)\RemObjects Software\Data Abstract for Java\bin") into the "libs" folder of the project and if needed go into the project properties and add them on the "Java Build Path" tab.
Finally by default the sample interacts with the RemObjects sample server at "http://remobjects.com:8099/bin".
Running the Sample
When the sample starts it has a ListView
which is initially empty apart from an instruction message. Then there is a menu bar with 3 buttons, the first "MODE" allows you to swap between "Local Filtering" and "Remote Filtering" modes. Next is a "Refresh" button that will retrieve the initial table data when pressed. Finally the sliders open the "Settings" screen where you can change the URL that the app connects to and provides some additional information.
The first step is to press the "Refresh" button, which will retrieve the data. As the sample defaults to "Local filtering" the full "Products" table is retrieved and Dynamic Where to retrieve only three rows from the "Groups" table. The ListView
is then updated with the data from the "Groups" table.
Pressing on one of the rows in the "Groups" ListView
will then display a table of filtered rows where the "ProductsGroup" field matches the selected group. You can change the filter "Mode" and press the "Refresh" button which will filter that table either locally or remotely and briefly display the number of records retrieved from the table in the server. With local filtering roughly 1200 records are retrieved and then filtered down to 4, with remote filtering only 4 records are returned.
Examining the Code
The Java based sample is comprised of 5 classes that handle the UI and those functions needed to interact with Relativity Server.
- DataModule handles initializing the basic connection to the server and creating the RemoteDataAdapter. It also registers itself to listen for changes to the preferences so that when the settings data is changed the RemoteDataAdapter is updated to reflect the new data.
- TableListAdapter is a class used by MainActivity to display the "Clients" data in the
ListView
. The class implements the TableChangedListener. - SettingsActivity handles interacting with the "Preferences" subsystem for storing and retrieving data that will be used for logging in like the server url, username and password.
- GroupsActivity handles retrieving the "Groups" table, and displaying that data in a
ListView
. - ProductsActivity handles retrieving & filtering of the "Products" table and display those results in a
ListView
.
Filtering data remotely with Dynamic Select & Dynamic Where
There are two examples of filtering the data remotely on the server in this sample. The first we'll describe uses both Dynamic Where and Dynamic Select to retrieve any rows from the "Products" table where the field "ProductsGroup" matches a particular value and only return certain fields from that row. The second is simpler and only uses Dynamic Where to retrieve 3 particular rows from the "Groups" table.
Starting with the first example, the first step to retrieving filtered data is to create a TableRequestInfoV5 object to which we can pass the WHERE
and SELECT
clauses. The number of records returned could be controlled by passing a value to the setMaxRecords of TableRequestInfoV5, without passing a value the class defaults to returning all matching records.
The next step is to create a Dynamic Where clause that will match any rows in the "Groups" table where the "ProductsGroup" field equals the value in fGroupId
. The [WhereExpression] is composed of a BinaryExpression, the first argument is the field to match against which is passed as a FieldExpression object whose constructor takes the field name as a string. The second argument is the value we want to match the field against, this is passed as a ConstantExpression object whose constructor takes the value to use as the first argument, and a data type as the second argument. The last argument passed to the BinaryExpression tells the expression how it is to treat the previous arguments, here BinaryOperator.Equal is passed to indicate that the two previous arguments are to be equal to each other.
If you wrote the BinaryExpression as an SQL statement it would be:
SELECT * FROM Groups WHERE (ProductsGroup=fGroupId)
To pass the WhereExpression to the setWhereClause method of TableRequestInfoV5, it needs to first be converted to XML using the toXmlNode method and wrapped in a XmlType object.
When retrieving rows normally all of the fields of that row are retrieved. If you want to limit the fields to only those you are interested in (perhaps to simply limit the amount of data transfered), then you can use the setDynamicSelectFieldNames method of TableRequestInfoV5. As an argument pass in a StringArray
object which takes an array of field names as strings.
To retrieve the data pass the table to fill, the TableRequestInfoV5 object and the callback to execute when the fill method is finished.
private void loadProductsWithRemoteFiltering(FillRequestTask.Callback callback) {
TableRequestInfoV5 request = new TableRequestInfoV5();
WhereExpression dw;
dw = new BinaryExpression(new FieldExpression("ProductGroup"),new ConstantExpression(fGroupId, DataType.Integer) , BinaryOperator.Equal);
request.setWhereClause(new XmlType(dw.toXmlNode()));
request.setDynamicSelectFieldNames(new StringArray(new String[] {
"ProductGroup",
"ProductCode",
"ProductName" }));
fDataModule.DataAdapter.fillAsync(fDataModule.productsTable, request, callback).execute();
}