droidQuery: The Android port of jQuery
-
Upload
phdbrown -
Category
Technology
-
view
4.497 -
download
0
description
Transcript of droidQuery: The Android port of jQuery
droidQuery The Android port of jQuery
Presented by Phil Brown
Overview1) What, Why and How?2) Understand the Syntax3) UI Traversal & Manipulation4) Asynchronous Rest Client (Ajax)5) Everything Else
1) What, Why, and How?
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 andmanipulation, 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+.
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.
Without 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 droidQuery:$.with(this, R.id.b1, R.id.b2, R.id.b3) .click(new Function() { public void invoke($ d, Object… args){ Log.i(“test”, “clicked”); } });
Example
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
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.
2) Understand the Syntax(And a comparison to jQuery)
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!”);}
};
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/
3) UI Traversal & Manipulation
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:
❏ .selectVisible()❏ .union()*❏ .intersect()*❏ .id()❏ .ids()
❏ .selectAll()❏ .selectByType()❏ .selectChildren()❏ .selectEmpties()❏ .selectFocused()❏ .selectHidden()❏ .selectImages()❏ .selectOnlyChilds()❏ .selectParents()
* - special case that accepts a second droidQuery instance as a parameter.
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);
Manipulate the SelectionOnce 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
UI Manipulation Example 1@Overridepublic 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;}
UI Manipulation Example 2String[] 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()); } });
Getter ShortcutsThe setter methods discussed previously become getters (for the first View in the selection) when the last parameter is removed.
$ d = $.with(this, android.R.id.text1);CharSequence text0 = d.text();CharSequence text1 = (CharSequence) d.attr(“text”);CharSequence text2 = (CharSequence) d.val();
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
Animations$.with(this, R.id.logo)
.animate(“{ width:48dp, height:48dp }”, 400, $.Easing.BOUNCE, new Function() {
public void invoke($ d, Object… args) {d.toast(“Animation Complete”, 1);
}});
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.
Animation LonghandAnimationOptions options = new AnimationOptions();options.duration(400) .easing($.Easing.ACCELERATE_DECELERATE) .debug(true) .reverse(true) .repeatCount(2) .progress(new Function() {
public void invoke($ d, Object… args) {Log.i(“animate”, args[0]+“=”+args[1]);
} }));$.with(this).selectImages()
.animate(“{ width:200%, height:200% }”, options);
Animation ShortcutsdroidQuery includes shortcuts for common animations including:
❏ .fadeIn()❏ .fadeOut()❏ .fadeTo()❏ .fadeToggle()❏ .slideLeft()❏ .slideUp()❏ .slideRight()❏ .slideDown()
4) Asynchronous Rest Client(Port of Ajax)
The $.ajax() MethodThis 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’}” +“}”);
AjaxOptions Example$.ajax(new AjaxOptions()
.url(“http://www.weath.er/getTemperature”)
.data(“{\“zipcode\”:\“55408\”}”)
.error(new Function() {public void invoke($ d, Object… args) {
AjaxError error = (AjaxError) args[0];Log.e(“Ajax”, error.toString());
}}).success(new Function() {
public void invoke($ d, Object… args) {JSONObject json = (JSONObject) args[0];Map<String, Object> data = $.map(json);Log.e(“Ajax”, “Temp: ”+ data.get(“Celsius”));
}}));
Ajax: Global Event HandlersGlobal 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()
Global Event Handlers Examplepublic 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);
}});
}
Other Ajax Methods❏ Helper Methods
❏ $.serialize()❏ $.serializeArray()
❏ Low-Level Methods❏ $.ajaxSetup()
❏ Shorthand Methods❏ $.get()❏ $.getJSON()❏ $.getScript()❏ $.post()❏ $.load()
AjaxOptions options = new AjaxOptions();Integer[] timeouts = new Integer[]{480,419,504,503,522,598,599};options.error(new Function() {
public void invoke($ d, Object… args) {AjaxError error = (AjaxError) args[0];Log.e(“Ajax Error”, error.toString());
}}.statusCode(timeouts, new function() {
public void invoke($ d, Object… args) {Log.e(“Ajax Error”,“Timeout(“+args[0]+
“)”);AjaxOptions o = (AjaxOptions) args[1];$.ajax(o.statusCode(timeouts, $.noop()));
}}));$.ajaxSetup(options);
droidQuery Ajax AdditionsAdditionally, 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
5) Everything Else(well, not everything...)
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.
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 functionalityd.click(clickListener);d.on(“click”, clickListener);d.bind(“click”, null, clickListener);
//this will only work the first time each view:d.one(“click”, clickListener);
Event Example (2 of 2)//handle EditText edit changesView editor = findViewById(R.id.myEditText);$.with(editor).change(new Function() {
public void invoke($ d, Object… args) {Log.i(“Change”, “EditText changed to: ” + d.text());}
});
FormsA 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();
Utilities
❏ Methods❏ .view(int)❏ .each(Function)❏ .parseJSON(String)❏ .parseXML(String)❏ .parseHTML(String)❏ $.map(JSONObject)❏ $.makeArray(JSONArray)❏ .data(), .data(Object)
Many additional classes and methods are bundled with droidQuery that can help simplify development:
❏ Classes❏ QuickMap/QuickEntry
❏ Map<String, ?> map = $.qm($.qe(“foo”, “bar”),
$.qe(“first”, 1));
❏ SwipeInterceptorView❏ EventCenter❏ Callbacks
droidQuery Extensions❏ Your project can be a droidQuery extension
1. Create a new library project2. Create a new Object that extends $Extension3. Override methods4. Include in app build path5. Access library code through droidQuery API
❏ Examples available on Github.
What’s next?❏ Finish CSS Integration❏ Update javaQuery (http://bit.ly/javaquery)❏ iQuery (Objective-c++)
❏ UITextView *view = [[UITextView] alloc] init];$ *d = new $(view);NSString *text;text = d->attr(@“text”, @“foobar”).attr(@“text”);NSLog(@“text=’%@’”, text);
❏ jQuery to (droid,java,i)Query generation? ❏ Hybrid jQuery/(droid,java,i)Query apps?
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/droidquery-
docs.
❏ 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