This presentation was given at DevFest Twin Cities in 2013, and introduces droidQuery - the Android port of jQuery, that allows UI manipulation and traversal of the Android layout, asynchronous REST client calls, event handling, animations, and much more.
4. WHAT IS droidQuery?
❏ A port of the popular javascript library jQuery.
❏ jQuery is:
“... a fast, small, and feature-rich JavaScript library [that]
makes things like HTML document traversal and
manipulation, event handling, animation, and Ajax* much
simpler with an easy-to-use API.”
-- www.jquery.com
❏ A java library that makes things like layout traversal and
manipulation, event handling, animation, and Ajax simple to
implement on Android 2.2+.
5. WHY DOES IT EXIST?
❏ Makes developing apps faster
❏ Chaining Method calls
❏ Fewer Lines of Code
❏ Simplifies common tasks
❏ Asynchronous RESTful API calls
❏ Animations
❏ Etc
❏ Familiar syntax for web developers to learn Android
development.
6. Example
Without droidQuery:
With droidQuery:
OnClickListener listener = new
OnClickListener() {
public void onClick(View v){
Log.i(“test”, “clicked”);
}
};
Button b1 =
(Button) findViewById(R.id.b1);
b1.setOnClickListener(listener);
Button b2 =
(Button) findViewById(R.id.b2);
b2.setOnClickListener(listener);
Button b3 =
(Button) findViewById(R.id.b3);
b3.setOnClickListener(listener);
$.with(this, R.id.b1, R.id.b2, R.id.b3)
.click(new Function() {
public void invoke($ d, Object… args){
Log.i(“test”, “clicked”);
}
});
7. HOW DOES IT WORK?
❏
❏
❏
❏
❏
Ported From the jQuery Documentation
Made to be as syntactically like jQuery as possible
❏ No generics
❏ $ for class name
Reflection/Proxying Techniques for advanced CSS, Animation, and
Event handling
Asynchronous Rest API based on Apache HTTPClient
Uses NineOldAndroids to support animations and attributes for low APIs
8. What are my alternatives?
❏
❏
No other library offers all of the features that droidQuery provides.
Many libraries support Asynchronous Network Tasks
❏ Android Volley
❏ Spring for Android
❏ AndroidAnnotations
❏ Picasso
❏ Image Specific
❏ Android Query
❏ Also provides APIs similar to jQuery, but syntax is very different.
❏
For animations supporting lower APIs, you can use NineOldAndroids.
10. In jQuery:
❏
The variable ‘$’ is used as an alias to the jQuery function, and as such is
commonly used to access variables and functions within jQuery.
❏
❏
$(“#myButton”).click(function(event) {
console.log(“element clicked!”);
});
droidQuery’s main class is $.java.
❏
$.with(myButton).click(new Function() {
public void invoke($ d, Object… args) {
Log.i(“droidQuery”, “view clicked!”);
}
};
11. droidQuery Syntax
❏
❏
❏
$.java
Function
Instantiation using $.with(...)
❏ Modeled after picasso*
❏ Accepts Context, View, View[], List<View>, Context and
vararg int ids, etc
❏
Assumes common callback syntax for event handling:
❏ Listeners should be an inner interface of the Object
❏ public interface OnFoobarListener {
public void|boolean onFoobar();
}
* - http://square.github.io/picasso/
13. Selectors
❏
❏
❏
Select one or multiple UI elements
Powerful shortcut for manipulating both individual views and groups of views
There are many selector methods provided by droidQuery, including:
❏
❏
❏
❏
❏
❏
❏
❏
❏
.selectAll()
.selectByType()
.selectChildren()
.selectEmpties()
.selectFocused()
.selectHidden()
.selectImages()
.selectOnlyChilds()
.selectParents()
❏
❏
❏
❏
❏
.selectVisible()
.union()*
.intersect()*
.id()
.ids()
* - special case that accepts a second
droidQuery instance as a parameter.
14. Selector Example
//Show hidden Views, Hide Shown Views
$ hidden = $.with(this).selectHidden();
$.with(this).selectShown().hide();
hidden.show();
//Edit views that contain a LinearLayout as only subview
$.with(this)
.selectByType(“android.widget.LinearLayout”)
.selectOnlyChilds()
.selectParents().attr(“backgroundColor”, Color.RED);
15. Manipulate the Selection
Once a selection has been made, these (and other) methods will manipulate each
View in the selection. Think of them as setters on all the Views in the selection.
❏
❏
❏
❏
❏
❏
❏
❏
❏
.attr(“name”, value)
.val(Object)
.text(int), .text(String)
.html(int), .html(String)
.mask(...)
.id(int)
.focus()
.focusOut()
.tag(Object)
❏
❏
❏
.image(Drawable), .image(Bitmap), .image(String)
.image(String, int, int, error)
❏ Set Image to Asset, File, or URL
.image(List<String>, int, int, error)
❏ Set different Strings for different views in the
selection
16. UI Manipulation Example 1
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null)
layout = LayoutInflater.from(mContext)
.inflate(R.layout.cell, parent, false);
Message data = getItem(position);
$.with(layout, R.id.title).text(data.getTitle())
.id(R.id.image).image(data.getImageUrl());
return convertView;
}
17. UI Manipulation Example 2
String[] urls = new String[] { “http://bit.ly/mmlogo.png”,
“http://bit.ly/mmicon.png”,
“http://bit.ly/mmthumb.png” };
int px = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
48, getResources().getDisplayMetrics());
$.with(this, R.id.logo, R.id.icon, R.id.thumb)
.image(Arrays.asList(urls), px, px, new Function() {
public void invoke($ d, Object… args) {
Log.e(“Images”, args[0].toString());
}
});
18. Getter Shortcuts
The setter methods discussed previously become getters (for the first View in
the selection) when the last parameter is removed.
$ d = $.with(this,
CharSequence text0
CharSequence text1
CharSequence text2
android.R.id.text1);
= d.text();
= (CharSequence) d.attr(“text”);
= (CharSequence) d.val();
19. CSS
❏
Current CSS-related Methods*
include:
❏ .height()
❏ .width()
❏ .innerHeight()
❏ .innerWidth()
❏ .outerHeight()
❏ .outerWidth()
❏ .offset()
❏ .position()
❏ .scrollLeft()
❏ .scrollTop()
❏
Future CSS-Related Methods
include:
❏ .css(String)
❏ .addClass(...)
❏ .hasClass(...)
❏ .removeClass(...)
* All of these methods can be used to get
or set the attribute
21. Animations, cont’d
❏
Uses a JSON string specifying animation properties, end values, and
units.
❏ Units can be any of: px, %, em, dp, dip, sp, in, mm, pt, or none
(defaults to px)
❏ Property names must be accessible using Getters or Setters (or via
ViewHelper, from NineOldAndroids).
❏
Additionally, an AnimationOptions Object is passed that provides
parameters and callbacks for the animation, including duration,
interpolator, etc - making these animation highly customizable and
responsive.
25. The $.ajax() Method
This method is used to start an asynchronous REST request. There are
multiple parameter types this accepts, however primarily developers will use
one of:
❏
❏
AjaxOptions
❏ $.ajax(new AjaxOptions().url(“http://example.com”));
String
❏ Does not support Functions, but may be useful where either global
event handlers are already set, or where no callbacks are needed.
❏ $.ajax(“{ url:’http://www.example.com’,” +
“ type:’PUT’,” +
“ data:{foo:1, bar:’example’}” +
“}”);
27. Ajax: Global Event Handlers
Global Ajax Event Handlers:
Register/Respond to Ajax Events for global requests.
These are specified using the .global() method of the AjaxOptions Object.
❏ $.ajaxComplete()
❏ $.ajaxBeforeSend()
❏ $.ajaxError()
❏ $.ajaxStart()
❏ $.ajaxStop()
❏ $.ajaxSuccess()
28. Global Event Handlers Example
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
$.ajaxStart(new Function() {
public void invoke($ d, Object… args) {
setProgressBarIndeterminateVisibility(true);
}
});
$.ajaxStop(new Function() {
public void invoke($ d, Object… args) {
setProgressBarIndeterminateVisibility(false);
}
});
}
30. droidQuery Ajax Additions
Additionally, droidQuery provides advanced caching and redundancy handling.
❏ Caching
❏ Saves statically - not persistent across JVM sessions
❏ Customizable
❏ ON/OFF
❏ Timeout Interval
❏ Per-Request caching technique (timeout, never timeout, only delete when
cache is cleared)
❏ Direct access to cache
❏
Redundancy Handling
❏ Ensures that only one identical request goes out at the same time
❏ Customize how to handle redundant requests
❏ Respond-To-All (default), Respond-To-First, Off
32. Events
❏
Refers to triggering and responding to
❏ User Input Events, such as clicks and swipes
❏ Changes to the layout
❏
Set or trigger an event using the following methods:
❏ .bind(), .on(), .one(), .change(), .click(), .longclick(), .swipe(), .
swipeLeft(), .swipeUp(), .swipeRight(), .swipeDown(), .focus(), .
focusout(), .keydown(), .keyup(), .keypress()
❏
Relies on standard Callback syntax to create proxies for the bind(),
on(), and one() methods.
❏
Using some of these methods will change a View’s existing
onTouchListener.
33. Event Example (1 of 2)
Function clickListener = new Function() {
public void invoke($ d, Object… args) {
d.toast(“a button was clicked!”, Toast.LENGTH_SHORT);
}
};
$ d = $.with(this).selectByType(Button.class);
//any of the below result in the same functionality
d.click(clickListener);
d.on(“click”, clickListener);
d.bind(“click”, null, clickListener);
//this will only work the first time each view:
d.one(“click”, clickListener);
34. Event Example (2 of 2)
//handle EditText edit changes
View editor = findViewById(R.id.myEditText);
$.with(editor).change(new Function() {
public void invoke($ d, Object… args) {
Log.i(“Change”, “EditText changed to: ” + d.text());
}
});
35. Forms
A Form layout allows quick creation of UI forms, plus simple validation.
<self.philbrown.view.Form
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:droidQuery="http://schemas.android.com/apk/res-auto"
android:id=”@+id/form”
android:layout_width=”match_parent”
android:layout_height=”match_parent” >
<EditText
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
droidQuery:layout_form_required=”true”/>
</self.philbrown.view.Form>
//Then in code:
boolean isValid = ((Form) findViewById(R.id.form)).validate();
36. Utilities
Many additional classes and methods are bundled with droidQuery that can
help simplify development:
❏
Methods
❏ .view(int)
❏ .each(Function)
❏ .parseJSON(String)
❏ .parseXML(String)
❏ .parseHTML(String)
❏ $.map(JSONObject)
❏ $.makeArray(JSONArray)
❏ .data(), .data(Object)
❏
Classes
❏ QuickMap/QuickEntry
❏
❏
❏
❏
Map<String, ?> map =
$.qm($.qe(“foo”, “bar”),
$.qe(“first”, 1));
SwipeInterceptorView
EventCenter
Callbacks
37. droidQuery Extensions
❏
Your project can be a droidQuery extension
1. Create a new library project
2. Create a new Object that extends $Extension
3. Override methods
4. Include in app build path
5. Access library code through droidQuery API
❏
Examples available on Github.
39. Thank You
❏
droidQuery is still a work in progress. If you would like to contribute
❏ please start by watching the github repo (http://bit.ly/droidquery).
❏ Use the @Modified annotation packaged with the project, to mark
your changes to the code.
❏
Javadocs from most recent release are available at http://bit.ly/droidquerydocs.
❏
Open Source Libraries that are used by droidQuery include:
❏ NineOldAndroids - http://nineoldandroids.com/
❏ cwac-task - https://github.com/commonsguy/cwac-task
❏ jCSS-Parser - https://github.com/phil-brown/jCSS-Parser