Top Banner
droidQuery The Android port of jQuery Presented by Phil Brown
40

droidQuery: The Android port of jQuery

May 10, 2015

Download

Technology

PhDBrown

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.
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: droidQuery: The Android port of jQuery

droidQuery The Android port of jQuery

Presented by Phil Brown

Page 2: droidQuery: The Android port of jQuery

Overview1) What, Why and How?2) Understand the Syntax3) UI Traversal & Manipulation4) Asynchronous Rest Client (Ajax)5) Everything Else

Page 3: droidQuery: The Android port of jQuery

1) What, Why, and How?

Page 4: droidQuery: The Android port of jQuery

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+.

Page 5: droidQuery: The Android port of jQuery

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.

Page 6: droidQuery: The Android port of jQuery

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

Page 7: droidQuery: The Android port of jQuery

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

Page 8: droidQuery: The Android port of jQuery

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.

Page 9: droidQuery: The Android port of jQuery

2) Understand the Syntax(And a comparison to jQuery)

Page 10: droidQuery: The Android port of 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!”);}

};

Page 11: droidQuery: The Android port of jQuery

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/

Page 12: droidQuery: The Android port of jQuery

3) UI Traversal & Manipulation

Page 13: droidQuery: The Android port of jQuery

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.

Page 14: droidQuery: The Android port of jQuery

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);

Page 15: droidQuery: The Android port of jQuery

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

Page 16: droidQuery: The Android port of jQuery

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;}

Page 17: droidQuery: The Android port of jQuery

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()); } });

Page 18: droidQuery: The Android port of jQuery

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();

Page 19: droidQuery: The Android port of jQuery

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

Page 20: droidQuery: The Android port of jQuery

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);

}});

Page 21: droidQuery: The Android port of jQuery

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.

Page 22: droidQuery: The Android port of jQuery

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);

Page 23: droidQuery: The Android port of jQuery

Animation ShortcutsdroidQuery includes shortcuts for common animations including:

❏ .fadeIn()❏ .fadeOut()❏ .fadeTo()❏ .fadeToggle()❏ .slideLeft()❏ .slideUp()❏ .slideRight()❏ .slideDown()

Page 24: droidQuery: The Android port of jQuery

4) Asynchronous Rest Client(Port of Ajax)

Page 25: droidQuery: The Android port of jQuery

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’}” +“}”);

Page 26: droidQuery: The Android port of jQuery

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”));

}}));

Page 27: droidQuery: The Android port of jQuery

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()

Page 28: droidQuery: The Android port of jQuery

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);

}});

}

Page 29: droidQuery: The Android port of jQuery

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);

Page 30: droidQuery: The Android port of jQuery

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

Page 31: droidQuery: The Android port of jQuery

5) Everything Else(well, not everything...)

Page 32: droidQuery: The Android port of jQuery

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.

Page 33: droidQuery: The Android port of jQuery

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);

Page 34: droidQuery: The Android port of jQuery

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());}

});

Page 35: droidQuery: The Android port of jQuery

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();

Page 36: droidQuery: The Android port of jQuery

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

Page 37: droidQuery: The Android port of jQuery

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.

Page 38: droidQuery: The Android port of jQuery

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?

Page 39: droidQuery: The Android port of jQuery

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