Monday, October 31, 2016
#webdevelop #webdesigns Blog: Write a novel in a month: A tome wasn’t built in a day, but 4 weeks is doable, say t… https://t.co/Qz5RYMcOCw
#webdevelop #webdesigns Blog: Write a novel in a month: A tome wasn’t built in a day, but 4 weeks is doable, say t… https://t.co/Qz5RYMcOCw
— Web Dev Pro (@Web_improve) October 31, 2016
from Twitter https://twitter.com/Web_improve
#webdevelop #webdesigns Blog: Apple releases big update to Final Cut Pro: Update includes new Magnetic Timeline, r… https://t.co/nUnCA2kY85
#webdevelop #webdesigns Blog: Apple releases big update to Final Cut Pro: Update includes new Magnetic Timeline, r… https://t.co/nUnCA2kY85
— Web Dev Pro (@Web_improve) October 31, 2016
from Twitter https://twitter.com/Web_improve
#webdevelop #webdesigns Blog: Apple releases big update to Final Cut Pro: Update includes new Magnetic Timeline, r… https://t.co/FOTiXcUJSj
#webdevelop #webdesigns Blog: Apple releases big update to Final Cut Pro: Update includes new Magnetic Timeline, r… https://t.co/FOTiXcUJSj
— Web Dev Pro (@Web_improve) October 31, 2016
from Twitter https://twitter.com/Web_improve
#webdevelop #webdesigns Apple releases big update to Final Cut Pro: Apple has introduced a significant update to i… https://t.co/0cxKZvE6xd
#webdevelop #webdesigns Apple releases big update to Final Cut Pro: Apple has introduced a significant update to i… https://t.co/0cxKZvE6xd
— Web Dev Pro (@Web_improve) October 31, 2016
from Twitter https://twitter.com/Web_improve
Sunday, October 30, 2016
Saturday, October 29, 2016
#code #HTML5 #webdesigns #css #ruby Download of the Day: Log Vectors Free for the Taking! https://t.co/0S6BEd3CzM
#code #HTML5 #webdesigns #css #ruby Download of the Day: Log Vectors Free for the Taking! https://t.co/0S6BEd3CzM
— Web Dev Pro (@Web_improve) October 29, 2016
from Twitter https://twitter.com/Web_improve
5 Authentic Vintage Handmade Fonts from TSV Creative - only $12! https://t.co/AvP3d0yFBs #developerdeals
5 Authentic Vintage Handmade Fonts from TSV Creative - only $12! https://t.co/AvP3d0yFBs #developerdeals
— Web Dev Pro (@Web_improve) October 29, 2016
from Twitter https://twitter.com/Web_improve
Friday, October 28, 2016
Exclusive Freebie: 60 Outline Brushes for Illustrator https://t.co/MZXT8rtgHM #developerdeals
Exclusive Freebie: 60 Outline Brushes for Illustrator https://t.co/MZXT8rtgHM #developerdeals
— Web Dev Pro (@Web_improve) October 28, 2016
from Twitter https://twitter.com/Web_improve
#webdevelop #webdesigns Blog: Apple unveils groundbreaking new MacBook Pro: Revolutionary Touch Bar, breakthrough … https://t.co/qo8jSBnbEI
#webdevelop #webdesigns Blog: Apple unveils groundbreaking new MacBook Pro: Revolutionary Touch Bar, breakthrough … https://t.co/qo8jSBnbEI
— Web Dev Pro (@Web_improve) October 28, 2016
from Twitter https://twitter.com/Web_improve
#webdevelop #webdesigns Apple unveils groundbreaking new MacBook Pro: Apple yesterday introduced the thinnest and … https://t.co/OYM5W7RU6n
#webdevelop #webdesigns Apple unveils groundbreaking new MacBook Pro: Apple yesterday introduced the thinnest and … https://t.co/OYM5W7RU6n
— Web Dev Pro (@Web_improve) October 28, 2016
from Twitter https://twitter.com/Web_improve
Build your own custom Photoshop and Illustrator panels - only $9! https://t.co/fsduPFsZ39 #developerdeals
Build your own custom Photoshop and Illustrator panels - only $9! https://t.co/fsduPFsZ39 #developerdeals
— Web Dev Pro (@Web_improve) October 28, 2016
from Twitter https://twitter.com/Web_improve
Thursday, October 27, 2016
Wednesday, October 26, 2016
Enjoy Making Sites for Clients Again with Pulse CMS - only $19! https://t.co/hAFPnGnIZB #developerdeals
Enjoy Making Sites for Clients Again with Pulse CMS - only $19! https://t.co/hAFPnGnIZB #developerdeals
— Web Dev Pro (@Web_improve) October 26, 2016
from Twitter https://twitter.com/Web_improve
Tuesday, October 25, 2016
Getting Started with NodeJS for Beginners #NodejsTutorial https://t.co/IdiumTO57S https://t.co/l4xZWpdLgv
Getting Started with NodeJS for Beginners #NodejsTutorialhttps://t.co/IdiumTO57S http://pic.twitter.com/l4xZWpdLgv
— Web Dev Pro (@Web_improve) October 26, 2016
from Twitter https://twitter.com/Web_improve
https://t.co/jgP5RUfSgi Core Deeper Dive Training #JavaScriptWorld #aspnet https://t.co/goSobuhlZm https://t.co/eZ6dKvGQUd
https://t.co/jgP5RUfSgi Core Deeper Dive Training #JavaScriptWorld #aspnethttps://t.co/goSobuhlZm http://pic.twitter.com/eZ6dKvGQUd
— Web Dev Pro (@Web_improve) October 25, 2016
from Twitter https://twitter.com/Web_improve
https://t.co/jgP5RUfSgi Core 1.0 Tutorial #JavaScriptWorld #aspnet https://t.co/S1x74n0uiL https://t.co/9ZqWoyGs0L
https://t.co/jgP5RUfSgi Core 1.0 Tutorial #JavaScriptWorld #aspnethttps://t.co/S1x74n0uiL http://pic.twitter.com/9ZqWoyGs0L
— Web Dev Pro (@Web_improve) October 25, 2016
from Twitter https://twitter.com/Web_improve
https://t.co/jgP5RUfSgi Core Deeper Dive Training #NodejsTutorial https://t.co/fzOIrfdZfC https://t.co/4C99QtRQQd
https://t.co/jgP5RUfSgi Core Deeper Dive Training #NodejsTutorialhttps://t.co/fzOIrfdZfC http://pic.twitter.com/4C99QtRQQd
— Web Dev Pro (@Web_improve) October 25, 2016
from Twitter https://twitter.com/Web_improve
https://t.co/jgP5RUfSgi Core, Angular, React, Knockout for Programmers #JavaScriptWorld https://t.co/3t0Fp24gyk https://t.co/Tu7U8kFeW8
https://t.co/jgP5RUfSgi Core, Angular, React, Knockout for Programmers #JavaScriptWorldhttps://t.co/3t0Fp24gyk http://pic.twitter.com/Tu7U8kFeW8
— Web Dev Pro (@Web_improve) October 25, 2016
from Twitter https://twitter.com/Web_improve
https://t.co/jgP5RUfSgi Core 1.0 Tutorial #NodejsTutorial https://t.co/Qkty5mnum6 https://t.co/FaKlVcGoKw
https://t.co/jgP5RUfSgi Core 1.0 Tutorial #NodejsTutorialhttps://t.co/Qkty5mnum6 http://pic.twitter.com/FaKlVcGoKw
— Web Dev Pro (@Web_improve) October 25, 2016
from Twitter https://twitter.com/Web_improve
https://t.co/jgP5RUfSgi Core, Angular, React, Knockout for Programmers #NodejsTutorial https://t.co/JXnNlp449U https://t.co/xcJlqJy7WY
https://t.co/jgP5RUfSgi Core, Angular, React, Knockout for Programmers #NodejsTutorialhttps://t.co/JXnNlp449U http://pic.twitter.com/xcJlqJy7WY
— Web Dev Pro (@Web_improve) October 25, 2016
from Twitter https://twitter.com/Web_improve
Bundle: 800 High-Quality Seamless Photoshop Patterns - only $14! https://t.co/6RDns7XefU #developerdeals
Bundle: 800 High-Quality Seamless Photoshop Patterns - only $14! https://t.co/6RDns7XefU #developerdeals
— Web Dev Pro (@Web_improve) October 25, 2016
from Twitter https://twitter.com/Web_improve
Monday, October 24, 2016
#webdevelop #webdesigns Sponsored Post: Digital, self-inflating, or airless tyres: If you still believe that tyres… https://t.co/Lx4NVDSSt2
#webdevelop #webdesigns Sponsored Post: Digital, self-inflating, or airless tyres: If you still believe that tyres… https://t.co/Lx4NVDSSt2
— Web Dev Pro (@Web_improve) October 24, 2016
from Twitter https://twitter.com/Web_improve
#webdevelop #webdesigns Blog: Sponsored Post: Digital, self-inflating, or airless tyres: What’s new in tyre indust… https://t.co/zp3Mk7xaEe
#webdevelop #webdesigns Blog: Sponsored Post: Digital, self-inflating, or airless tyres: What’s new in tyre indust… https://t.co/zp3Mk7xaEe
— Web Dev Pro (@Web_improve) October 24, 2016
from Twitter https://twitter.com/Web_improve
Creative Bundle: 110+ UI Screen Templates with 1000 UI Components - only $21! https://t.co/4YV2toqUv3 #developerdeals
Creative Bundle: 110+ UI Screen Templates with 1000 UI Components - only $21! https://t.co/4YV2toqUv3 #developerdeals
— Web Dev Pro (@Web_improve) October 24, 2016
from Twitter https://twitter.com/Web_improve
Sunday, October 23, 2016
30 Days of Python | Unlock your Python Potential [100% Off] https://t.co/Kal7o0g3qR #programming
30 Days of Python | Unlock your Python Potential [100% Off] https://t.co/Kal7o0g3qR #programming
— Web Dev Pro (@Web_improve) October 23, 2016
from Twitter https://twitter.com/Web_improve
Become a Successful Programmer Without a Degree [FREE] https://t.co/Fxs4H06YTE #programming
Become a Successful Programmer Without a Degree [FREE] https://t.co/Fxs4H06YTE #programming
— Web Dev Pro (@Web_improve) October 23, 2016
from Twitter https://twitter.com/Web_improve
The Portable Guitarist—Transporting and Mounting an iOS Rig
So far in this series, I’ve shown you the advantages of using an iOS-based live rig, as well the tech most suited to the job.
In this tutorial, I’ll show you how to safely transporting the gear, and how to ensure you have it to hand in a live environment when you need it.
Safety First
I'll be honest: the iPad’s amazing, but it’s still more fragile—and sometimes more expensive—than a typical piece of a guitarist’s gigging equipment. A guitar or amp might survive being knocked over, but an iPad’s less likely to.
Furthermore it’s easier to steal, and often more in demand, than a guitar. So choose a gig wisely. There'll be a difference between performing on a raised stage or playing in a rough pub where the audience keep clattering into you.
Here are some things to think about.
Surviving the Journey
You’ve got to get the iPad, interface, and cables to and from the gig. Chucking it all into your guitar’s gig bag’s an option, and attractive if you need to travel light, but think about the level of protection offered.
As the screen’s the most vulnerable part, consider the Smart Cover from Apple; it clips magnetically to the device, and prices typically start from around £40.
I’m a great believer in rarely relying on a single solution. My iPad’s fitted with a Belkin Snap Case. It’s a thick covering for the back, costing less than £10. It then goes into a Belkin Pleated Sleeve, a padded, double-zipped pouch for under £15. Both items have easily survived several years of daily usage.
In terms of transporting to and from gigs, I use a shoulder bag; this carries the iPad, interface, plus a wealth of cabling. I’ve opted for this as it’s hands free (like I haven’t got enough to carry at a gig), and occupies little space in the car (an important consideration).
It’s also easier to keep it with me, alleviating concerns regarding theft. Alternatively, an aluminium flight case could be bought from a retailer, such as Maplin, for as little as £25. These usually contain foam, which could be sculpted to your devices accordingly.
Mounting Options for a Device
Unless you’ve a friendly/cheap guitar tech to hand, chances are you’re going to have to operate the iPad during the gig. This means having it within reach. There are several options available to you.
Desktop
If the gig’s small, you could place the iPad in a stand atop a speaker cabinet or table. For this, there’s the iKlip Studio from IK Multimedia, available for under £30. It takes your device either in portrait or landscape, has a place for attaching one of their iRig interfaces, and folds away almost flat—save for the lip on which the device sits.
Whilst they’re very useful—I own one—I’d only recommend it for home use, or small gigs where there’s no possibility of the audience getting anywhere near it. The potential for damage is too great. Fine for an intimate, seated singer-songwriter type of gig, but little else.
Stands
There’s the age-old route of the small folding music stand. They’re designed to be extremely portable, and are REALLY cheap—often less than £10. There’s nothing, however, to stop any sideways movement of the device.
Furthermore, their portability means that they’re flimsy—you only need the main wing nut to fail, and the iPad will be sailing backwards very quickly.
If the music stand appeals, but robustness concerns you, the opposite end of the spectrum is the lectern-style stand. These usually comprise folding feet and telescopic tubes more typically associated with speaker cabinet stands.
A large lipped top provides plenty of support and surface area, giving you somewhere to safely put both your device and interface. Many are also perforated, so you shouldn’t worry about the device overheating. Price-wise, you can spend little or lots, but £20 will get you the type of orchestral music stands you see in schools.
Whilst sturdier, their big disadvantage is portability, or lack thereof. The feet and the tubing are collapsable, but the actual top isn’t, so what you gain in surface area costs you in terms of having to cart it around.
Cradles
As I already use a microphone stand, I prefer a cradle that attaches to it. This means that there’s little extra to bring, it’s very portable, occupies no additional floor space, plus associated cabling can run down the mic stand.
There are many from which to choose, and they don’t have to be expensive; indeed, some are under £15. However, you get what you pay for, and I’d rather not trust the well-being of an expensive device by going for the cheapest one available.
My choice is the iPad stand from König & Meyer (also known as K&M). The cradle’s far thicker than many of its competitors, plus the fixings are reassuringly industrial. Choose from one that screws directly onto the thread of a mic stand—although you can’t now attach a mic—or one that mounts on an arm that clamps lower down the stand.
The cradle itself can orient either landscape or portrait, and can also be angled back, so exact positioning is achievable. I prefer waist height. The interface can fix to the arm. I use Velcro. Best of all, such choice and sturdiness only costs £20 to £30.
Conclusion
Using iOS live is a different proposition to home usage, so think about the following:
- Choose your gig appropriately
- How the device will be transported
- How the device will be protected
- Balance portability with robustness
- Consider the footprint a stand will occupy
- A desktop stand’s only appropriate for quiet, intimate gigs
- A folding stand’s cheap and portable, but flimsy
- Lectern stands are robust, but bulky
- A cradle and clamp is a compact, safe, portable solution
In the next tutorial, I’ll cover output connections and cabling, plus best choices of amplification.
HTML Simplified, Learning Web Development [$10 Only] https://t.co/DMoWrSKte8 #programming
HTML Simplified, Learning Web Development [$10 Only] https://t.co/DMoWrSKte8 #programming
— Web Dev Pro (@Web_improve) October 23, 2016
from Twitter https://twitter.com/Web_improve
Django + AngularJS for a Powerful Web Application [100% Off] https://t.co/zhnA2xf7iJ #webdevelopment
Django + AngularJS for a Powerful Web Application [100% Off] https://t.co/zhnA2xf7iJ #webdevelopment
— Web Dev Pro (@Web_improve) October 23, 2016
from Twitter https://twitter.com/Web_improve
Learn Matlab Programming by Examples (Codes Included) [$10 Only] https://t.co/osRMPX9HV1 #programming
Learn Matlab Programming by Examples (Codes Included) [$10 Only] https://t.co/osRMPX9HV1 #programming
— Web Dev Pro (@Web_improve) October 23, 2016
from Twitter https://twitter.com/Web_improve
Saturday, October 22, 2016
14 Unique Fonts in TT Cottons from TYPETYPE - only $9! https://t.co/TJTgeYvTrD #developerdeals
14 Unique Fonts in TT Cottons from TYPETYPE - only $9! https://t.co/TJTgeYvTrD #developerdeals
— Web Dev Pro (@Web_improve) October 22, 2016
from Twitter https://twitter.com/Web_improve
Friday, October 21, 2016
#webdevelop #webdesigns Blog: Get Predator vision with CAT’s new thermal imaging rugged phone: Spot water leaks an… https://t.co/5FwwgQKrsf
#webdevelop #webdesigns Blog: Get Predator vision with CAT’s new thermal imaging rugged phone: Spot water leaks an… https://t.co/5FwwgQKrsf
— Web Dev Pro (@Web_improve) October 21, 2016
from Twitter https://twitter.com/Web_improve
#webdevelop #webdesigns Blog: 5 Web conferences you need to attend in November 2016: Get yourself a seat at the bi… https://t.co/TreCJVclSm
#webdevelop #webdesigns Blog: 5 Web conferences you need to attend in November 2016: Get yourself a seat at the bi… https://t.co/TreCJVclSm
— Web Dev Pro (@Web_improve) October 21, 2016
from Twitter https://twitter.com/Web_improve
#webdevelop #webdesigns 5 Web conferences you need to attend in November 2016: ffconf Get yourself a seat at the b… https://t.co/DO699THrxs
#webdevelop #webdesigns 5 Web conferences you need to attend in November 2016: ffconf
— Web Dev Pro (@Web_improve) October 21, 2016
Get yourself a seat at the b… https://t.co/DO699THrxs
from Twitter https://twitter.com/Web_improve
The Fantastic Snow Text Generator - only $7! https://t.co/iWrUNJARyo #developerdeals
The Fantastic Snow Text Generator - only $7! https://t.co/iWrUNJARyo #developerdeals
— Web Dev Pro (@Web_improve) October 21, 2016
from Twitter https://twitter.com/Web_improve
Thursday, October 20, 2016
#code #HTML5 #webdesigns #css #ruby How to Create Your Own Handwritten Font (in 30 minutes or less) https://t.co/Nq5wkwNRPi
#code #HTML5 #webdesigns #css #ruby How to Create Your Own Handwritten Font (in 30 minutes or less) https://t.co/Nq5wkwNRPi
— Web Dev Pro (@Web_improve) October 20, 2016
from Twitter https://twitter.com/Web_improve
#webdevelop #webdesigns Blog: 5 tools to create video users want to watch: Make your video better and engage your … https://t.co/gf5TBqH9LY
#webdevelop #webdesigns Blog: 5 tools to create video users want to watch: Make your video better and engage your … https://t.co/gf5TBqH9LY
— Web Dev Pro (@Web_improve) October 20, 2016
from Twitter https://twitter.com/Web_improve
#webdevelop #webdesigns 5 tools to create video users want to watch: YouTube Creator Academy Fast-loading videos a… https://t.co/QEbvsbtCjD
#webdevelop #webdesigns 5 tools to create video users want to watch: YouTube Creator Academy
— Web Dev Pro (@Web_improve) October 20, 2016
Fast-loading videos a… https://t.co/QEbvsbtCjD
from Twitter https://twitter.com/Web_improve
Wednesday, October 19, 2016
Building RESTful APIs With Flask: ORM Independent
In the first part of this three-part tutorial series, we saw how to write RESTful APIs all by ourselves using Flask as the web framework. In the second part, we created a RESTful API using Flask-Restless which depends on SQLAlchemy as the ORM. In this part, we will use another Flask extension, Flask-Restful, which abstracts your ORM and does not make any assumptions about it.
I will take the same sample application as in the last part of this series to maintain context and continuity. Although this example application is based on SQLAlchemy itself, this extension can be used along with any ORM in a similar fashion, as shown in this tutorial.
Installing Dependencies
While continuing with the application from the first part, we need to install only one dependency:
$ pip install Flask-Restful
The Application
Before we start, you might want to remove the code that we wrote for the second part of this tutorial series for more clarity.
As always, we will start with changes to our application's configuration, which will look something like the following lines of code:
flask_app/my_app/__init__.py
from flask.ext.restful import Api api = Api(app)
Just adding the above couple of lines to the existing code should suffice.
flask_app/my_app/catalog/views.py
import json from flask import Blueprint, abort from flask.ext.restful import Resource from flask.ext.restful import reqparse from my_app.catalog.models import Product from my_app import api, db catalog = Blueprint('catalog', __name__) parser = reqparse.RequestParser() parser.add_argument('name', type=str) parser.add_argument('price', type=float) @catalog.route('/') @catalog.route('/home') def home(): return "Welcome to the Catalog Home." class ProductApi(Resource): def get(self, id=None, page=1): if not id: products = Product.query.paginate(page, 10).items else: products = [Product.query.get(id)] if not products: abort(404) res = {} for product in products: res[product.id] = { 'name': product.name, 'price': product.price, } return json.dumps(res) def post(self): args = parser.parse_args() name = args['name'] price = args['price'] product = Product(name, price) db.session.add(product) db.session.commit() res = {} res[product.id] = { 'name': product.name, 'price': product.price, } return json.dumps(res) api.add_resource( ProductApi, '/api/product', '/api/product/<int:id>', '/api/product/<int:id>/<int:page>' )
Most of the code above is self-explanatory. I will highlight a few points, though. The code above seems very similar to the one that we wrote in the first part of this series, but here the extension used does a bunch of behind-the-scenes optimizations and provides a lot more features that can be leveraged.
Here the methods declared under any class that subclasses Resource
are automatically considered for routing. Also, any parameters that we expect to receive along with incoming HTTP calls need to be parsed using reqparse
.
Testing the Application
This application can be tested in exactly the same way as we did in the second part of this tutorial series. I have kept the routing URL the same for the same purpose.
Conclusion
In this last part of this three-part tutorial series on developing RESTful APIs with Flask, we saw how to write ORM-independent RESTful APIs. This wraps up the basics of writing RESTful APIs with Flask in various ways.
There is more that can be learned about each of the methods covered, and you can explore this on your own, using the basics you've learned in this series.
Woodford Bourne PRO Family of 18 Vintage Grotesque-Style Fonts - only $15! https://t.co/q7aIf6ibsZ #developerdeals
Woodford Bourne PRO Family of 18 Vintage Grotesque-Style Fonts - only $15! https://t.co/q7aIf6ibsZ #developerdeals
— Web Dev Pro (@Web_improve) October 19, 2016
from Twitter https://twitter.com/Web_improve
Tuesday, October 18, 2016
Explore Emberjs with Greensock #NodejsTutorial #emberjs https://t.co/tPlXCYiDgv https://t.co/AXWxlJagNR
Explore Emberjs with Greensock #NodejsTutorial #emberjshttps://t.co/tPlXCYiDgv http://pic.twitter.com/AXWxlJagNR
— Web Dev Pro (@Web_improve) October 19, 2016
from Twitter https://twitter.com/Web_improve
AngularJS, NodeJS and TypeScript Tutorial #NodejsTutorial #Nodejs #Angularjs https://t.co/uUw8H78bVh https://t.co/VjAItN1Ngo
AngularJS, NodeJS and TypeScript Tutorial #NodejsTutorial #Nodejs #Angularjshttps://t.co/uUw8H78bVh http://pic.twitter.com/VjAItN1Ngo
— Web Dev Pro (@Web_improve) October 18, 2016
from Twitter https://twitter.com/Web_improve
Zero to Hero with Microservices #JavaScriptWorld https://t.co/3uPzFFoWZf https://t.co/KkkbL34AWn
Zero to Hero with Microservices #JavaScriptWorldhttps://t.co/3uPzFFoWZf http://pic.twitter.com/KkkbL34AWn
— Web Dev Pro (@Web_improve) October 18, 2016
from Twitter https://twitter.com/Web_improve
TypeScript and Angular 2: True Let's Play! #NodejsTutorial https://t.co/ElN6AoBRuo https://t.co/4qTxnvudEf
TypeScript and Angular 2: True Let's Play! #NodejsTutorialhttps://t.co/ElN6AoBRuo http://pic.twitter.com/4qTxnvudEf
— Web Dev Pro (@Web_improve) October 18, 2016
from Twitter https://twitter.com/Web_improve
Native Mobile Apps in Javascript #JavaScriptWorld #JavaScript https://t.co/eivHawVl1f https://t.co/4LvVZ666na
Native Mobile Apps in Javascript #JavaScriptWorld #JavaScripthttps://t.co/eivHawVl1f http://pic.twitter.com/4LvVZ666na
— Web Dev Pro (@Web_improve) October 18, 2016
from Twitter https://twitter.com/Web_improve
Maximize The Performance of HTML5 Video in RPI2 #JavaScriptWorld #html5 https://t.co/q1f8Zk5bjL https://t.co/rzJ3O8zWUX
Maximize The Performance of HTML5 Video in RPI2 #JavaScriptWorld #html5https://t.co/q1f8Zk5bjL http://pic.twitter.com/rzJ3O8zWUX
— Web Dev Pro (@Web_improve) October 18, 2016
from Twitter https://twitter.com/Web_improve
Let's Go: Testing Golang Programs
In this tutorial I will teach you all the basics of idiomatic testing in Go using the best practices developed by the language designers and the community. The main weapon will be the standard testing package. The target will be a sample program that solves a simple problem from Project Euler.
Square Sum Difference
The sum square difference problem is pretty simple: "Find the difference between the sum of the squares of the first one hundred natural numbers and the square of the sum."
This particular problem can be solved rather concisely especially if you know your Gauss. For example, the sum of the first N natural numbers is (1 + N) * N / 2
, and the sum of squares of the first N integers is: (1 + N) * (N * 2 + 1) * N / 6
. So the whole problem can be solved by the following formula and assigning 100 to N:
(1 + N) * (N * 2 + 1) * N / 6 - ((1 + N) * N / 2) * ((1 + N) * N / 2)
Well, that's very specific, and there isn't much to test. Instead, I created some functions that are a little more general than what's needed for this problem, but can serve for other programs in the future (project Euler has 559 problems right now).
The code is available on GitHub.
Here are the signatures of the four functions:
// The MakeIntList() function returns an array of consecutive integers // starting from 1 all the way to the `number` (including the number) func MakeIntList(number int) []int // The squareList() function takes a slice of integers and returns an // array of the quares of these integers func SquareList(numbers []int) []int // The sumList() function takes a slice of integers and returns their sum func SumList(numbers []int) int // Solve Project Euler #6 - Sum square difference func Process(number int) int
Now, with our target program in place (please forgive me, TDD zealots), let's see how to write tests for this program.
The Testing Package
The testing package goes hand in hand with the go test
command. Your package tests should go in files with the "_test.go" suffix. You can split your tests across several files that follow this convention. For example: "whatever1_test.go" and "whatever2_test.go". You should put your test functions in these test files.
Every test function is a publicly exported function whose name starts with "Test", accepts a pointer to a testing.T
object, and returns nothing. It looks like:
func TestWhatever(t *testing.T) { // Your test code goes here }
The T object provides various methods you can use to indicate failure or record errors.
Remember: only test functions defined in test files will be executed by the go test
command.
Writing Tests
Every test follows the same flow: set up the test environment (optional), feed the code under test input, capture the result, and compare it to the expected output. Note that inputs and results don't have to be arguments to a function.
If the code under test is fetching data from a database then the input will be making sure the database contains appropriate test data (which may involve mocking at various levels). But, for our application, the common scenario of passing input arguments to a function and comparing the result to the function output is sufficient.
Let's start with the SumList()
function. This function takes a slice of integers and returns their sum. Here is a test function that verifies SumList()
behaves as it should.
It tests two test cases, and if an expected output doesn't match the result, it calls the Error()
method of the testing.T object.
func TestSumList_NotIdiomatic(t *testing.T) { // Test []{} -> 0 result := SumList([]int{}) if result != 0 { t.Error( "For input: ", []int{}, "expected:", 0, "got:", result) } // Test []{4, 8, 9} -> 21 result = SumList([]int{4, 8, 9}) if result != 21 { t.Error( "For input: ", []int{}, "expected:", 0, "got:", result) } }
This is all straightforward, but it looks a little verbose. Idiomatic Go testing uses table-driven tests where you define a struct for pairs of inputs and expected outputs and then have a list of these pairs that you feed in a loop to the same logic. Here is how it is done for testing the SumList()
function.
type List2IntTestPair struct { input []int output int } func TestSumList(t *testing.T) { var tests = []List2IntTestPair{ {[]int{}, 0}, {[]int{1}, 1}, {[]int{1, 2}, 3}, {[]int{12, 13, 25, 7}, 57}, } for _, pair := range tests { result := SumList(pair.input) if result != pair.output { t.Error( "For input: ", pair.input, "expected:", pair.output, "got:", result) } } }
This is much better. It is easy to add more test cases. It's easy to have the full spectrum of test cases in one place, and if you decide to change the test logic you don't need to change multiple instances.
Here is another example for testing the SquareList()
function. In this case, both the input and the output are slices of integers, so the test pair struct is different, but the flow is identical. One interesting thing here is that Go doesn't provide a built-in way to compare slices, so I use reflect.DeepEqual()
to compare the output slice to the expected slice.
type List2ListTestPair struct { input []int output []int } func TestSquareList(t *testing.T) { var tests = []List2ListTestPair{ {[]int{}, []int{}}, {[]int{1}, []int{1}}, {[]int{2}, []int{4}}, {[]int{3, 5, 7}, []int{9, 25, 49}}, } for _, pair := range tests { result := SquareList(pair.input) if !reflect.DeepEqual(result, pair.output) { t.Error( "For input: ", pair.input, "expected:", pair.output, "got:", result) } } }
Running Tests
Running tests is as simple as typing go test
in your package directory. Go will find all the files with the "_test.go" suffix and all the functions with the "Test" prefix and run them as tests. Here is what it looks like when everything is OK:
(G)/project-euler/6/go > go test PASS ok _/Users/gigi/Documents/dev/github/project-euler/6/go 0.006s
Not very dramatic. Let me break a test on purpose. I'll change the test case for SumList()
such that the expected output for summing 1 and 2 will be 7.
func TestSumList(t *testing.T) { var tests = []List2IntTestPair{ {[]int{}, 0}, {[]int{1}, 1}, {[]int{1, 2}, 7}, {[]int{12, 13, 25, 7}, 57}, } for _, pair := range tests { result := SumList(pair.input) if result != pair.output { t.Error( "For input: ", pair.input, "expected:", pair.output, "got:", result) } } }
Now, when you type go test
, you get:
(G)/project-euler/6/go > go test --- FAIL: TestSumList (0.00s) 006_sum_square_difference_test.go:80: For input: [1 2] expected: 7 got: 3 FAIL exit status 1 FAIL _/Users/gigi/Documents/dev/github/project-euler/6/go 0.006s
That states pretty well what happened and should give you all the information you need to fix the problem. In this case, the problem is that the test itself is wrong and the expected value should be 3. That's an important lesson. Don't automatically assume that if a test fails the code under test is broken. Consider the entire system, which includes the code under test, the test itself, and the test environment.
Test Coverage
To ensure your code works, it's not enough to have passing tests. Another important aspect is test coverage. Do your tests cover every statement in the code? Sometimes even that is not enough. For example, if you have a loop in your code that runs until a condition is met, you may test it successfully with a condition that works, but fail to notice that in some cases the condition may always be false, resulting in an infinite loop.
Unit Tests
Unit tests are like brushing your teeth and flossing. You shouldn't neglect them. They are the first barrier against problems and will let you have confidence in refactoring. They are also a boon when trying to reproduce issues and being able to write a failing test that demonstrates the issue that passes after you fix the issue.
Integration Tests
Integration tests are necessary as well. Think of them as visiting the dentist. You may be OK without them for a while, but if you neglect them for too long it won't be pretty.
Most non-trivial programs are made of multiple inter-related modules or components. Problems can often occur when wiring those components together. Integration tests give you confidence that your entire system is operating as intended. There are many other types of tests like acceptance tests, performance tests, stress/load tests and full-fledged whole system tests, but unit tests and integration tests are two of the foundational ways to test software.
Conclusion
Go has built-in support for testing, a well-defined way to write tests, and recommended guidelines in the form of table-driven tests.
The need to write special structs for every combination of inputs and outputs is a little annoying, but that's the price you pay for Go's simple by design approach.
#webdevelop #webdesigns Websites that make you go wow: Fiat 124 Spider – ROADS: “Italian carmaker Fiat enlists the… https://t.co/FvzPBVVsqS
#webdevelop #webdesigns Websites that make you go wow: Fiat 124 Spider – ROADS: “Italian carmaker Fiat enlists the… https://t.co/FvzPBVVsqS
— Web Dev Pro (@Web_improve) October 18, 2016
from Twitter https://twitter.com/Web_improve
#webdevelop #webdesigns Blog: Websites that make you go wow: Fiat 124 Spider – ROADS: Hop into the back of a Fiat … https://t.co/9hISGwmxGx
#webdevelop #webdesigns Blog: Websites that make you go wow: Fiat 124 Spider – ROADS: Hop into the back of a Fiat … https://t.co/9hISGwmxGx
— Web Dev Pro (@Web_improve) October 18, 2016
from Twitter https://twitter.com/Web_improve
20 Superb New Website Templates from GT3Themes - only $17! https://t.co/HUkDxyxv13 #developerdeals
20 Superb New Website Templates from GT3Themes - only $17! https://t.co/HUkDxyxv13 #developerdeals
— Web Dev Pro (@Web_improve) October 18, 2016
from Twitter https://twitter.com/Web_improve
Monday, October 17, 2016
#webdevelop #webdesigns Blog: WebVR: the key players making it happen: Who are making WebVR happen? We look at the… https://t.co/qAc0SbaGvC
#webdevelop #webdesigns Blog: WebVR: the key players making it happen: Who are making WebVR happen? We look at the… https://t.co/qAc0SbaGvC
— Web Dev Pro (@Web_improve) October 17, 2016
from Twitter https://twitter.com/Web_improve
#webdevelop #webdesigns WebVR: the key players making it happen: GOOGLE With Cardboard, Google has put VR into the… https://t.co/uGplrerprg
#webdevelop #webdesigns WebVR: the key players making it happen: GOOGLE
— Web Dev Pro (@Web_improve) October 17, 2016
With Cardboard, Google has put VR into the… https://t.co/uGplrerprg
from Twitter https://twitter.com/Web_improve
Building Websites web Development Introduction to jQuery [100% Off] https://t.co/CKXjFqST6W #programming
Building Websites web Development Introduction to jQuery [100% Off] https://t.co/CKXjFqST6W #programming
— Web Dev Pro (@Web_improve) October 17, 2016
from Twitter https://twitter.com/Web_improve
Step By Step Java Programming Complete Course [$10 Only] https://t.co/Qe5YQgcst4 #programming
Step By Step Java Programming Complete Course [$10 Only] https://t.co/Qe5YQgcst4 #programming
— Web Dev Pro (@Web_improve) October 17, 2016
from Twitter https://twitter.com/Web_improve
Java Programming Tutorial For Beginners With Project [$10 Only] https://t.co/iyNOORVNhS #programming
Java Programming Tutorial For Beginners With Project [$10 Only] https://t.co/iyNOORVNhS #programming
— Web Dev Pro (@Web_improve) October 17, 2016
from Twitter https://twitter.com/Web_improve
BUNDLE: Gorgeous Flower Graphics - only $25! https://t.co/lYlyyISk97 #developerdeals
BUNDLE: Gorgeous Flower Graphics - only $25! https://t.co/lYlyyISk97 #developerdeals
— Web Dev Pro (@Web_improve) October 17, 2016
from Twitter https://twitter.com/Web_improve
Sunday, October 16, 2016
Learn HTML 4 from scratch scratch [$10 Only] https://t.co/uZJQn6UNRR #programming
Learn HTML 4 from scratch scratch [$10 Only] https://t.co/uZJQn6UNRR #programming
— Web Dev Pro (@Web_improve) October 17, 2016
from Twitter https://twitter.com/Web_improve
JavaScript: Learn JavaScript Essentials And Build Project [$10 Only] https://t.co/qEu4xaxlNr #webdevelopment
JavaScript: Learn JavaScript Essentials And Build Project [$10 Only] https://t.co/qEu4xaxlNr #webdevelopment
— Web Dev Pro (@Web_improve) October 16, 2016
from Twitter https://twitter.com/Web_improve
Saturday, October 15, 2016
How to Create Slack Bots #JavaScriptWorld https://t.co/Ur0Ts9Co36
How to Create Slack Bots #JavaScriptWorldhttps://t.co/Ur0Ts9Co36
— Web Dev Pro (@Web_improve) October 16, 2016
from Twitter https://twitter.com/Web_improve
Getting Started with Number Guesser in React.js #Nodejstutorial #reactjs https://t.co/FAgU7jY9wT
Getting Started with Number Guesser in React.js #Nodejstutorial #reactjshttps://t.co/FAgU7jY9wT
— Web Dev Pro (@Web_improve) October 16, 2016
from Twitter https://twitter.com/Web_improve
Next Generation Web Apps with Aurelia.js #JavaScriptWorld #Aureliajs https://t.co/DuGQWB9epl
Next Generation Web Apps with Aurelia.js #JavaScriptWorld #Aureliajshttps://t.co/DuGQWB9epl
— Web Dev Pro (@Web_improve) October 16, 2016
from Twitter https://twitter.com/Web_improve
Angular 2 for Angular 1 Developers #Nodejstutorial https://t.co/IJPPJDSEl0
Angular 2 for Angular 1 Developers #Nodejstutorialhttps://t.co/IJPPJDSEl0
— Web Dev Pro (@Web_improve) October 16, 2016
from Twitter https://twitter.com/Web_improve
Hot Reloading with React, Redux and Ember.js #Nodejstutorial #emberjs https://t.co/SBZ06UZbmv
Hot Reloading with React, Redux and Ember.js #Nodejstutorial #emberjshttps://t.co/SBZ06UZbmv
— Web Dev Pro (@Web_improve) October 16, 2016
from Twitter https://twitter.com/Web_improve
Redesigning & Rewriting our Application in Ember.js #JavaScriptWorld #Emberjs https://t.co/vcMSuHgd5W
Redesigning & Rewriting our Application in Ember.js #JavaScriptWorld #Emberjshttps://t.co/vcMSuHgd5W
— Web Dev Pro (@Web_improve) October 16, 2016
from Twitter https://twitter.com/Web_improve
How to Create a WordPress Website from Scratch – No Coding [100% Off] https://t.co/dWvn6O2lIH #webdevelopment
How to Create a WordPress Website from Scratch – No Coding [100% Off] https://t.co/dWvn6O2lIH #webdevelopment
— Web Dev Pro (@Web_improve) October 15, 2016
from Twitter https://twitter.com/Web_improve
AngularJS Tutorial for Beginners Part 3 #Nodejstutorial #AngularJS https://t.co/gbiZ3FDeEX https://t.co/NWlV5VmpG2
AngularJS Tutorial for Beginners Part 3 #Nodejstutorial #AngularJShttps://t.co/gbiZ3FDeEX http://pic.twitter.com/NWlV5VmpG2
— Web Dev Pro (@Web_improve) October 15, 2016
from Twitter https://twitter.com/Web_improve
AngularJS Tutorial for Beginners Part 2 #Nodejstutorial #AngularJS https://t.co/SdY7YolzDG https://t.co/apAF2ElPz7
AngularJS Tutorial for Beginners Part 2 #Nodejstutorial #AngularJShttps://t.co/SdY7YolzDG http://pic.twitter.com/apAF2ElPz7
— Web Dev Pro (@Web_improve) October 15, 2016
from Twitter https://twitter.com/Web_improve
AngularJS Tutorial for Beginners Part 1 #Nodejstutorial https://t.co/b2sDMRAWqF https://t.co/XGdaUkk3dy
AngularJS Tutorial for Beginners Part 1 #Nodejstutorialhttps://t.co/b2sDMRAWqF http://pic.twitter.com/XGdaUkk3dy
— Web Dev Pro (@Web_improve) October 15, 2016
from Twitter https://twitter.com/Web_improve
160 Website Flowchart Cards from The UI Shop - only $7! https://t.co/rLPdL730gg #developerdeals
160 Website Flowchart Cards from The UI Shop - only $7! https://t.co/rLPdL730gg #developerdeals
— Web Dev Pro (@Web_improve) October 15, 2016
from Twitter https://twitter.com/Web_improve
Crash Course Into JavaFX: The Best Way to make GUI Apps [FREE] https://t.co/ogRRGS9IR7 #programming
Crash Course Into JavaFX: The Best Way to make GUI Apps [FREE] https://t.co/ogRRGS9IR7 #programming
— Web Dev Pro (@Web_improve) October 15, 2016
from Twitter https://twitter.com/Web_improve
Friday, October 14, 2016
Getting Started with Ember.js #JavaScriptWorld #emberjs https://t.co/mqUfPnlVKc https://t.co/JUVK5A9tf3
Getting Started with Ember.js #JavaScriptWorld #emberjshttps://t.co/mqUfPnlVKc http://pic.twitter.com/JUVK5A9tf3
— Web Dev Pro (@Web_improve) October 15, 2016
from Twitter https://twitter.com/Web_improve
Angular Material 2 - Tutorial Building Your App High Quality UI #Nodejstutorial https://t.co/Epin2LYuGe https://t.co/f7ezUy7rhp
Angular Material 2 - Tutorial Building Your App High Quality UI #Nodejstutorialhttps://t.co/Epin2LYuGe http://pic.twitter.com/f7ezUy7rhp
— Web Dev Pro (@Web_improve) October 15, 2016
from Twitter https://twitter.com/Web_improve
Meteor.js - Create modern apps faster than ever in pure JavaScript #JavaScriptWorld https://t.co/hqzrLNN9VY https://t.co/Kth0ATBKvD
Meteor.js - Create modern apps faster than ever in pure JavaScript #JavaScriptWorldhttps://t.co/hqzrLNN9VY http://pic.twitter.com/Kth0ATBKvD
— Web Dev Pro (@Web_improve) October 15, 2016
from Twitter https://twitter.com/Web_improve
NYC.JS HTML5 Gaming #JavaScriptWorld #nycjs #html5 https://t.co/ZXmAjQIkFE https://t.co/rFYG90yj3b
NYC.JS HTML5 Gaming #JavaScriptWorld #nycjs #html5https://t.co/ZXmAjQIkFE http://pic.twitter.com/rFYG90yj3b
— Web Dev Pro (@Web_improve) October 15, 2016
from Twitter https://twitter.com/Web_improve
Ember.js Tutorial for Front End Frameworks #JavaScriptWorld #emberjs https://t.co/rxRaiM4NWQ https://t.co/QW8jCaeJa7
Ember.js Tutorial for Front End Frameworks #JavaScriptWorld #emberjshttps://t.co/rxRaiM4NWQ http://pic.twitter.com/QW8jCaeJa7
— Web Dev Pro (@Web_improve) October 15, 2016
from Twitter https://twitter.com/Web_improve
Let’s Make Some Great Art with Emberjs #JavaScriptWorld https://t.co/SUHB2Id0d3 https://t.co/YT5OZyJKS3
Let’s Make Some Great Art with Emberjs #JavaScriptWorldhttps://t.co/SUHB2Id0d3 http://pic.twitter.com/YT5OZyJKS3
— Web Dev Pro (@Web_improve) October 15, 2016
from Twitter https://twitter.com/Web_improve
Concurrency on Android with Service
In this tutorial we’ll explore the Service
component and its superclass, the IntentService
. You'll learn when and how to use this component to create great concurrency solutions for long-running background operations. We’ll also take quick look at IPC (Inter Process Communication), to learn how to communicate with services running on different processes.
To follow this tutorial you'll need some understanding of concurrency on Android. If you don’t know much about it, you might want to read some of our other articles about the topic first.
-
Android SDKAndroid From Scratch: Background OperationsPaul Trebilcox-Ruiz
-
AndroidUnderstanding AsyncTask Values in 60 SecondsPaul Trebilcox-Ruiz
-
Android SDKUnderstanding Concurrency on Android Using HaMeRTin Megali
-
Android SDKPractical Concurrency on Android With HaMeRTin Megali
1. The Service Component
The Service
component is a very important part of Android's concurrency framework. It fulfills the need to perform a long-running operation within an application, or it supplies some functionality for other applications. In this tutorial we’ll concentrate exclusively on Service
’s long-running task capability, and how to use this power to improve concurrency.
What is a Service?
A Service
is a simple component that's instantiated by the system to do some long-running work that doesn't necessarily depend on user interaction. It can be independent from the activity life cycle and can also run on a complete different process.
Before diving into a discussion of what a Service
represents, it's important to stress that even though services are commonly used for long-running background operations and to execute tasks on different processes, a Service
doesn't represent a Thread
or a process. It will only run in a background thread or on a different process if it's explicitly asked to do so.
A Service
has two main features:
- A facility for the application to tell the system about something it wants to be doing in the background.
- A facility for an application to expose some of its functionality to other applications.
Services and Threads
There is a lot of confusion about services and threads. When a Service
is declared, it doesn't contain a Thread
. As a matter of fact, by default it runs directly on the main thread and any work done on it may potentially freeze an application. (Unless it's a IntentService
, a Service
subclass that already comes with a worker thread configured.)
So, how do services offer a concurrency solution? Well, a Service
doesn't contain a thread by default, but it can be easily configured to work with its own thread or with a pool of threads. We'll see more about that below.
Disregarding the lack of a built-in thread, a Service
is an excellent solution for concurrency problems in certain situations. The main reasons to choose a Service
over other concurrency solutions like AsyncTask
or the HaMeR framework are:
- A
Service
can be independent of activity life cycles. - A
Service
is appropriate for running long operations. - Services don't depend on user interaction.
- When running on different processes, Android can try to keep services alive even when the system is short on resources.
- A
Service
can be restarted to resume its work.
Service Types
There are two types of Service
, started and bound.
A started service is launched via Context.startService()
. Generally it performs only one operation and it will run indefinitely until the operation ends, then it shuts itself down. Typically, it doesn't return any result to the user interface.
The bound service is launched via Context.bindService()
, and it allows a two-way communication between client and Service
. It can also connect with multiple clients. It destroys itself when there isn't any client connected to it.
To choose between those two types, the Service
must implement some callbacks: onStartCommand()
to run as a started service, and onBind()
to run as a bound service. A Service
may choose to implement only one of those types, but it can also adopt both at the same time without any problems.
2. Service Implementation
To use a service, extend the Service
class and override its callback methods, according to the type of Service
. As mentioned before, for started services the onStartCommand()
method must be implemented and for bound services, the onBind()
method. Actually, the onBind()
method must be declared for either service type, but it can return null for started services.
public class CustomService extends Service { @Override public int onStartCommand(Intent intent, int flags, int startId) { // Execute your operations // Service wont be terminated automatically return Service.START_NOT_STICKY; } @Nullable @Override public IBinder onBind(Intent intent) { // Creates a connection with a client // using a interface implemented on IBinder return null; } }
onStartCommand()
: launched byContext.startService()
. This is usually called from an activity. Once called, the service may run indefinitely and it's up to you to stop it, either callingstopSelf()
orstopService()
.onBind()
: called when a component wants to connect to the service. Called on the system byContext.bindService()
. It returns anIBinder
that provides an interface to communicate with the client.
The service's life cycle is also important to take into consideration. The onCreate()
and onDestroy()
methods should be implemented to initialize and shut down any resources or operations of the service.
Declaring a Service on Manifest
The Service
component must be declared on the manifest with the <service>
element. In this declaration it's also possible, but not obligatory, to set a different process for the Service
to run in.
<manifest ... > ... <application ... > <service android:name=".ExampleService" android:process=":my_process"/> ... </application> </manifest>
2.2. Working with Started Services
To initiate a started service you must call Context.startService()
method. The Intent
must be created with the Context
and the Service
class. Any relevant information or data should also be passed in this Intent
.
Intent serviceIntent = new Intent(this, CustomService.class); // Pass data to be processed on the Service Bundle data = new Bundle(); data.putInt("OperationType", 99); data.putString("DownloadURL", "http://ift.tt/2ebEbhI"); serviceIntent.putExtras(data); // Starting the Service startService(serviceIntent);
In your Service
class, the method that you should be concerned about is the onStartCommand()
. It's on this method that you should call any operation that you want to execute on the started service. You'll process the Intent
to capture information sent by the client. The startId
represents an unique ID, automatically created for this specific request and the flags
can also contain extra information about it.
@Override public int onStartCommand(Intent intent, int flags, int startId) { Bundle data = intent.getExtras(); if (data != null) { int operation = data.getInt(KEY_OPERATION); // Check what operation to perform and send a msg if ( operation == OP_DOWNLOAD){ // make a download } } return START_STICKY; }
The onStartCommand()
returns a constant int
that controls the behavior:
Service.START_STICKY
: Service is restarted if it gets terminated.Service.START_NOT_STICKY
: Service is not restarted.Service.START_REDELIVER_INTENT
: The service is restarted after a crash and the intents then processing will be redelivered.
As mentioned before, a started service needs to be stopped, otherwise it will run indefinitely. This can be done either by the Service
calling stopSelf()
on itself or by a client calling stopService()
on it.
void someOperation() { // do some long-running operation // and stop the service when it is done stopSelf(); }
Binding to Services
Components can create connections with services, establishing a two-way communication with them. The client must call Context.bindService()
, passing an Intent
, a ServiceConnection
interface and a flag
as parameters. A Service
can be bound to multiple clients and it will be destroyed once it has no clients connected to it.
void bindWithService() { Intent intent = new Intent(this, PlayerService.class); // bind with Service bindService(intent, mConnection, Context.BIND_AUTO_CREATE); }
It's possible to send Message
objects to services. To do it you'll need to create a Messenger
on the client side in a ServiceConnection.onServiceConnected
interface implementation and use it to send Message
objects to the Service
.
private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName className, IBinder service) { // use the IBinder received to create a Messenger mServiceMessenger = new Messenger(service); mBound = true; } @Override public void onServiceDisconnected(ComponentName arg0) { mBound = false; mServiceMessenger = null; } };
It's also possible to pass a response Messenger
to the Service
for the client to receive messages. Watch out though, because the client may not no longer be around to receive the service's message. You could also use BroadcastReceiver
or any other broadcast solution.
private Handler mResponseHandler = new Handler() { @Override public void handleMessage(Message msg) { // handle response from Service } }; Message msgReply = Message.obtain(); msgReply.replyTo = new Messenger(mResponseHandler); try { mServiceMessenger.send(msgReply); } catch (RemoteException e) { e.printStackTrace(); }
It's important to unbind from the Service when the client is being destroyed.
@Override protected void onDestroy() { super.onDestroy(); // disconnect from service if (mBound) { unbindService(mConnection); mBound = false; } }
On the Service
side, you must implement the Service.onBind()
method, providing an IBinder
provided from a Messenger
. This will relay a response Handler
to handle the Message
objects received from client.
IncomingHandler(PlayerService playerService) { mPlayerService = new WeakReference<>(playerService); } @Override public void handleMessage(Message msg) { // handle messages } } public IBinder onBind(Intent intent) { // pass a Binder using the Messenger created return mMessenger.getBinder(); } final Messenger mMessenger = new Messenger(new IncomingHandler(this));
3 Concurrency Using Services
Finally, it's time to talk about how to solve concurrency problems using services. As mentioned before, a standard Service
doesn't contain any extra threads and it will run on the main Thread
by default. To overcome this problem you must add an worker Thread
, a pool of threads or execute the Service
on a different process. You could also use a subclass of Service
called IntentService
that already contains a Thread
.
Making a Service Run on a Worker Thread
To make the Service
execute on a background Thread
you could just create an extra Thread
and run the job there. However Android offers us a better solution. One way to take the best advantage of the system is to implement the HaMeR framework inside the Service
, for example by looping a Thread
with a message queue that can process messages indefinitely.
It's important to understand that this implementation will process tasks sequentially. If you need to receive and process multiple tasks at the same time, you should use a pool of threads. Using thread pools is out of the scope of this tutorial and we won't talk about it today.
To use HaMeR you must provide the Service
with a Looper
, a Handler
and a HandlerThread
.
private Looper mServiceLooper; private ServiceHandler mServiceHandler; // Handler to receive messages from client private final class ServiceHandler extends Handler { ServiceHandler(Looper looper) { super(looper); } @Override public void handleMessage(Message msg) { super.handleMessage(msg); // handle messages // stopping Service using startId stopSelf( msg.arg1 ); } } @Override public void onCreate() { HandlerThread thread = new HandlerThread("ServiceThread", Process.THREAD_PRIORITY_BACKGROUND); thread.start(); mServiceLooper = thread.getLooper(); mServiceHandler = new ServiceHandler(mServiceLooper); }
If the HaMeR framework is unfamiliar to you, read our tutorials on HaMer for Android concurrency.
-
Android SDKUnderstanding Concurrency on Android Using HaMeRTin Megali
-
Android SDKPractical Concurrency on Android With HaMeRTin Megali
The IntentService
If there is no need for the Service
to be kept alive for a long time, you could use IntentService
, a Service
subclass that's ready to run tasks on background threads. Internally, IntentService
is a Service
with a very similar implementation to the one proposed above.
To use this class, all you have to do is extend it and implement the onHandleIntent()
, a hook method that will be called every time a client calls startService()
on this Service
. It's important to keep in mind that the IntentService
will stop as soon as its job is completed.
public class MyIntentService extends IntentService { public MyIntentService() { super("MyIntentService"); } @Override protected void onHandleIntent(Intent intent) { // handle Intents send by startService } }
IPC (Inter Process Communication)
A Service
can run on a completely different Process
, independently from all tasks that are happening on the main process. A process has its own memory allocation, thread group, and processing priorities. This approach can be really useful when you need to work independently from the main process.
Communication between different processes is called IPC (Inter Process Communication). In a Service
there are two main ways to do IPC: using a Messenger
or implementing an AIDL
interface.
We've learned how to send and receive messages between services. All that you have to do is use create a Messenger
using the IBinder
instance received during the connection process and use it to send a reply Messenger
back to the Service
.
private Handler mResponseHandler = new Handler() { @Override public void handleMessage(Message msg) { // handle response from Service } }; private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName className, IBinder service) { // use the IBinder received to create a Messenger mServiceMessenger = new Messenger(service); Message msgReply = Message.obtain(); msgReply.replyTo = new Messenger(mResponseHandler); try { mServiceMessenger.send(msgReply); } catch (RemoteException e) { e.printStackTrace(); } }
The AIDL
interface is a very powerful solution that allows direct calls on Service
methods running on different processes and it's appropriate to use when your Service
is really complex. However, AIDL
is complicated to implement and it's rarely used, so its use won't be discussed in this tutorial.
4. Conclusion
Services can be simple or complex. It depends on the needs of your application. I tried to cover as much ground as possible on this tutorial, however I've focused just on using services for concurrency purposes and there are more possibilities for this component. I you want to study more, take a look at the documentation and Android guides.
See you soon!
Introduction to Emberkit Emberjs #JavaScriptWorld #Emberjs https://t.co/KjcjgOTS81 https://t.co/jmaJ3ika2C
Introduction to Emberkit Emberjs #JavaScriptWorld #Emberjshttps://t.co/KjcjgOTS81 http://pic.twitter.com/jmaJ3ika2C
— Web Dev Pro (@Web_improve) October 14, 2016
from Twitter https://twitter.com/Web_improve
Ember Addons #JavaScriptWorld #Emberjs https://t.co/irYMnGCOt0 https://t.co/x9Sgfx9V0H
Ember Addons #JavaScriptWorld #Emberjshttps://t.co/irYMnGCOt0 http://pic.twitter.com/x9Sgfx9V0H
— Web Dev Pro (@Web_improve) October 14, 2016
from Twitter https://twitter.com/Web_improve
Complete Python Programming Course 2016: Code using Python 3 [100% Off] https://t.co/InmYVUotyr #programming
Complete Python Programming Course 2016: Code using Python 3 [100% Off] https://t.co/InmYVUotyr #programming
— Web Dev Pro (@Web_improve) October 14, 2016
from Twitter https://twitter.com/Web_improve
AbsurdJS Hacking the Front End #JavaScriptWorld #AbsurdJS https://t.co/gWYbUPLOF4 https://t.co/IMIxE1qzRZ
AbsurdJS Hacking the Front End #JavaScriptWorld #AbsurdJShttps://t.co/gWYbUPLOF4 http://pic.twitter.com/IMIxE1qzRZ
— Web Dev Pro (@Web_improve) October 14, 2016
from Twitter https://twitter.com/Web_improve
Updating a project to Emberjs #JavaScriptWorld #Emberjs https://t.co/SzqbP3FxDM https://t.co/IHLXe6hHNS
Updating a project to Emberjs #JavaScriptWorld #Emberjshttps://t.co/SzqbP3FxDM http://pic.twitter.com/IHLXe6hHNS
— Web Dev Pro (@Web_improve) October 14, 2016
from Twitter https://twitter.com/Web_improve
Learn Ember js from scratch [FREE] https://t.co/xLoEpymST5 #webdevelopment
Learn Ember js from scratch [FREE] https://t.co/xLoEpymST5 #webdevelopment
— Web Dev Pro (@Web_improve) October 14, 2016
from Twitter https://twitter.com/Web_improve
Script Fonts Bundle: 13 Fonts from QueenType (with extended license) - only $9! https://t.co/dlHfaDHdDO #developerdeals
Script Fonts Bundle: 13 Fonts from QueenType (with extended license) - only $9! https://t.co/dlHfaDHdDO #developerdeals
— Web Dev Pro (@Web_improve) October 14, 2016
from Twitter https://twitter.com/Web_improve
Thursday, October 13, 2016
#code #HTML5 #webdesigns #css #ruby Download of the Day: Pennant Mockup Template https://t.co/xihU19KzO1
#code #HTML5 #webdesigns #css #ruby Download of the Day: Pennant Mockup Template https://t.co/xihU19KzO1
— Web Dev Pro (@Web_improve) October 13, 2016
from Twitter https://twitter.com/Web_improve
Websockets and Ember Data #JavaScriptWorld https://t.co/J0MUuCntJg https://t.co/YvrerOJWFy
Websockets and Ember Data #JavaScriptWorldhttps://t.co/J0MUuCntJg http://pic.twitter.com/YvrerOJWFy
— Web Dev Pro (@Web_improve) October 13, 2016
from Twitter https://twitter.com/Web_improve