Understanding Bitcoin


Companion Video:

Bitcoin is just another currency. Bitcoin refers to the entire currency system and BitCOINS are basic units (just like Dollar or Pound)

Like other currencies, you can save/ spend Bitcoins, or exchange with other currencies.

What is Digital currency?

Digital currency can be easily stored and used on a computer.

Dollar can be considered digital currency as such, we can use it to shop online.

However, dollar supply is controlled by a centralized bank.

What is Decentralized?

Gold coins are decentralized, means, there is no central authority controls the supply of gold.

Anyone can dig for gold and distribute gold, but it is not easy to exchange with exact change.

Also not possible to transfer over internet.

Bitcoin is the world’s first currency that is both Digital and Decentralized, somewhat like digital gold.

Bitcoins is a stateless currency, not associated with any nation, but it is not a private currency.

Private currencies are issued by person or company/organization, may collapse due to bankruptcy or other failure of the person or company.

Bitcoin is not a company, nor controlled by a person/organization, so there is no single point of failure. Nobody can inflate the supply or create hyperinflation.

Why Bitcoin?

Now-a-days people can send digital cash back and forth via a central mediator (like, Paypal).

These central mediator can track payments and record the money transfer in a privately held account ledger.

Let’s indulge the thought that if we can trust such central mediator, or if we can send cash without being tracked.

The challenge with decentralized money is, how two strangers can trust each other and accomplish a financial transaction? [Aka, Byzantine Generals’ problem]

Learning from history

Between 1921 and 1924, the value of the German mark fell by a factor of more than 10 trillion due to overprinting by the government.

In 2008, the government of Zimbabwe printed so much of its currency that in a single year, a loaf of bread increased from $1 to $100 billion.

In both cases, any savings that people had in the form of national currency were completely destroyed.

Hello Bitcoin!

In 2008, Satoshi Nakamoto, described an elegant solution of Byzantine Generals’ problem and the invention of Bitcoin in a paper, Bitcoin: A Peer-to-Peer Electronic Cash System.

First version of the software that demonstrated the concept was written by Satoshi, but now open source.

In January 2009, first bitcoins were distributed using the software.

Slowly but surely the use of Bitcoin increased and what began as an experiment, now a multibillion dollar economy and process hundreds of thousands transaction per day.

Benefits of Bitcoin

  • International currency, anyone can send bitcoins to anyone else, almost instantly.
  • Travel the world without exchanging to local currency.
  • No middle man involved, so the transaction fees are negligible.
  • No need to provide personal information like credit cards.
  • No risk of losing savings or runaway inflation, it is designed to have fixed supply.
  • Fundamentally impossible to counterfeit.
  • Merchants can accept bitcoins without any paperwork.
  • No governments can seize your money.

Why understanding bitcoin is complex

At times, it was not comfortable for people to use pieces of paper instead of precious metals (gold/ silver).

Additionally it uses modern cryptography, digital signatures, public/private key pairs and secure hashing.

To resist abusers to destroy the system, Bitcoin’s design uses game theory to align incentives to maintain network and who act in for selfish interest.

How Bitcoin works

As a decentralized currency, without any central authority, everyone cooperates to keep track of everyone else’s money.

Imagine only $21 million exists in the world and there is a list of all people who possess the money and in what amount and EVERYONE has a copy of this list.

When you give $2 to your friend, you must subtract $2 from your entry and add $2 to her entry. After informing her about the transaction, she updates her list as well.

Now everyone needs to update the list, otherwise their list would be inaccurate. So in addition to notify your friend, you need to publicly announce that you are updating the list.

Now if you try to cheat and send your friend $1000, that you do not possess, your cheating attempt would be easy to catch, cause everyone knows you don’t have $1000.

Imagine the whole transactions are carried out on computers, automated and through internet and replace $ with bitcoins.

Few questions,

  • How the unit should be valued? Should a haircut be worth of 5000 bitcoins or 0.005 bitcoins?
  • How do you obtain the copy of the list?
  • How bitcoins initially distributed?

We will come to these points later.

Bitcoin units

Total currency is capped at 21 million, but the smallest unit is a hundred millionth of a bitcoin (0.00000001 bitcoins), called satoshi, in honor of Satoshi Nakamoto.

Goods can be priced very precisely with exact change. Like a gallon of milk is 0.00152374 bitcoins or 152,374 satoshis.

Merchants uses short form BTC or XBT for bitcoins.

1 bitcoin = 1 BTC or 1 XBT
1 BTC = 1,000 mBTC
1 mBTC = 1,000 µBTC
1 µBTC = 100 satoshis

Standard of currency code (ISO 4217) wise, since Bitcoin is a nongovernmental currency, the name should start with X, as is the case with gold (XAU) or silver (XAG).

Bitcoin address

Bitcoin uses a public ledger that indicates the number of bitcoins and their owner. Instead of owner name, they use Bitcoin address to associate with a owner.

A sample Bitcoin address:
13tQ1fbTMB6GxUJfMqCSDgivc8fvkHEh3J

Pretty much like a bank account number, usually starts with 1.

To send someone bitcoin you need to know their Bitcoin address. Similarly, when you share your address, others can send you bitcoins.

People uses QR (Quick Response) code to represent their address. You can print your address or QR code in business card/ website/ storefront.

You need an internet connection to send bitcoins, but you don’t need to be connected to receive. So you can pass out your address and collect bitcoins while you sleep.

Other than QR code, you can use first bits scheme to send out first few characters of the address. Or, you can use address-shortening service (like URL shortening). From version 0.9+ Bitcoin supports human readable address (like, website address rather than IP)

Bitcoins ledger copies are distributed across millions of computers, so there is no central point of failure and impossible to erase records.

But Bitcoin ledger are public information, so how do you maintain privacy? Although there is no personal information in ledger but as you share your address, people will know your Bitcoin balance.

To maintain privacy you can use many Bitcoin address, but publicly share one or some of them.

In general, maintaining complete privacy while doing online transaction is very difficult with or without Bitcoin. Although Bitcoin provides far better protection than Credit card, however other privacy-protecting tool (TOR) might need to be used as well.

Private Key

To unlock (move or send) bitcoins, there is a private key associated with each Bitcoin address.

If Bitcoin address is similar to bank account number, then private key is like PIN.

When a transaction is broadcast, computer check whether the transaction has been digitally signed using a private key that can only be created by someone possessing the private key.

Similar to PIN, private key should be kept secret. If someone obtains your private key, he will be able to spend your bitcoins.

Private key can be used to produce digital signature, but the reverse is not possible, means, you can not obtain the private key using digital signature. A digital signature can not be reused.

This is fundamentally different from online payment with credit card. You provide your card number to someone to authorize the transaction and that number can be reused (maliciously)

Unlike PIN, only you know the private key, not any bank/others. But if you lose the private key the bitcoins will remain locked in that address forever.

Key association

Every private key is associated with a single Bitcoin address, but the reverse is not true. A Bitcoin address can require multiple private keys to unlock.

Most people use multiple Bitcoin address, each with it’s own private key and store them in a digital wallet.

Bitcoin wallet

A Bitcoin wallet is a collection of address and corresponding private keys owned by one person. It helps to organize money and maintain privacy.

Bitcoin wallet program is a tool for common Bitcoin tasks, like, creating new Bitcoin address, sending bitcoins, backing up private keys etc.

greenaddressdesktop

GreenAddress.it android (a bitcoin wallet program)

Several other Bitcoin wallet program can be found here

There are some sites that are giving away small amounts of free Bitcoin, mostly for the newbies to try out. Here are two of these, TryBTC.com and Bitcoin Street Faucet. [No guarantee that they are still providing free coins when you stumble this blog post.]

Some wallet (for example, Electrum) ask for a seed, consists of 12 random words from you to generate Bitcoin address and private key. In case you lost your private key, it can be regained using the seed.

Blockchain

Bitcoin ledger is called Blockchain. Transactions are added in pool and about every 10 minutes, the pool transactions are bundled into a block and added to the blockchain.

transaction ID: 10110
address 1bl35lndlkas32l33 -2.0 BTC
address 18scklshl13nnlk33 +2.0 BTC
transaction ID: 10232
....

The thousands of computer that collects transactions and add them to blockchain are called miners. Anybody can be a miner by running open source Bitcoin-mining software.

Why would anyone update the blockchain? You might not want to send/receive bitcoins for months, then why bother update?

For the Bitcoin system it is required to keep the blockchain up-to-date. Otherwise, if only person had the latest copy then she could manipulate the records.

If you add a blockchain you will be rewarded with all the transaction fees of that block.

Blockchain lottery

Based on some probability a miner is chosen to add a block to blockchain. What is the purpose of using a lottery system to run Bitcoin?

When we engage in a transaction in $, we put our trust on a bank to confirm the transaction. The banker’s job is to announce that both party can trust each other and to update the ledger correctly.

In Bitcoin anyone can be a banker (miner) and then he announces to the network that the transaction is valid. Picking a person randomly helps to accomplish this.

There is a small chance that miner knows a person involved in a the transaction. To avoid this personal conflict interest, each miner also needs to confirm the previous transaction along with her’s.

To eligible for the next lottery, a miner needs the latest copy of the blockchain. It motivates then to add as many blocks to blockchain and update the blockchain.

The process is done automatically by Bitcoin-mining software, run by the community; no central authority exists to choose a winner. Thousands of miners constantly helping the transaction process.

Blockchain forking

Lottery system works as expected most of the time. Occasionally two miner finds a block at the same time and blockchain become forked, resulting two different branches.

For example, A and B both miners add a block to blockchain. The contents are identical but added by different miners.

Now in next 10 minutes, whichever these two branches take the next block would be the winning branch and other branch will be discarded, called orphaned.

The process is automatic and most of the users do not notice this forking, ignoring orphaned blocks and thus no negative impact on the use of Bitcoin.

Transaction confirmation

The transaction that not yet added to blockchain has a depth 0, newly added block transactions have depth 1, immediate previous transactions have depth 2.

For low-value transactions it’s enough to forgo the transaction of depth 1. Merchants require higher depth confirmation before selling high-priced item. But how this confirms if the transaction is valid?

Suppose a super-villain try to double spend his bitcoins. He simultaneously sends same bitcoins to receiver address and another address owned by him.

This is called Double-Spending problem. To know more details follow the post.

When miners detect two transactions that spent same bitcoins, but sent to different address, they accept the first one they received and ignore the second.

It is impossible to add both transaction to the blockchain as one contradicts to the other.

The super-villain intent is for the merchant to delivery the product but transaction to be ignored and the other transaction to be added to blockchain.

This devious scheme is usually unsuccessful because many merchants use special monitoring software that can recognize two conflicting Bitcoin transactions.

Even simpler for the merchant to wait for 10 minutes until the transaction is added to blockchain. However, what if the super-villain has truly extra ordinary resources (many millions of $ of hardware) and orphaned the block!

To cope with this remote possibility, merchants who sell high value products typically wait until a transaction has depth 2 before delivering the product.

Mining Bitcoins

Total supply of bitcoin is capped at 21 million and it reached slowly over time. Miner reward is included small sum of newly minted bitcoins that increased the total supply.

Miners must find a certain winning number by generating numbers at random repeatedly to win (thus getting newly minted bitcoin). It creates incentive for the miners to use power computers.

Today, mining requires significant capital, expertise, inexpensive electricity. Similar to gold mining, at one time unearthing gold could be done by a person, now this is performed by large companies with expensive drills.

There are two parts of mining reward.

  1. First part is transaction fee. Transaction fees are typically few cents, but as each block contains hundreds or thousands of transactions, the reward is the sum of all transactions fees.
  2. Second part is newly minted bitcoins.

The second part is decreasing gradually over time.

  • The first 210,000 blocks – on a 10 mins spanning – took 4 years to mine. It provided every miner 50 newly minted bitcoins per block + transaction fees.
  • The next 210,000 blocks – (210,001 to 420,000) – reward miners 25 newly minted bitcoins per block.
  • Thereafter, the reward drops to 12.5, 6.725 and so on.

This mining process is only source of new bitcoins. It is the reason no more than 21 million bitcoins will ever be in circulation.

Every 4 years the newly minted bitcoins rewarded per block halves.

Question: How can you ensure that only 210,000 blocks will be added every 4 years, it could be more (or less) based on the number of transactions and users?

Answer: Blocks are constrained by time, not transactions. A block can have any number of transactions, but one block will be added at every 10 mins. Due to increasing number of transactions in each block it requires a performant machine to process.

Transaction fees will grow as the Bitcoin user base grows. Eventually, transaction fees will be greater than newly minted bitcoin value.

At that point, Bitcoin network will be sustained entirely through transaction fees.

Don’t do this

Bitcoin wallet is pretty foolproof. However don’t do this,

  1. You created your first bitcoin wallet.
  2. You wrote down your address and private key.
  3. Well, what if you computer gets a virus that steal all your money?
  4. You thought that let’s DELETE the wallet, as you have written down private key.
  5. You money will go into back hole!!

What went wrong?

  • A Bitcoin wallet is not just ONE address, instead it’s a LIST of Bitcoin addresses.
  • When you send money from one address, all the money is used up of that address.
  • Don’t worry yet!! your money is safe. Listen to the rest of the process.
  • After sending, rest of the money moved to another address of the same wallet.
  • But you won’t be able to recover the new address if you only have the private key of the old address.

Think in terms of ENTIRE Bitcoin Wallet, not individual Bitcoin address.

Some wallet apps have a feature called, Import private key – only experts should rely on this risky feature.

Storing Bitcoin safely

Storing Bitcoin safely means storing your private key(s) safely. Nothing can be protected with 100 percent certainty. Bitcoins can be stored extremely securely or loosely (due to technical failures)

Your bitcoins are stored in blockchain. Millions of copies of blockchain are distributed all over the world and no disaster can erase every copies, so you don’t need to worry about your Bitcoin address.

To access the bitcoins you require private key. And you need to store your private key with serious precautions. Bitcoin allows you to be your own bank. It comes with great responsibility.

Hot storage vs Cold storage

Hot storage refers to private keys are stored on a online device. Cold storage refers the storage not accessible via internet.

You can share your Bitcoin address with everyone, but storing the private key in cold storage provides better security. Remember, a hot storage can not become cold by going offline.

If a wallet company claims they store your private in cold storage but the fund can be moved to hot storage conveniently, it is a red flag. May be they are not using cold storage at all. Cold storage requires a person to access an offline computer physically.

Personal vs Hosted wallets

With a personal wallet, only you know the private keys.

With a hosted wallet, a third party knows your private keys and they do operations (send, receive, store) on your behalf, (unlike traditional bank who stores your cash in vault and won’t give you keys to open it)

With online personal wallet, they host the wallet software on their server but not the private keys.

The liability can be distributed using two private keys, one will be used by customer and other by online service. Both keys will be required for unlocking one address.

Safety, Security and Convenience

These 3 major factors are sometimes conflict with each other.

  1. Safety (preventing accidental loss of bitcoins)
  2. Security (preventing the theft of bitcoins)
  3. Convenience (ability to easily unlock bitcoins)

Most people use two storage methods: one for storing small amounts conveniently but less securely, another for large amounts less conveniently but very securely. Just like carrying small cash in pocket but most of the cash in bank account.

Storing small amounts

The following methods are for small amount that are convenient, easy to use and reasonably safe.

A sophisticated attacker can hack your traditional bank account. As remedy banks implement daily withdrawal limits and other measures.

Online hosted wallet services

Similar to online banking, no software installation is required. They manage all your transfers on your behalf.

But you do not have access to your private keys and you may loose your bitcoins if the service provider goes bankrupt.

You can access the service using username/password (so can a thief!). Make sure your provide require two-factor authentication.

Remember that, provider knows who you are, how much bitcoins you have and all transactions.

Online personal wallet services

Similar to Online hosted wallet services, but once the website loads locally on your device, no communication occur to server.

You can make transactions by using your private keys that never leave your device.

If the company goes bankrupt you will have a little bit of inconvenience but never loose your bitcoins.

Typically it’s a greater responsibility. If you loose your password to their service, they can not rescue it for you. Write down your password in a secure place.

Online personal wallet services provide better security but they may track usage patterns and other data other than private keys.

Personal hot wallet

Install the wallet software (open source) in your device and full responsibility is yours. It provides greater security but you are to protect your device from malware, viruses.

Remember,

  • Do not keep large amount in your hot wallet.
  • Keep in mind that you computer can be stolen, destroyed, lost.
  • Avoid cloud storage to store your private keys.

Recommended personal hot wallet is Electrum or Multibit, both are open source and in use for many years.

Storing large amounts

Disclaimer: If you are storing a large Bitcoin fortune, consider having a security expert audit your storage method.

To try out the following methods you can use open source Bitcoin wallet generator, Bitaddress. You can download the entire website and run it on offline computer.

To use this website you need to cursor over a box of letters and numbers to provide a random seed to generate Bitcoin address. It’s a challenge of CS to generate truly random numbers.

Paper wallets

This is simplest and most popular cold storage method. Generate address and private in an offline computer and write down the keys in a paper and locked it away.

When you need to unlock, use import private key feature of any bitcoin wallet. Then immediately transfer the rest of the amount in another address and store the private key same way.

Paper wallets are one time use only. For each transaction you will create a new address and store a new private key.

Do not scan, take photo or any duplication method other than handwriting. Some photocopiers maintain records of every document they scan/copy.

Encrypted paper wallets

You write down an encrypted version of your private key in a paper. Most common encryption method used is BIP38 encryption.

To create BIP38 encrypted paper wallet, go to bitaddress site and shake your mouse until you generate enough random data for encryption.

Remember for encryption uses passphrases, not password. If you forget your passphrases you’ll permanently lose access of your bitcoins.

Store your paper wallet (written down encrypted private key) and passphrases into separate safe locations.

Offline transaction signing

In this process, you need two computers, one is online and other one is offline. Steps are follows

  1. Create an unsigned transaction from online computer.
  2. Copy the unsigned transaction to offline computer.
  3. Digitally sign the transaction in offline computer.
  4. Copy the signed transaction to online computer.
  5. Send signed transaction to the Bitcoin network.

To help out this process you can try a highly recommended wallet called Armony Bitcoin Client, which is open source and designed with maximum security in mind.

Fragmented private keys

A cryptographic trick named secret sharing, a Bitcoin private key can be divided into many fragments.

This is called m of n private key, where,

m = necessary fragments
n = available fragments.

For example, 3 of 5 private key means, a private key is split into 5 fragments and any 3 of them can be used to reconstruct it.

Several different cryptographic protocols are used for secret sharing, most popular is Shamir’s Secret Sharing method and several open source implementations of this method can be found on the Web.

Multi-signature addresses

This method uses multiple private keys rather fragments of single private key.

For example, 3 private keys are required to unlock an address, Or, any 2 of the 3 private keys can be used to unlock an address.

Multiple persons are required, not even CEO or President can solely able to unlock an address.

The Bitcoin hardware wallet

This is a small device that store your private keys in a way that no one can extract them from the device.

It works as a cold storage. Downside is, you need to purchase it and you may lose it.

Trezor received a lot of attention,

Trezor is like a paranoid chef who will never reveal his secret but cook for you anytime. You can use to any computers (good for traveler).

The bitcoin brain wallet

This method is recommended only for experts. Memorize your private key as passphrase. Then use the passphrase in an offline computer to retrieve your private key and address.

Buying bitcoins

To be continued

Source:

  1. Befuddled
  2. Introduction to Bitcoin and Decentralized Technology

Git and Github: Key points


Command line tutorial

File compare tool from OS

Windows :- FC (File compare)
Linux/Mac :- Diff (Difference)

Git

Check git version
git --version

Git commit story

  • Each commit has an Id. For a medium sized repository, first 8 chars can be enough to uniquely identify the commit.
  • Details log command,
    git log --stat
  • Display the difference between two commits,
    git diff COMMIT_ID_1 COMMIT_ID_2
    First write source commit and then destination commit. Depending on the source and destination order, you will be displayed add/delete codes.
    Altering these two will show the same changes but in opposite order.
  • There is a difference between copy and clone. In Clone, history will be downloaded as well as content.
  • Activate colorful git bash:
    git config --global color.ui.auto
  • Checkout
  • git checkout COMMIT_ID (Checkout a commit)
    git checkout BRANCH_NAME (Checkout a branch)

Detached HEAD

Whenever you checkout a previous commit, you will be in detached HEAD state. However you can restore the head by
git checkout master (Go back to master)
git checkout BRANCH_NAME (Go back to a branch)

Essentially it means, you are looking at a commit that was not labeled with a branch name.

You can see where HEAD is points to by command,
cat .git/HEAD

Note that, git log works from current branch to the parent commit

if you checkout an earlier commit and make changes and create a new commit then the new commit is lost and will not be displayed in output, cause it’s not reachable from current branch.

You can create a branch though to retain the changes in that newly created commit,
git checkout -b new_branch_name

Git workspace

Download two files

  1. git-completion.bash
  2. git-prompt.sh

add these two files in your .bash_profile like this,

source git-completion.bash
source git-prompt.sh

Set default editor to write commit messages

If you would like to open up your favorite editor whenever you write, git commit then run the following command,
git config --global core.editor "SUBLIME_PATH -n -w"

Here we are assuming your favorite editor is Sublime and replace SUBLIME_PATH with Sublime executable file.

In general if you would like to create an alias, (i.e typing a shortcut to open up Sublime or any other editor) the follow the command in your .bash_profile file
alias subl = "SUBLIME_PATH"

Common git commands

git log
git status
git clone
git diff
git checkout
git init

Staging area

There are 3 spaces:

  1. Working directory
  2. Staging area
  3. Repository

Create a file,
Using echo "First change" > index.txt

Initialize a repo by,
Using git init

Now index.txt is in your working directory.

Using git add index.txt you can add this file to staging.
Using git add . will all files to staging.

When you commit, git takes the entire changes of staging area and make a commit to repo.

Commit message style

Type

feat: a new feature
fix: a bug fix
docs: changes to documentation
style: formatting, missing semi colons, etc; no code change
refactor: refactoring production code
test: adding tests, refactoring test; no production code change
chore: updating build tasks, package manager configs, etc; no production code change

The Subject

Subjects should be no greater than 50 characters, should begin with a capital letter and do not end with a period.

Use an imperative tone to describe what a commit does, rather than what it did. For example, use change; not changed or changes.

The Body

Not all commits are complex enough to warrant a body, therefore it is optional and only used when a commit requires a bit of explanation and context. Use the body to explain the what and why of a commit, not the how.

When writing a body, the blank line between the title and the body is required and you should limit the length of each line to no more than 72 characters.

The Footer

The footer is optional and is used to reference issue tracker IDs.

Example commit msg

	feat: Summarize changes in around 50 characters or less

	More detailed explanatory text, if necessary. Wrap it to about 72
	characters or so. In some contexts, the first line is treated as the
	subject of the commit and the rest of the text as the body. The
	blank line separating the summary from the body is critical (unless
	you omit the body entirely); various tools like `log`, `shortlog`
	and `rebase` can get confused if you run the two together.

	Explain the problem that this commit is solving. Focus on why you
	are making this change as opposed to how (the code explains that).
	Are there side effects or other unintuitive consequenses of this
	change? Here's the place to explain them.

	Further paragraphs come after blank lines.

	- Bullet points are okay, too

	- Typically a hyphen or asterisk is used for the bullet, preceded
	by a single space, with blank lines in between, but conventions
	vary here

	If you use an issue tracker, put references to them at the bottom,
	like this:

	Resolves: #123
	See also: #456, #789

Commonly used git situations

  • You can compare two commits by git diff, but there is no Id in staging and working directory. So to compare working directory with staging area use no-arg git diff like this,
  • git diff

  • To compare staging with repo
  • git diff --staged

  • Discard changes in working directory
  • git checkout -- FILENAME

  • To discard any changes in working and staging area (be very careful, you can not revert this, codes in working and staging area have not been recorded )
  • git reset --hard

  • To go back to a particular commit, by discarding all the commits after it
  • git reset --hard DESIRED_COMMIT_ID

  • To go back to a commit but keeping your working directory as it is you can use reset soft. It will make code to move to that commit but your working directory will be same as of now. So the newly made changes will be there but code is commited upto that desired commit.
  • git reset --soft DESIRED_COMMIT_ID

  • To delete changes from staging area/li>
    git rm --cached FILE_NAME

Git branches

  • Display all branches as a list
  • git branch

  • Create a branch
  • git branch BRANCH_NAME

  • Checkout a branch
  • git checkout BRANCH_NAME

  • Graphical view of branches
  • git log --graph master BRANCH_NAME

  • Graphical view of branches (shorter)
  • git log --graph --oneline master BRANCH_NAME

  • Delete a branch
  • git branch -d BRANCH_NAME

  • Display the recent commit of all branches
  • git branch -v

Merge

How git merge works!

Suppose original file content is like below,
A
B
D

Now Tarif vai made some changes
B
D
E

Tarun vai also made some changes
A
B
C
D

Now if you ask git to merge the changes how will it manage to merge?

We are certain that,
B and
D
will present in final merged version, as these both are common in all 3 versions.

However,
A will not present. Becasue, Tarif vai deliberately removed it and Tarun vai didn’t do anything. Of course you don’t want to see a line in final merged version that has been deleted explicitely.
C will be present as Tarun vai added it.
E will be present as Tarif vai added it

When you merge two branches, git essentially creates another commit, called merge commit. But you may have missed it before because of IDE or SCM GUI.

Suppose, your master branch has some new commits and you are merging a previously created branch with it. Now if you run git log, in what order the log file will be displayed?
– It will be displayed in chronological order. That means, commits log will be jumbled up as the commits have been created in different point of time.

How will it affect you?
– If you run git diff of two consecutive commits, you may experience a large number of changes. May be because they are from differnt branch and just happen to reside together because of their commit time.

How do you get the REAL changes of a commit is this situation?
– Run git show COMMIT_ID, this will display the diff of this commit to it’s immediate parent commit

Merge Conflict

Merge conflict ocurres when two persons make changes in a single line. For example,

Original file content was,
A
B
C

Tarif vai made changes in 2nd line,
A
B'
C

Tarun vai also made this his changes in 2nd line,
A
B''
C

Before proceed with Git, you need to resolve the conflict. Remember, merge and conflict resolution goes into a single commit.

Rebase

Rebase is kind of an extension of merge. You still have to do the merging but the end result will be a bit differnt. Follow the concepts,

  • From a feature branch, if you rebase to master, git rebase master then the unique commits in feature branch will be applied to one by one on the top of present day master branch.
  • After the rebase you still need to do the merging. Checkout master branch and run,
  • git merge FEATURE_BRANCH

  • Now if you try git log --oneline --graph, you should see a cleaner commit history, as if there was no branching and you just applied the changes in master directly.

Github

We learnd there are 3 spaces in local repository: Working, Staging and Repo.
In remote repository like Github there are two types of repository: Origin, Upstream (You can create more if you wish, but these two are most common)

  • You can add multiple remote repos, if there is only one repo then we usually refer it by name origin
  • Fetch and Pull could be different url. To check remote urls,
  • git remote -v

  • To push to origin follow the format git push TARGET_REPOSITORY LOCAL_REPOSITORY
  • git push origin master

Fork

Fork is a concept introduced by Github, it’s not part of Git. Gitlab might call it a different name.
Fork means to clone repository from a other’s github account to your github account

When you push to remote branch there are two branches in your local machine,

  1. origin/master
  2. master

What happens when you have changes in both local master and origin master?
– Let me introduce git fetch. Git fetch updates your local machine’s origin/master and does not touch your local master branch. So there is no chance of conflict. After that you can use git log and git diff to compare.

Now you can also merge manually or you can do the fetch and merge combined by this command
git pull origin master

For log and diff in origin/master follow the command,
git log origin/master
git diff origin/master master

You can update all yoru local copies of every branches in the origin repositry by,
git fetch origin

If git pull == git fetch + git merge, then why git pull doesn’t generate a new merge commit like we see before?
– It’s called fast-forward merges. When base commit is ancestor of the other commit then it happens and merge commit will be a redundant commit, don’t ou think?

Pull request

When creating pull request from github, make sure you are selecting correct parent and correct child and also make sure chind branch can be successfully merged with parent branch so that one can accept just by a single click. Otherwise github will disable the merge request button.

So whenever you are making a pull request you need to pull the parent branche’s latest code and resolve all conflicts and create the pull request. If you request gets rejected then,

  1. fix the issue
  2. pull again from parent branch (if there is some changes meanwhile
  3. resolve conflicts (if any)
  4. push again

if you would like to get updates from Grand parent repo (from which you made the fork) or would like to make a pull request to Grand parent repo then you need to add the Grand parent repo as upstream by convention. it will create an upstream/master in your local machine.

To add an upstream url,
git remote add upstream GIT_URL

Now the rest follows exactly same as origin, just make sure to use upstream/master instead of origin/master when you refer to upstream.

Thanks for reading!

Golang: First look


Features of Golang:

  1. Compiled language. So, you can measure performance and do memory profile. It generates machine code that will run on the processor.
  2. Garbage collected. Usually system level langauges are not garbage collected, but Go is. Also note that, Go garbage collector is latency free. So, garbage collector runs without any speed bumps.
  3. Language level support for concurrency strategy known as communicating sequential processes aka Actor model.
  4. It’s not a C derivative language. It’s a static language but with the ease of dynamic language

Interesting notes

  • Like Swift playground in Xcode, you can try out go code in https://play.golang.org/
  • Go doesn’t have method overloading.
  • Function name starts with Uppercase are going to be exported (public)
  • Go packages can be directly imported from URL inside code
  • You can’t write curly braces in separate line, like C#. Yey!

Installation

Install Go and make sure to define GOROOT and GOPATH

export GOROOT="/usr/local/go"
export GOPATH="/Users/USERNAME/GoWorkspace/"

First Program

package main

import (
	"fmt"
)

func main() {
	fmt.Println("Hello, playground")
}

#1. package declaration is required and it is called module. “main” package denotes entry point
#7. You have to maintain the signature
func main() {
}

as it is the execution point

To run,
go run main.go
To build and make executable file,
go build main.go

Variable

package main

import "fmt"

func main() {
	// declare multiple variable
	var a, b int

	// initialize multiple variable
	var c, d int = 1, 2

	// omit data type
	var e, f = 4, 5

	// infer type
	var g, h = 6, false

	// declare and init together
	message := "Hello"

	// by default, un-initialized value is 0
	fmt.Println(a, b, c, d, e, f, g, h, message)
}

/*
Output:
0 0 1 2 4 5 6 false Hello
 */

Constant

package main

import (
	"fmt"
)

const (
	FIRST_CONSTANT = "Hello"
)

var (
	globalVar = 5
)

func main() {
	fmt.Println(FIRST_CONSTANT)
	fmt.Println(globalVar)
}

/*
Output
Hello
5
 */

Init function

If you write init function it will run the first time the module is referenced. It will run before the main function and after all the instance variable is initialized.

package main

import (
	"fmt"
)

var (
	globalVar = 5
)

func init() {
	globalVar = 6
}

func main() {
	fmt.Println(globalVar)
}

/*
Output
6
 */

Unused imports

Unused imports will give you error. For example, if you declare “fmt” package but do not use it, you will get error,

package main

import (
	"fmt"
)

var (
	globalVar = 5
)

func main() {
	println(globalVar)
}

// tmp/sandbox540429761/main.go:4: imported and not used: "fmt"

Installation

Download and install Go from here, https://golang.org/

Update your .bash_profile in MacOS or .bash_rc in Linux

export GOROOT="/usr/local/go/bin/go"
export GOPATH="/Users/<username>/GoWorkspace"
export PATH=$PATH:$GOROOT

Install Sublime and then Sublime package control,
https://packagecontrol.io/installation

Install GoSublime
https://github.com/DisposaBoy/GoSublime

Verify installation

Create a file named main.go

package main

func main() {
	println("Hello Go")
}

Open terminal and go to the file directory and run

~$ go run main.go
Hello Go

Data types

package main

func main() {
	var anInt int = 5

	// witout the . (dot) value will be inferred as int
	var aFloat float32 = 3. 

	// shorthand to declare and initialize
	aString := "Hello there" 

	println(anInt)
	println(aFloat)
	println(aString)
}

Constants again

package main

const (
	first = iota // auto incrementing number
	second
	third
)

func main() {
	println(first)
	println(second)
	println(third)
}

/*
0
1
2
*/
package main

const (
	first = 1 << iota
	second
	third
)

func main() {
	println(first)
	println(second)
	println(third)
}

/*
1
2
4
*/

Collections: Array

package main

import (
	"fmt"
)

func main() {
	anArray := [...]int{3, 6, 9, 12}

	fmt.Println(anArray)
	fmt.Println(len(anArray))
}

/*
[3 6 9 12]
4
*/

Collections: Slice

package main

import (
	"fmt"
)

func main() {
	anArray := [...]int{3, 6, 9, 12}

	aSlice := anArray[:]        // all elements
	aSlice = anArray[1:]        // except first element
	aSlice = append(aSlice, 15) // appending 15

	fmt.Println(aSlice)
	fmt.Println(len(aSlice))

	newSlice := []float32{1., 2., 3.}
	fmt.Println(newSlice)

	anotherSlice := make([]int, 20)
	anotherSlice[0] = 5
	anotherSlice[1] = 10

	fmt.Println(anotherSlice)
}

/*
[6 9 12 15]
4
[1 2 3]
[5 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
*/

Loop

package main

func main() {
	for i := 0; i < 5; i++ { 	} 	hello := 0 	for { 		hello++ 		if hello > 5 {
			break
		}
	}

	list := []string{"hello", "world", "go"}

	for index, value := range list {
		println(index, value)
	}
}

Functions

package main

func main() {
	param := "Hello there"
	helloGo(¶m)
	println(param)
}

func helloGo(param *string) {
	*param = "Hello Go"
}

func helloGo2(params ...string) {
	// variable argument function aka variadic parameter
}

Multiple return values

package main

func main() {
	result := add(1, 2, 3, 4)
	println(result)
	a, b := andAndLen(1, 2, 3, 4)
	println(a, b)
	len, sum := andAndLen2(1, 2, 3, 4)
	println(len, sum)
}

func add(nums ...int) int {
	ret := 0
	for _, num := range nums {
		ret += num
	}

	return ret
}

func andAndLen(nums ...int) (int, int) {
	ret := 0
	for _, num := range nums {
		ret += num
	}

	return len(nums), ret
}

func andAndLen2(nums ...int) (length int, sum int) {
	for _, num := range nums {
		sum += num
	}

	length = len(nums)

	return
}

Struct

package main

import (
	"fmt"
)

func main() {
	aVar := aStruct{}
	aVar.aField = "hello"

	anotherVar := aStruct{"hi"}
	println(anotherVar.aField)

	// creates the object in heap
	yetAnotherVar := new(aStruct)
	yetAnotherVar.aField = "hola"

	fmt.Println(aVar)
}

type aStruct struct {
	aField string
}

/*
hi
{hello}
*/

Constructor

package main

import (
	"fmt"
)

func main() {
	aVar := newAStruct()
	aVar.aMap["foo"] = "bar"

	fmt.Println(aVar)

}

type aStruct struct {
	aMap map[string]string
}

func newAStruct() *aStruct {
	ret := aStruct{}
	ret.aMap = map[string]string{}

	return &ret
}

Method

package main

func main() {
	mp := msgPrinter{"foo"}
	mp.printMsg()
}

type msgPrinter struct {
	msg string
}

func (mp *msgPrinter) printMsg() {
	println(mp.msg)
}

Go routine

package main

import (
	"runtime"
	"time"
)

func main() {
	runtime.GOMAXPROCS(4)

	go printMsg()
	println("after all print")
	time.Sleep(100 * time.Millisecond)
}

func printMsg() {
	for i := byte('a'); i <= byte('z'); i++ {
		go println(string(i))
	}
}

Xamarin.Forms: First look


Installation

In MacOS, install Xamarin Studio and you will be able to developing for iOS and Android.
In Windows, you will require to install Visual Studio and/or Xamarin Studio and you will be able to develop Android and Windows. If you have access to a MacOS then you will also be able to develop for iOS.

Go to, https://www.xamarin.com/download

Download Xamarin Studio and Install. The installation wizard will download a pretty big amount of data, like 3.5 GB. Bear with it.

After Installation, enter your credential in Xamarin Studio (Menu) -> Accounts.

Xamarin Player

Download Xamarin Player from, https://developer.xamarin.com/releases/android/android-player/

Screenshot at Nov 22 04-29-02.png

First Project

  1. Start Xamarin Studio/ Visual Studio
  2. File -> New Solution.
  3. Multiplatform -> App.
  4. Forms App (C#) -> Next.

Screenshot at Sep 17 11-13-37.png

  1. Give an app name. Here, XamarinFormsFirstLook
  2. Select Use Portable Class Library
  3. Select Use XAML for user interface files
  4. Next

Screenshot at Nov 22 04-12-13.png

Optionally you can enable Git and Automated UI test.

Screenshot at Nov 22 04-13-41.png

You should see there are three projects under a solution.

  1. Common code/ project (PCL)
  2. Droid project
  3. iOS project.

Screenshot at Nov 22 04-31-59.png

Before beginning, let’s build the project. Build (menu) -> Build All (Cmd + B)

Troubleshooting

Error MT0091: This version of Xamarin.iOS requires the iOS 10.0 SDK (shipped with Xcode 8.0) when the managed linker is disabled. Either upgrade Xcode, or enable the managed linker. (MT0091) (XAMLFirstLookDemo.iOS)

If you get the above error, it means you need to upgrade your Xcode.

If that is not an option for now, you can try to downgrade your Xamarin.iOS. You can get the previous Xamarin.iOS SDK here.

If that is not an option for now, you can enable the managed linker (although this may not work if your project uses API that was introduced in the required SDK).

(Disclaimer: This is official Xamarin suggestion, but didn’t work for me.)

Double-click on the iOS project and browse to iOS Build > Linker Options, as illustrated below:

Screenshot at Sep 17 11-31-59.png

And select, Linker behavior: Link All.

Rebuild the project again.

Project Structure

There are 3 projects inside the solution XamarinFormsFirstLook

Screenshot at Nov 22 04-36-47.png

We will be working with XamarinFormsFirstLookPage.xaml file.

Let’s create a simple change in the XamarinFormsFirstLookPage.xaml file

First Program

<?xml version="1.0" encoding="utf-8"?>
<ContentPage 	xmlns="http://xamarin.com/schemas/2014/forms" 	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 	xmlns:local="clr-namespace:XamarinFormsFirstLook" 	x:Class="XamarinFormsFirstLook.XamarinFormsFirstLookPage">
	<ContentPage.Content>
		<StackLayout 			Padding="16">
			<Label 				Text="Welcome to Xamarin Forms!" 				VerticalOptions="Start" 				HorizontalOptions="Center" />
			<StackLayout 				Orientation="Horizontal" 				Spacing="8">
				<Label 					Text="Name" 					VerticalOptions="Center" />
				<Entry 					Placeholder="Enter your name" />
			</StackLayout>
		</StackLayout>
	</ContentPage.Content>
</ContentPage>

Run the application and see the output in iOS simulator.

The equivalent C# code would look like this,

namespace XamarinFormsFirstLookPage
{
	public partial class XAMLFirstLookDemoPage : ContentPage
	{
		public XAMLFirstLookDemoPage()
		{
			Content = CreateUI();
			InitializeComponent();
		}

		public View CreateUI()
		{
			var parentStackLayout = new StackLayout()
			{
				Padding = 16,
				Children = {
					new Label() {
						Text = "Welcome to Xamarin Forms!",
						VerticalOptions = LayoutOptions.Start,
						HorizontalOptions = LayoutOptions.Center
					},
					new StackLayout() {
						Orientation = StackOrientation.Horizontal,
						Padding = 16,
						Children = {
							new Label() {
								Text = "Name",
								VerticalOptions = LayoutOptions.Center
							},
							new Entry() {
								Placeholder = "Enter your name"
							}
						}
					}
				}
			};

			return parentStackLayout;
		}
	}
}

Add an Action

<?xml version="1.0" encoding="utf-8"?>
<ContentPage 	xmlns="http://xamarin.com/schemas/2014/forms" 	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 	xmlns:local="clr-namespace:XamarinFormsFirstLook" 	x:Class="XamarinFormsFirstLook.XamarinFormsFirstLookPage">
	<ContentPage.Content>
		<StackLayout 			Padding="16">
			<Label 				Text="Welcome to Xamarin Forms!" 				VerticalOptions="Start" 				HorizontalOptions="Center" />
			<StackLayout 				Orientation="Horizontal" 				Spacing="8">
				<Label 					Text="Name" 					VerticalOptions="Center" />
				<Entry 					Placeholder="Enter your name" />
				<Button Text="Submit" Clicked="Submit_Clicked"/>
			</StackLayout>
		</StackLayout>
	</ContentPage.Content>
</ContentPage>
using System;
using Xamarin.Forms;

namespace XamarinFormsFirstLook
{
	public partial class XamarinFormsFirstLookPage : ContentPage
	{
		public XamarinFormsFirstLookPage()
		{
			InitializeComponent();
		}

	    private void Submit_Clicked(object sender, EventArgs e)
	    {
	        DisplayAlert("Greetings!", "Hello from Xamarin.Forms!", "OK");
	    }
	}
}

Navigation

To navigate from one page to another you need Navigation.
Using Navigation you can move to next page, come back to previous page, skip any intermediate page, remove a page, insert a new page in between etc.

In this example, we will add a button in our first page and tapping on the button will take us to the second page.

Let’s add NavigationPage.

using Xamarin.Forms;

namespace XamarinFormsFirstLook
{
	public partial class App : Application
	{
		public App()
		{
			InitializeComponent();

			MainPage = new NavigationPage(new XamarinFormsFirstLookPage());
		}

		protected override void OnStart()
		{
			// Handle when your app starts
		}

		protected override void OnSleep()
		{
			// Handle when your app sleeps
		}

		protected override void OnResume()
		{
			// Handle when your app resumes
		}
	}
}

Now let’s create a new page

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage 	xmlns="http://xamarin.com/schemas/2014/forms" 	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 	x:Class="XamarinFormsFirstLook.NextPage">
	<ContentPage.Content>
		<Button 				Text="Hello I am Next Page" 				VerticalOptions="Start" 				HorizontalOptions="Center" 				Clicked="GoBack_Clicked"/>
	</ContentPage.Content>
</ContentPage>

using System;
using System.Collections.Generic;

using Xamarin.Forms;

namespace XamarinFormsFirstLook
{
	public partial class NextPage : ContentPage
	{
		public NextPage()
		{
			InitializeComponent();
		}

		private void GoBack_Clicked(object sender, EventArgs e)
		{
			Navigation.PopAsync();
		}
	}
}

Add a button and title in our first page

<?xml version="1.0" encoding="utf-8"?>
<ContentPage 	xmlns="http://xamarin.com/schemas/2014/forms" 	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 	xmlns:local="clr-namespace:XamarinFormsFirstLook" 	x:Class="XamarinFormsFirstLook.XamarinFormsFirstLookPage" 		Title="Xamarin.Forms First Look">
	<ContentPage.Content>
		<StackLayout 			Padding="16">
			<Label 				Text="Welcome to Xamarin Forms!" 				VerticalOptions="Start" 				HorizontalOptions="Center" />
			<StackLayout 				Orientation="Horizontal" 				Spacing="8">
				<Label 					Text="Name" 					VerticalOptions="Center" />
				<Entry 					Placeholder="Enter your name" />
				<Button Text="Submit" Clicked="Submit_Clicked"/>
			</StackLayout>
			<Button Text="Next Page" Clicked="NextPage_Clicked"/>
		</StackLayout>
	</ContentPage.Content>
</ContentPage>
using System;
using Xamarin.Forms;

namespace XamarinFormsFirstLook
{
	public partial class XamarinFormsFirstLookPage : ContentPage
	{
		public XamarinFormsFirstLookPage()
		{
			InitializeComponent();
		}

		private void Submit_Clicked(object sender, EventArgs e)
		{
			DisplayAlert("Greetings!", "Hello from Xamarin.Forms!", "OK");
		}

		private void NextPage_Clicked(object sender, EventArgs e)
		{
			Navigation.PushAsync(new NextPage());
		}
	}
}

Let’s run the app again.

Data binding

Create a model class User, with some simple properties.

namespace XamarinFormsFirstLook.Models
{
    public class User
    {
        public User()
        {
        }

        public string FirstName { get; set; }
        public string LastName { get; set; }
        public int Age { get; set; }
	public string Password { get; set; }
    }
}

XAML layout file to display the properties

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage 	xmlns="http://xamarin.com/schemas/2014/forms" 	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 	x:Class="XamarinFormsFirstLook.DataBindingPage1">
	<ContentPage.Content>
		<StackLayout 			Padding="16">
			<Label 				Text="{Binding FirstName}" 				Font="16" />
			<Label 				Text="{Binding LastName}" 				Font="14" />
			<Label 				Text="{Binding Age}" 				Font="12" />
		</StackLayout>
	</ContentPage.Content>
</ContentPage>

Now we will create a simple User object and set it as BindingContext

using System;
using System.Collections.Generic;

using Xamarin.Forms;
using XamarinFormsFirstLook.Models;

namespace XamarinFormsFirstLook
{
	public partial class DataBindingPage1 : ContentPage
	{
		public DataBindingPage1()
		{
			BindingContext = GetUser();
			InitializeComponent();
		}

		private User GetUser()
		{
			return new User
			{
				FirstName = "John",
				LastName = "Doe",
				Age = 25
			};
		}
	}
}

Data binding#2

using System;
using XamarinFormsFirstLook.Models;

namespace XamarinFormsFirstLook
{
	public class DataBindingPage2ViewModel
	{
		public DataBindingPage2ViewModel(User user)
		{
			FullName = user.FirstName + " " + user.LastName;
			Age = GetAge(user.Age);
			Password = user.Password.Length == 0 ? "<Set password>" : "******";
		}

		string GetAge(int Age)
		{
			if (Age < 18) return Age + "(Child)";
			if (Age < 30) return Age + "(Young)";
			if (Age < 50) return Age + "(Adult)";
			else return Age + "(Old)";
		}

		public string FullName { get; set; }
		public string Age { get; set; }
		public string Password { get; set; }

		public static User GetUser()
		{
			return new User()
			{
				FirstName = "John",
				LastName = "Doe",
				Age = 25,
				Password = "Jonny"

			};
		}

		public static User GetUser2()
		{
			return new User()
			{
				FirstName = "Sarah",
				LastName = "Doe",
				Age = 65,
				Password = ""
			};
		}

	}
}
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage 	xmlns="http://xamarin.com/schemas/2014/forms" 	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 	x:Class="XamarinFormsFirstLook.DataBindingPage2">
	<ContentPage.Content>
		<StackLayout 			Padding="16">
			<Label 				Text="{Binding FullName}" 				Font="16" />
			<Label 				Text="{Binding Age}" 				Font="14" />
			<Label 				Text="{Binding Password}" 				Font="12" />
		</StackLayout>
	</ContentPage.Content>
</ContentPage>
using System;
using System.Collections.Generic;

using Xamarin.Forms;
using XamarinFormsFirstLook.Models;

namespace XamarinFormsFirstLook
{
	public partial class DataBindingPage2 : ContentPage
	{
		DataBindingPage2ViewModel dbp2VM;

		public DataBindingPage2()
		{
			User user1 = DataBindingPage2ViewModel.GetUser();
			User user2 = DataBindingPage2ViewModel.GetUser2();

			dbp2VM = new DataBindingPage2ViewModel(user2);
			BindingContext = dbp2VM;

			InitializeComponent();
		}
	}
}

List View

using System;
using System.Collections.Generic;
using XamarinFormsFirstLook.Model;

namespace XamarinFormsFirstLook
{
	public class ListPage1ViewModel
	{
		public string FirstName { get; set; }
		public string LastName { get; set; }
		public string Age { get; set; }

		public ListPage1ViewModel()
		{
		}

		public List<User> Users()
		{
			return new List<User>()
			{
				new User() {FirstName = "John", LastName = "Doe", Age = 25},
				new User() {FirstName = "Sarah", LastName = "Doe", Age = 58},
				new User() {FirstName = "Andrew", LastName = "Phillips", Age = 35}
			};

		}
	}
}
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage 	xmlns="http://xamarin.com/schemas/2014/forms" 	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 	x:Class="XamarinFormsFirstLook.ListPage1">
	<ContentPage.Content>
		<ListView 			x:Name="UserListView" 			ItemSelected="ListView_OnItemSelected" 			RowHeight="120">
			<ListView.ItemTemplate>
				<DataTemplate>
					<ViewCell>
						<StackLayout 							Padding="16" 							Spacing="8" 							Orientation="Vertical">
							<Label 								Text="{Binding FirstName}" 								FontSize="20">
							</Label>
							<Label 								Text="{Binding LastName}" 								FontSize="18">
							</Label>
							<Label 								Text="{Binding Age}" 								FontSize="16">
							</Label>
						</StackLayout>
					</ViewCell>
				</DataTemplate>
			</ListView.ItemTemplate>
		</ListView>
	</ContentPage.Content>
</ContentPage>
using System;
using System.Collections.Generic;

using Xamarin.Forms;
using XamarinFormsFirstLook.Model;

namespace XamarinFormsFirstLook
{
	public partial class ListPage1 : ContentPage
	{
		private ListPage1ViewModel vm;

		public ListPage1()
		{

			InitializeComponent();
			vm = new ListPage1ViewModel();
			UserListView.ItemsSource = vm.Users();
		}

		private void ListView_OnItemSelected(object sender, SelectedItemChangedEventArgs e)
		{
			User user = e.SelectedItem as User;
			DisplayAlert("User selected", user.FirstName, "OK");
		}
	}
}

Tabbed Pages

Create a generic XAML file

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage 	xmlns="http://xamarin.com/schemas/2014/forms" 	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 	x:Class="XamarinFormsFirstLook.TabPage1" 	Title="Tab 1">
	<ContentPage.Content>
		<Label 			Text="I am Tab 1" 			FontSize="20" 			VerticalOptions="Center" 			HorizontalOptions="Center" />
	</ContentPage.Content>
</ContentPage>

Remember, the Title property is very important.

using System;
using System.Collections.Generic;

using Xamarin.Forms;

namespace XamarinFormsFirstLook
{
	public partial class TabPage1 : ContentPage
	{
		public TabPage1()
		{
			InitializeComponent();
		}
	}
}
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage 	xmlns="http://xamarin.com/schemas/2014/forms" 	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 	x:Class="XamarinFormsFirstLook.TabPage2" 	Title="Tab 2">
	<ContentPage.Content>
		<Label 			Text="I am Tab 2" 			FontSize="20" 			VerticalOptions="Center" 			HorizontalOptions="Center" />
	</ContentPage.Content>
</ContentPage>
using System;
using System.Collections.Generic;

using Xamarin.Forms;

namespace XamarinFormsFirstLook
{
	public partial class TabPage2 : ContentPage
	{
		public TabPage2()
		{
			InitializeComponent();
		}
	}
}
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage 	xmlns="http://xamarin.com/schemas/2014/forms" 	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 	x:Class="XamarinFormsFirstLook.TabPage3" 	Title="Tab 3">
	<ContentPage.Content>
		<Label 			Text="I am Tab 3" 			FontSize="20" 			VerticalOptions="Center" 			HorizontalOptions="Center" />
	</ContentPage.Content>
</ContentPage>
using System;
using System.Collections.Generic;

using Xamarin.Forms;

namespace XamarinFormsFirstLook
{
	public partial class TabPage3 : ContentPage
	{
		public TabPage3()
		{
			InitializeComponent();
		}
	}
}

Now we need a tab container, TabbedPage

<?xml version="1.0" encoding="UTF-8"?>
<TabbedPage 	xmlns="http://xamarin.com/schemas/2014/forms" 	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 	x:Class="XamarinFormsFirstLook.TabContainer" 	xmlns:local="clr-namespace:XamarinFormsFirstLook;assembly=XamarinFormsFirstLook">

	<TabbedPage.Children>
		<local:TabPage1/>
		<local:TabPage2/>
		<local:TabPage3/>
	</TabbedPage.Children>

</TabbedPage>
using System;
using System.Collections.Generic;

using Xamarin.Forms;

namespace XamarinFormsFirstLook
{
	public partial class TabContainer : TabbedPage
	{
		public TabContainer()
		{
			InitializeComponent();
		}
	}
}

Static Style

Let’s create a StylePage and will put colors on our regular controls.

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage 	xmlns="http://xamarin.com/schemas/2014/forms" 	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 	x:Class="XamarinFormsFirstLook.StylePage">
	<ContentPage.Resources>
		<ResourceDictionary>
<Style 				x:Key="buttonStyle" 				TargetType="Button">
				<Setter 					Property="HorizontalOptions" 					Value="Center">
				</Setter>
				<Setter 					Property="TextColor" 					Value="Lime">
				</Setter>
				<Setter 					Property="FontSize" 					Value="20">
				</Setter>
			</Style>
<Style 				TargetType="Label">
				<Setter 					Property="HorizontalOptions" 					Value="Center">
				</Setter>
				<Setter 					Property="TextColor" 					Value="Blue">
				</Setter>
				<Setter 					Property="FontSize" 					Value="26">
				</Setter>
			</Style>
<Style 				x:Key="baseStyle" 				TargetType="View">
				<Setter 					Property="HorizontalOptions" 					Value="Start">
				</Setter>
			</Style>
<Style 				x:Key="entryStyle" 				TargetType="Entry" 				BasedOn="{StaticResource baseStyle}">
				<Setter 					Property="TextColor" 					Value="Red">
				</Setter>
			</Style>

		</ResourceDictionary>
	</ContentPage.Resources>
	<ContentPage.Content>
		<StackLayout 			Orientation="Vertical">
			<Button 				Text="Button 01" 				Style="{StaticResource buttonStyle}">
			</Button>
			<Button 				Text="Button 02">
			</Button>
			<Button 				Text="Button 03" 				BorderWidth="2">
			</Button>
			<Label 				Text="Label 01">
			</Label>
			<Entry 				Placeholder="Entry 01">
			</Entry>
			<Entry 				Placeholder="Entry 02" 				Style="{StaticResource entryStyle}">
			</Entry>
		</StackLayout>
	</ContentPage.Content>
</ContentPage>
using System;
using System.Collections.Generic;

using Xamarin.Forms;

namespace XamarinFormsFirstLook
{
	public partial class StylePage : ContentPage
	{
		public StylePage()
		{
			InitializeComponent();
		}
	}
}

Dynamic Style

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage 	xmlns="http://xamarin.com/schemas/2014/forms" 	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 	x:Class="XamarinFormsFirstLook.DynamicStylePage">
	<ContentPage.Resources>
		<ResourceDictionary>
			<x:String 				x:Key="currentTime">Show current time</x:String>
		</ResourceDictionary>
	</ContentPage.Resources>
	<ContentPage.Content>
		<Label 			HorizontalOptions="Center" 			VerticalOptions="Center" 			FontSize="24" 			Text="{DynamicResource currentTime}">
		</Label>
	</ContentPage.Content>
</ContentPage>
using System;
using System.Collections.Generic;

using Xamarin.Forms;

namespace XamarinFormsFirstLook
{
	public partial class DynamicStylePage : ContentPage
	{
	    private bool shouldDisplayTime;

		public DynamicStylePage()
		{
			InitializeComponent();
		}

	    protected override void OnAppearing()
	    {
	        shouldDisplayTime = true;
	        Device.StartTimer( TimeSpan.FromSeconds(1), () =>
	        {
	            Resources["currentTime"] = DateTime.Now.ToString();
	            return shouldDisplayTime;
	        });
	        base.OnAppearing();

	    }

	    protected override void OnDisappearing()
	    {
	        shouldDisplayTime = false;
	        base.OnDisappearing();
	    }
	}
}

Triggers

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage 	xmlns="http://xamarin.com/schemas/2014/forms" 	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 	xmlns:local="clr-namespace:XamarinFormsFirstLook;assembly=XamarinFormsFirstLook" 	x:Class="XamarinFormsFirstLook.TriggerPage" 	Title="Trigger">
	<ContentPage.Resources>
		<ResourceDictionary>
<Style 				TargetType="Entry">
				<Style.Triggers>
					<Trigger 						Property="Entry.IsFocused" 						Value="true" 						TargetType="Entry">
						<Setter 							Property="Entry.TextColor" 							Value="Blue" />
					</Trigger>
				</Style.Triggers>
			</Style>

		</ResourceDictionary>
	</ContentPage.Resources>
	<ContentPage.Content>
		<StackLayout 			Padding="16">
			<Entry 				Placeholder="Enter your first name" />
			<Entry 				Placeholder="Enter your last name" />
			<Entry 				TextColor="Black" 				Placeholder="Enter your age">
				<Entry.Triggers>
					<EventTrigger 						Event="TextChanged">
						<local:EntryValidation />
					</EventTrigger>
				</Entry.Triggers>
			</Entry>
		</StackLayout>
	</ContentPage.Content>
</ContentPage>
using Xamarin.Forms;

namespace XamarinFormsFirstLook
{
    public class EntryValidation : TriggerAction<Entry>
    {
        public EntryValidation()
        {
        }

        protected override void Invoke(Entry sender)
        {
            int parsedAge;

            bool isValid = int.TryParse(sender.Text, out parsedAge);

            if (!isValid)
            {
                sender.TextColor = Color.Red;
            }
            else {
                sender.TextColor = Color.Blue;
            }
        }
    }
}

Publisher Subscriber (Pub Sub)

We can send messages from one page to another.

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage 	xmlns="http://xamarin.com/schemas/2014/forms" 	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 	x:Class="XamarinFormsFirstLook.PubSubPage" 	Title="Pub Sub Page">
	<ContentPage.Content>
		<Button 			x:Name="ButtonPubSub" 			HorizontalOptions="Center" 			VerticalOptions="Center" 			Text="Next page" 			Clicked="Button_OnClicked">
		</Button>
	</ContentPage.Content>
</ContentPage>
using System;
using System.Collections.Generic;

using Xamarin.Forms;

namespace XamarinFormsFirstLook
{
	public partial class PubSubPage : ContentPage
	{
		public PubSubPage()
		{
			InitializeComponent();
		    Subscribe();
		}

	    private void Subscribe()
	    {
	        MessagingCenter.Subscribe<PubSubPage>(this, "fireEvent", (sender) =>
	        {
	            ButtonPubSub.Text = "Don't click!!";
	        });
	    }

	    private void Button_OnClicked(object sender, EventArgs e)
	    {
	        Navigation.PushAsync(new PubPage());
	    }
	}
}

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage 	xmlns="http://xamarin.com/schemas/2014/forms" 	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 	x:Class="XamarinFormsFirstLook.PubPage" 	Title="Pub Page">
	<ContentPage.Content>
		<Button 			HorizontalOptions="Center" 			VerticalOptions="Center" 			Text="Pub Page" 			Clicked="Button_OnClicked">
		</Button>
	</ContentPage.Content>
</ContentPage>
using System;
using System.Collections.Generic;

using Xamarin.Forms;

namespace XamarinFormsFirstLook
{
	public partial class PubPage : ContentPage
	{
		public PubPage()
		{
			InitializeComponent();
		}

	    private void Button_OnClicked(object sender, EventArgs e)
	    {
            MessagingCenter.Send<PubSubPage>(new PubSubPage(), "fireEvent");
	        Navigation.PopAsync();
	    }
	}
}
<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:Todo_Xamarin_Forms" x:Class="Todo_Xamarin_Forms.Todo_Xamarin_FormsPage">
	<ContentPage.Content>
		<StackLayout Padding="16" BackgroundColor="Blue" />
	</ContentPage.Content>
</ContentPage>

On #4 we have  BackgroundColor="Blue" and it takes up whole space of iOS but leaves the status bar of Android.

To resolve this, we need to add padding in iOS

<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:Todo_Xamarin_Forms" x:Class="Todo_Xamarin_Forms.Todo_Xamarin_FormsPage">
	<ContentPage.Padding>
        <OnPlatform x:TypeArguments="Thickness" iOS="0, 20, 0, 0" />
	</ContentPage.Padding>
	<ContentPage.Content>
		<StackLayout Padding="16" BackgroundColor="Blue" />
	</ContentPage.Content>
</ContentPage>

Adding a StackLayout with an Entry and Button click handler.

<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:Todo_Xamarin_Forms" x:Class="Todo_Xamarin_Forms.Todo_Xamarin_FormsPage">
	<ContentPage.Padding>
		<OnPlatform x:TypeArguments="Thickness" iOS="0, 20, 0, 0" />
	</ContentPage.Padding>
	<ContentPage.Content>
		<!--  		Padding = Layout padding 		Spacing = Space between elements  		-->
		<StackLayout Padding="16" Spacing="8" VerticalOptions="Center" HorizontalOptions="Center">
			<Label x:Name="LblName" Text="Enter user name" />
			<Entry x:Name="TxtUserName" Placeholder="Enter user name" />
			<Button x:Name="BtnSubmit" Text="Submit" IsEnabled="true" Clicked="Submit_Clicked" />
		</StackLayout>
	</ContentPage.Content>
</ContentPage>
using System;
using Xamarin.Forms;

namespace Todo_Xamarin_Forms
{
	public partial class Todo_Xamarin_FormsPage : ContentPage
	{

		public Todo_Xamarin_FormsPage()
		{
			InitializeComponent();
		}

		void Submit_Clicked(object sender, System.EventArgs e)
		{
			LblName.Text = "Hello, " + TxtUserName.Text + "!";
		}
	}
}

Adding Preference

Add Xam.Plugins.Settings package in all 3 projects (Forms, Android, iOS)

After adding the package change in Helpers -> Settings.cs of Forms module

// Helpers/Settings.cs

using Plugin.Settings;
using Plugin.Settings.Abstractions;

namespace Todo_Xamarin_Forms.Helpers
{
	///
<summary>
	/// This is the Settings static class that can be used in your Core solution or in any
	/// of your client applications. All settings are laid out the same exact way with getters
	/// and setters.
	/// </summary>

	public static class Settings
	{
		private static ISettings AppSettings
		{
			get { return CrossSettings.Current; }
		}

		#region Setting Constants

		private const string SettingsKey = "settings_key";
		private static readonly string SettingsDefault = string.Empty;

		private const string UserNameKey = "uname_key";
		private static readonly string UserNameDefault = string.Empty;

		#endregion

		public static string GeneralSettings
		{
			get { return AppSettings.GetValueOrDefault<string>(SettingsKey, SettingsDefault); }
			set { AppSettings.AddOrUpdateValue<string>(SettingsKey, value); }
		}

		public static string UserName
		{
			get { return AppSettings.GetValueOrDefault<string>(UserNameKey, UserNameDefault); }
			set { AppSettings.AddOrUpdateValue<string>(UserNameKey, value); }
		}
	}
}
public partial class Todo_Xamarin_FormsPage : ContentPage
	{

		public Todo_Xamarin_FormsPage()
		{
			InitializeComponent();

			TxtUserName.Text = Settings.UserName;
		}

		void Submit_Clicked(object sender, System.EventArgs e)
		{
			var name = TxtUserName.Text;

			if (!string.IsNullOrWhiteSpace(name))
			{
				Settings.UserName = name;
			}
			else
			{
				DisplayAlert("Error", "Pleaes enter your user name", "OK");
			}

			LblName.Text = "Hello, " + name + "!";
		}
	}

Add a ListView

Create a new ListPage

<?xml version="1.0" encoding="UTF-8"?>

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"              x:Class="Todo_Xamarin_Forms.LIstPage" Title="Saved Items">
    <ContentPage.Content>
        <ListView x:Name="ListView" ItemSelected="ListView_OnItemSelected" RowHeight="80">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <AbsoluteLayout IsClippedToBounds="True" LayoutBounds="1,1,1,1" LayoutFlags="All">
                            <Image Source="bg_img.png" Aspect="Fill" />
                            <StackLayout Padding="10, 10, 0, 0" HorizontalOptions="StartAndExpand"                                          Orientation="Vertical">
                                <Label Text="{Binding title}" HorizontalOptions="Start" FontSize="Medium"                                        TextColor="Blue" />
                                <Label Text="{Binding description}" FontSize="Small" TextColor="Green" />
                            </StackLayout>
                        </AbsoluteLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </ContentPage.Content>
</ContentPage>
using System;
using System.Collections.Generic;

using Xamarin.Forms;

namespace Todo_Xamarin_Forms
{
	public partial class LIstPage : ContentPage
	{
		public LIstPage()
		{
			InitializeComponent();
		}

	    private void ListView_OnItemSelected(object sender, SelectedItemChangedEventArgs e)
	    {

	    }
	}
}

Add NagivationPage

		public App()
		{
			InitializeComponent();

			MainPage = new NavigationPage(new Todo_Xamarin_FormsPage())
			{
				BarTextColor = Color.White,
				BarBackgroundColor = Color.Blue
			};
		}

Add SQLite Database

Add library sqlite-net-pcl

Get platform specific DB connection

using SQLite;

namespace Todo_Xamarin_Forms
{
    public interface ISQLite
    {
        SQLiteConnection GetConnection();
    }
}

Android Implementation

using System;
using System.IO;
using SQLite;
using Todo_Xamarin_Forms.Droid;
using Xamarin.Forms;

[assembly: Dependency(typeof(SQLite_Android))]
namespace Todo_Xamarin_Forms.Droid
{
	public class SQLite_Android : ISQLite
	{
		public SQLite_Android()
		{

		}

		#region ISQLite implementation 

		public SQLiteConnection GetConnection()
		{
			var dbFile = "database.db3";
			var privatePath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
			var path = Path.Combine(privatePath, dbFile);
			var connection = new SQLite.SQLiteConnection(path, true);
			return connection;
		}

		#endregion
	}
}

iOS Implementation

using System;
using System.IO;
using SQLite;
using Xamarin.Forms;
using Todo_Xamarin_Forms.iOS;

[assembly: Dependency(typeof(SQLite_iOS))]
namespace Todo_Xamarin_Forms.iOS
{
	public class SQLite_iOS : ISQLite
	{
		public SQLite_iOS()
		{
		}

		#region ISQLite implementation 

		public SQLiteConnection GetConnection()
		{
			var dbFile = "database.db3";
			var privatePath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
			var libPath = Path.Combine(privatePath, "..", "Library");
			var path = Path.Combine(libPath, dbFile);
			var connection = new SQLite.SQLiteConnection(path, true);
			return connection;
		}

		#endregion
	}
}

Model class

using System;
using SQLite;

namespace Todo_Xamarin_Forms
{
	public class ListItemModel
	{
		[PrimaryKey, AutoIncrement]
		public int ID { get; set; }

		public string title { get; set; }
		public string description { get; set; }
	}
}

Database

using System;
using SQLite;
using Xamarin.Forms;
using System.Collections.Generic;
using System.Linq;

namespace Todo_Xamarin_Forms
{
	public class Database
	{

		private SQLiteConnection _connection;

		public Database()
		{
			_connection = DependencyService.Get<ISQLite>().GetConnection();
			_connection.CreateTable<ListItemModel>();
		}

		public List<ListItemModel> GetListItems()
		{
			return (from item in _connection.Table<ListItemModel>() select item).ToList();
		}

		public void AddItem(ListItemModel item)
		{
			_connection.Insert(item);
		}

		public void AddItems(List<ListItemModel> items)
		{
			foreach (var item in items)
				AddItem(item);
		}

		public void EditItem(ListItemModel item)
		{
			_connection.Update(item);
		}
	}
}

Load Items from Database

using System;
using System.Collections;
using System.Collections.Generic;

using Xamarin.Forms;

namespace Todo_Xamarin_Forms
{
	public partial class ListPage : ContentPage
	{
		public ListPage()
		{
			InitializeComponent();
		    CheckDatabasePopulated();
		    ListView.ItemsSource = GetItems();
		}

	    List<ListItemModel> GetItems()
	    {
	        var items = new Database().GetListItems();
	        return items;
	    }

	    private void CheckDatabasePopulated()
	    {
	        if (new Database().GetListItems().Count < 1)
	        {
	            var items = new List<ListItemModel>();

	            for (int i = 0; i < 10; i++)
	            {
	                items.Add(new ListItemModel()
	                {
                        title = "Item title" + (i + 1).ToString(),
	                    description = "Description - " + (i + 1).ToString()
	                });
	            }

	            new Database().AddItems(items);
	        }
	    }

	    private void ListView_OnItemSelected(object sender, SelectedItemChangedEventArgs e)
	    {

	    }
	}
}

Item Edit Page

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Todo_Xamarin_Forms.ItemEditPage" xmlns:locale="clr-namespace:Todo_Xamarin_Forms:assembly=Todo_Xamarin_Forms" Title="Edit page">
	<ContentPage.Content>
		<StackLayout HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand" Orientation="Horizontal">
			<Entry Text="{Binding title, Mode=TwoWay}" HorizontalOptions="CenterAndExpand" />
			<Entry Text="{Binding description, Mode=TwoWay}" HorizontalOptions="CenterAndExpand" />
			<Button Text="Save" Clicked="Save_Clicked" />
		</StackLayout>
	</ContentPage.Content>
</ContentPage>
using System;
using System.Collections.Generic;
using System.ComponentModel;

using Xamarin.Forms;

namespace Todo_Xamarin_Forms
{
	public partial class ItemEditPage : ContentPage
	{
		public ListItemModel Model
		{
			get { return (ListItemModel)BindingContext; }
			set
			{
				BindingContext = value;
				OnPropertyChanged();
			}
		}

		public ItemEditPage(ListItemModel item)
		{
			Model = item;

			InitializeComponent();
		}

		void Save_Clicked(object sender, System.EventArgs e)
		{
			if (string.IsNullOrEmpty(Model.title)) return;

			new Database().EditItem(Model);
			Navigation.PopAsync();
		}
	}
}

Updates ListPage

public partial class ListPage : ContentPage
	{
		public ListPage()
		{
			InitializeComponent();
			CheckDatabasePopulated();
		}

		protected override void OnAppearing()
		{
			base.OnAppearing();
			ListView.ItemsSource = GetItems();
		}

		List<ListItemModel> GetItems()
		{
			var items = new Database().GetListItems();
			return items;
		}

		private void CheckDatabasePopulated()
		{
			if (new Database().GetListItems().Count < 1)
			{
				var items = new List<ListItemModel>();

				for (int i = 0; i < 10; i++)
				{
					items.Add(new ListItemModel()
					{
						title = "Item title" + (i + 1).ToString(),
						description = "Description - " + (i + 1).ToString()
					});
				}

				new Database().AddItems(items);
			}
		}

		private void ListView_OnItemSelected(object sender, SelectedItemChangedEventArgs e)
		{
			if (e.SelectedItem == null) return;

			((ListView)sender).SelectedItem = null;

			Navigation.PushAsync(new ItemEditPage((ListItemModel)e.SelectedItem));
		}
	}

Custom Button

using System;
using Xamarin.Forms;

namespace XamarinFormsFirstLook
{
	public class GLabButton : Button
	{
		public GLabButton()
		{
		}
	}
}
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage 	xmlns="http://xamarin.com/schemas/2014/forms" 	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 	x:Class="XamarinFormsFirstLook.CustomButton" 	xmlns:local="clr-namespace:XamarinFormsFirstLook;assembly=XamarinFormsFirstLook">
	<ContentPage.Content>
		<StackLayout Padding="16">
               <Entry Placeholder="Enter your name"/>
            <local:GLabButton Text="Click me!" TextColor="Navy" FontSize="16" Clicked="OnClickHandler"/>
		</StackLayout>
	</ContentPage.Content>
</ContentPage>

using System;
using System.Collections.Generic;

using Xamarin.Forms;

namespace XamarinFormsFirstLook
{
	public partial class CustomButton : ContentPage
	{
		public CustomButton()
		{
			InitializeComponent();
		}

	    private void OnClickHandler(object sender, EventArgs e)
	    {
	        DisplayAlert("Hello", "Nice Button", "OK");
	    }
	}
}

Inside the iOS project create the renderer file

using System.Reflection;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using XamarinFormsFirstLook;
using XamarinFormsFirstLook.iOS;

[assembly:ExportRendererAttribute(typeof(GLabButton), typeof(GLabButtonRenderer))]

namespace XamarinFormsFirstLook.iOS
{
    public class GLabButtonRenderer : ButtonRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
        {
            base.OnElementChanged(e);
            if (Control != null)
            {
                Control.BackgroundColor = UIColor.Red;
            }
        }
    }
}

Run the project in iOS and see the custom effect (Background color red)
Run the same project in Android and see a regular button instead of this effect.

Custom BoxView

using System;

using Xamarin.Forms;

namespace XamarinFormsFirstLook
{
	public class GLabBoxView : BoxView
	{
		public static readonly BindableProperty BorderColorProperty = BindableProperty.Create<GLabBoxView, Color>(
		    p => p.BorderColor, default(Color)
		);

	    public Color BorderColor
	    {
	        get { return (Color) GetValue(BorderColorProperty); }
	        set { SetValue(BorderColorProperty, value);}
	    }

	    public static readonly BindableProperty BorderThicknessProperty = BindableProperty.Create<GLabBoxView, double>(
	        p => p.BorderThickness, default(double)
	    );

	    public double BorderThickness
	    {
	        get { return (double) GetValue(BorderThicknessProperty); }
	        set { SetValue(BorderThicknessProperty, value);}
	    }
	}
}

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage 	xmlns="http://xamarin.com/schemas/2014/forms" 	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 	x:Class="XamarinFormsFirstLook.CustomBoxView" 	xmlns:local="clr-namespace:XamarinFormsFirstLook;assembly=XamarinFormsFirstLook">
	<ContentPage.Content>
		<StackLayout 			Padding="16">
			<local:GLabBoxView 				WidthRequest="160" 				HeightRequest="160" 				Color="Accent" 				BorderColor="Green" 				BindingContext="{x:Reference Name=SliderThickNess}" 				BorderThickness="{Binding Path=Value}" />
			<Label 				BindingContext="{x:Reference Name=SliderThickNess}" 				Text="{Binding Path=Value}" />
			<Slider 				x:Name="SliderThickNess" 				Minimum="0" 				Maximum="30" />
		</StackLayout>
	</ContentPage.Content>
</ContentPage>

Custom renderer in iOS

using Xamarin.Forms.Platform.iOS;
using UIKit;
using System.ComponentModel;
using CoreGraphics;
using Xamarin.Forms;
using XamarinFormsFirstLook;
using XamarinFormsFirstLook.iOS;

[assembly:ExportRendererAttribute(typeof(GLabBoxView), typeof(GLabBoxViewRenderer))]

namespace XamarinFormsFirstLook.iOS
{
    public class GLabBoxViewRenderer : BoxRenderer
    {
        public override void Draw(CGRect rect)
        {
            GLabBoxView boxView = (GLabBoxView) Element;
            using (var context = UIGraphics.GetCurrentContext())
            {
                context.SetFillColor(boxView.Color.ToCGColor());
                context.SetStrokeColor(boxView.BorderColor.ToCGColor());
                context.SetLineWidth((float) boxView.BorderThickness);

                var rectangle = Bounds.Inset((int) boxView.BorderThickness, (int) boxView.BorderThickness);

                var path = CGPath.FromRect(rectangle);
                context.AddPath(path);
                context.DrawPath((CGPathDrawingMode.FillStroke));
            }
        }

        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == GLabBoxView.BorderThicknessProperty.PropertyName)
            {
                SetNeedsDisplay();
            }
        }
    }
}

Custom renderer in Android

using System.ComponentModel;
using Android.Graphics;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using XamarinFormsFirstLook;
using XamarinFormsFirstLook.Droid;

[assembly:ExportRendererAttribute(typeof(GLabBoxView), typeof(GLabBoxViewRenderer))]

namespace XamarinFormsFirstLook.Droid
{
    public class GLabBoxViewRenderer : BoxRenderer
    {
        public GLabBoxViewRenderer()
        {
            SetWillNotDraw(false);
        }

        public override void Draw(Android.Graphics.Canvas canvas)
        {
            base.Draw(canvas);

            GLabBoxView boxView = (GLabBoxView) Element;

            Rect rect = new Rect();
            GetDrawingRect(rect);

            Rect inside = rect;
            inside.Inset(
                (int) boxView.BorderThickness,
                (int) boxView.BorderThickness
            );

            Paint p = new Paint();
            p.Color = boxView.Color.ToAndroid();

            canvas.DrawRect(inside, p);

            p.Color = boxView.BorderColor.ToAndroid();
            p.StrokeWidth = (float) boxView.BorderThickness;
            p.SetStyle(Paint.Style.FillAndStroke);

            canvas.DrawRect(rect, p);
        }

        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);
            Invalidate();
        }
    }
}

Custom markup extension

using System;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace XamarinFormsFirstLook.Extension
{
    public class RGBExtension : IMarkupExtension
    {
        public int Red { get; set; }
        public int Green { get; set; }
        public int Blue { get; set; }

        public object ProvideValue(IServiceProvider serviceProvider)
        {
            return Color.FromRgb(Red, Green, Blue);
        }
    }
}

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage 	xmlns="http://xamarin.com/schemas/2014/forms" 	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 	x:Class="XamarinFormsFirstLook.CustomMarkup" 	xmlns:local="clr-namespace:XamarinFormsFirstLook.Extension;assembly=XamarinFormsFirstLook">
	<ContentPage.Content>
		<StackLayout 			Padding="16">
			<Label 				Text="Hello World" 				FontSize="30" 				TextColor="{local:RGBExtension Red=105, Green=205, Blue=180}" />
			<Label 				Text="Hello Xamarin" 				FontSize="36" 				TextColor="{local:RGBExtension Red=150, Green=250, Blue=0}" 				BackgroundColor="{local:RGBExtension Red=50, Green=60, Blue=70}" />
		</StackLayout>
	</ContentPage.Content>
</ContentPage>

Platform Service

using System;

namespace XamarinFormsFirstLook.Extension
{
    public interface ITwitter
    {
        void SendTweet(String msg);
    }
}

Write the service in iOS

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage 	xmlns="http://xamarin.com/schemas/2014/forms" 	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 	x:Class="XamarinFormsFirstLook.PlatformService">
	<ContentPage.Content>
        <Button Text="Twitter" Clicked="onClickTwitter"></Button>
	</ContentPage.Content>
</ContentPage>

using System;
using System.Collections.Generic;

using Xamarin.Forms;
using XamarinFormsFirstLook.Extension;

namespace XamarinFormsFirstLook
{
	public partial class PlatformService : ContentPage
	{
		public PlatformService()
		{
			InitializeComponent();
		}

	    private void onClickTwitter(object sender, EventArgs e)
	    {
                DependencyService.Get<ITwitter>().SendTweet("Hello world!!");
	    }
	}
}

List View (Once again)

using System;

namespace XamarinFormsFirstLook.Model
{
    public class Contact
    {
        public string FirstName { get; set; }

        public string LastName { get; set; }

        public string Email { get; set; }

        public Boolean IsFavorite { get; set; }
    }
}
using System;
using System.Collections.Generic;

using XamarinFormsFirstLook.Model;

namespace XamarinFormsFirstLook.Data
{
    public class DataGenerator
    {
        private static List<string> FirstNames = new List<string> {
            "Aiden", "Liam", "Lucas", "Noah", "Mason", "Ethan", "Caden", "Jacob", "Logan", "Jayden", "Elijah", "Jack", "Luke", "Michael", "Benjamin",
            "Alexander", "James", "Jayce", "Caleb", "Connor", "William", "Carter", "Ryan", "Oliver", "Matthew", "Daniel", "Gabriel", "Henry", "Owen",
            "Grayson", "Lincoln", "Jordan", "Tristan", "Jason", "Josiah", "Xavier", "Camden", "Chase", "Declan", "Carson", "Colin", "Brody", "Asher",
            "Jeremiah", "Micah", "Easton", "Xander", "Ryder", "Nathaniel", "Elliot", "Sean"
        };

        private static List<string> LastNames = new List<string> {
            "SMITH", "JOHNSON", "WILLIAMS", "BROWN", "JONES", "MILLER", "DAVIS", "GARCIA", "RODRIGUEZ", "WILSON", "MARTINEZ", "ANDERSON", "TAYLOR", "THOMAS HERNANDEZ",
            "RICHARDSON", "WOOD", "WATSON", "BROOKS", "BENNETT GRAY", "JAMES", "REYES", "CRUZ", "HUGHES", "PRICE", "MYERS", "LONG", "FOSTER SANDERS", "ROSS",
            "MORALES", "POWELL", "SULLIVAN", "RUSSELL ORTIZ", "JENKINS", "GUTIERREZ", "PERRY", "BUTLER", "BARNES FISHER", "HENDERSON", "COLEMAN", "SIMMONS", "PATTERSON",
            "JORDAN", "REYNOLDS"
        };

        public static List<Contact> GetContacts() {

            var random = new Random();
            List<Contact> contacts = new List<Contact>();

            for (int i = 0; i < 20; i++) {
                Contact contact = new Contact();
                contact.FirstName = FirstNames [i];
                contact.LastName = LastNames [i];
                contact.Email = FirstNames [i] + "@gmail.com";
                contact.IsFavorite = random.Next(FirstNames.Count) % 2 == 0;
                contacts.Add(contact);
            }
            return  contacts;
        }
    }
}
<?xml version="1.0" encoding="UTF-8"?>

<ContentPage
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    x:Class="XamarinFormsFirstLook.ListPage2">
    <ContentPage.Content>
        <StackLayout Padding="40">
            <Label Text="Contacts" FontSize="20" />
            <ListView x:Name="ContactList" ItemsSource="{Binding Contacts}" ItemTapped="OnItemTapped">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <ViewCell>
                            <ViewCell.View>
                                <StackLayout Padding="10">
                                    <StackLayout Orientation="Horizontal">
                                        <Label Text="{Binding FirstName}" FontSize="14" FontAttributes="Bold"
                                               TextColor="Blue" />
                                        <Label Text="{Binding LastName}" FontSize="14" FontAttributes="Bold"
                                               TextColor="Blue" />
                                    </StackLayout>
                                    <StackLayout Orientation="Horizontal">
                                        <Label Text="{Binding Email}" FontSize="10" />
                                    </StackLayout>
                                </StackLayout>
                            </ViewCell.View>
                        </ViewCell>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using Xamarin.Forms;
using XamarinFormsFirstLook.Data;
using XamarinFormsFirstLook.Model;

namespace XamarinFormsFirstLook
{
	public partial class ListPage2 : ContentPage
	{
	    public List<Contact> Contacts { get; set; }
	    
	    public ListPage2()
	    {
	        Init();
		}

	    private void Init()
	    {
            Contacts = DataGenerator.GetContacts();
            BindingContext = this;
            InitializeComponent();
	    }

	    private void OnItemTapped(object sender, ItemTappedEventArgs e)
	    {
            var contact = e.Item as Contact;
			DisplayAlert("Great!", contact.FirstName + " " + contact.LastName, "OK");
	    }
	}
}

List View (Grouping)

using System.Collections.Generic;
using System.Collections.ObjectModel;

namespace XamarinFormsFirstLook.Model
{
    public class Grouping<K, T> : ObservableCollection<T> {
        public K Key { get; private set; }

        public Grouping(K key, IEnumerable<T> items) {
            Key = key;
            foreach (var item in items)
                Items.Add(item);
        }
    }
}
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using XamarinFormsFirstLook.Model;

namespace XamarinFormsFirstLook.Data
{
    public class DataGenerator
    {
        private static List<string> FirstNames = new List<string> {
            "Aiden", "Liam", "Lucas", "Noah", "Mason", "Ethan", "Caden", "Jacob", "Logan", "Jayden", "Elijah", "Jack", "Luke", "Michael", "Benjamin",
            "Alexander", "James", "Jayce", "Caleb", "Connor", "William", "Carter", "Ryan", "Oliver", "Matthew", "Daniel", "Gabriel", "Henry", "Owen",
            "Grayson", "Lincoln", "Jordan", "Tristan", "Jason", "Josiah", "Xavier", "Camden", "Chase", "Declan", "Carson", "Colin", "Brody", "Asher",
            "Jeremiah", "Micah", "Easton", "Xander", "Ryder", "Nathaniel", "Elliot", "Sean"
        };

        private static List<string> LastNames = new List<string> {
            "SMITH", "JOHNSON", "WILLIAMS", "BROWN", "JONES", "MILLER", "DAVIS", "GARCIA", "RODRIGUEZ", "WILSON", "MARTINEZ", "ANDERSON", "TAYLOR", "THOMAS HERNANDEZ",
            "RICHARDSON", "WOOD", "WATSON", "BROOKS", "BENNETT GRAY", "JAMES", "REYES", "CRUZ", "HUGHES", "PRICE", "MYERS", "LONG", "FOSTER SANDERS", "ROSS",
            "MORALES", "POWELL", "SULLIVAN", "RUSSELL ORTIZ", "JENKINS", "GUTIERREZ", "PERRY", "BUTLER", "BARNES FISHER", "HENDERSON", "COLEMAN", "SIMMONS", "PATTERSON",
            "JORDAN", "REYNOLDS"
        };

        public static List<Contact> GetContacts() {

            var random = new Random();
            List<Contact> contacts = new List<Contact>();

            for (int i = 0; i < 25; i++) {
                Contact contact = new Contact();
                contact.FirstName = FirstNames [i];
                contact.LastName = LastNames [i];
                contact.Email = FirstNames [i] + "@gmail.com";
                contact.IsFavorite = random.Next(FirstNames.Count) % 2 == 0;
                contacts.Add(contact);
            }
            return  contacts;
        }

        public static ObservableCollection<Contact> GetObservableContacts() {

            var random = new Random();
            var contacts = new ObservableCollection<Contact>();

            for (int i = 0; i < 25; i++) {
                Contact contact = new Contact();
                contact.FirstName = FirstNames [i];
                contact.LastName = LastNames [i];
                contact.Email = FirstNames [i] + "@gmail.com";
                contact.IsFavorite = random.Next(FirstNames.Count) % 2 == 0;
                contacts.Add(contact);
            }
            return  contacts;
        }
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage
	xmlns="http://xamarin.com/schemas/2014/forms"
	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
	x:Class="XamarinFormsFirstLook.ListPage3">
    <ContentPage.Content>
        <StackLayout
            Padding="40">
            <ListView
                x:Name="ContactList"
                ItemsSource="{Binding .}"
                ItemTapped="OnItemTapped"
                IsGroupingEnabled="true"
                GroupShortNameBinding="{Binding Key}"
                HasUnevenRows="true">
                <ListView.GroupHeaderTemplate>
                    <DataTemplate>
                        <ViewCell
                            Height="30">
                            <StackLayout
                                VerticalOptions="FillAndExpand"
                                Padding="10"
                                BackgroundColor="Blue">
                                <Label
                                    Text="{Binding Key}"
                                    TextColor="White"
                                    VerticalOptions="Center" />
                            </StackLayout>
                        </ViewCell>
                    </DataTemplate>
                </ListView.GroupHeaderTemplate>
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <ViewCell>
                            <ViewCell.View>
                                <StackLayout
                                    Padding="10">
                                    <StackLayout
                                        Orientation="Horizontal">
                                        <Label
                                            Text="{Binding FirstName}"
                                            FontSize="14"
                                            TextColor="Red" />
                                        <Label
                                            Text="{Binding LastName}"
                                            FontSize="14"
                                            TextColor="Red" />
                                    </StackLayout>
                                    <Label
                                        Text="{Binding Email}"
                                        FontSize="10" />
                                </StackLayout>
                            </ViewCell.View>
                        </ViewCell>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Xamarin.Forms;
using XamarinFormsFirstLook.Data;
using XamarinFormsFirstLook.Model;

namespace XamarinFormsFirstLook
{
	public partial class ListPage3 : ContentPage
	{
	    public ObservableCollection<Grouping<string,Contact>> ContactGroup;

	    public ListPage3() {
	        Init();
	        BindingContext = ContactGroup;
	        InitializeComponent();
	    }

	    private void Init()
	    {
	        var listOfContacts = DataGenerator.GetObservableContacts();

	        var sorted =
	            from c in listOfContacts
	            orderby c.FirstName
	            group c by c.FirstName[0].ToString()
	            into theGroup
	            select new Grouping<string, Contact>(theGroup.Key, theGroup);

	        ContactGroup = new ObservableCollection<Grouping<string,Contact>>(sorted);
	    }

	    private void OnItemTapped(object sender, ItemTappedEventArgs e)
	    {
	        var contact = e.Item as Contact;
	        DisplayAlert("Great!", contact.FirstName + " " + contact.LastName, "OK");
	    }
	}
}

List View (Item Trigger)

<?xml version="1.0" encoding="UTF-8"?>

<ContentPage
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    x:Class="XamarinFormsFirstLook.ListPage4">
    <ContentPage.Content>
        <StackLayout
            Padding="40">
            <Label
                Text="Contacts"
                FontSize="20" />
            <ListView
                x:Name="ContactList"
                ItemsSource="{Binding Contacts}"
                ItemTapped="OnItemTapped">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <ViewCell>
                            <ViewCell.View>
                                <StackLayout
                                    Padding="10">
                                    <StackLayout
                                        Orientation="Horizontal">
                                        <Label
                                            Text="{Binding FirstName}"
                                            FontSize="14"
                                            FontAttributes="Bold"
                                            TextColor="Blue">
                                            <Label.Triggers>
                                                <DataTrigger
                                                    TargetType="Label"
                                                    Binding="{Binding IsFavorite}"
                                                    Value="True">
                                                    <Setter
                                                        Property="TextColor"
                                                        Value="Red" />
                                                </DataTrigger>
                                            </Label.Triggers>
                                        </Label>
                                        <Label
                                            Text="{Binding LastName}"
                                            FontSize="14"
                                            FontAttributes="Bold"
                                            TextColor="Blue">
                                            <Label.Triggers>
                                                <DataTrigger
                                                    TargetType="Label"
                                                    Binding="{Binding IsFavorite}"
                                                    Value="True">
                                                    <Setter
                                                        Property="TextColor"
                                                        Value="Red" />
                                                </DataTrigger>
                                            </Label.Triggers>
                                        </Label>
                                    </StackLayout>
                                    <StackLayout
                                        Orientation="Horizontal">
                                        <Label
                                            Text="{Binding Email}"
                                            FontSize="10" />
                                    </StackLayout>
                                </StackLayout>
                            </ViewCell.View>
                        </ViewCell>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>
using System.Collections.Generic;
using XamarinFormsFirstLook.Data;
using XamarinFormsFirstLook.Model;

namespace XamarinFormsFirstLook
{
    public class ListPage4ViewModel
    {
        public List<Contact> Contacts { get; set; }

        public ListPage4ViewModel()
        {
            Contacts = new List<Contact>();
            var listOfContacts = DataGenerator.GetContacts();
            Contacts = listOfContacts;

        }
    }
}
using System.Collections.Generic;
using XamarinFormsFirstLook.Data;
using XamarinFormsFirstLook.Model;

namespace XamarinFormsFirstLook
{
    public class ListPage4ViewModel
    {
        public List<Contact> Contacts { get; set; }

        public ListPage4ViewModel()
        {
            Contacts = new List<Contact>();
            var listOfContacts = DataGenerator.GetContacts();
            Contacts = listOfContacts;

        }
    }
}

Rest service

Package: Microsoft.Net.Http
Newtonsoft.Json

using System;

namespace XamarinFormsFirstLook.Model
{
    public class WeatherObservation
    {
        public string weatherCondition { get; set; }

        public string ICAO { get; set; }

        public long elevation { get; set; }

        public string countryCode { get; set; }

        public string cloudCode { get; set; }

        public long lng { get; set; }

        public long temperature { get; set; }

        public long dewPoint { get; set; }

        public long windSpeed { get; set; }

        public long humidity { get; set; }

        public string stationName { get; set; }

        public DateTime dateTime { get; set; }

        public long lat { get; set; }

        public long hectoPascAltimeter { get; set; }
    }
}
namespace XamarinFormsFirstLook.Model
{
    public class WeatherResult
    {
        public WeatherObservation weatherObservation { get; set; }
    }
}
using System;
using System.ComponentModel;
using System.Net.Http;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using Newtonsoft.Json;
using XamarinFormsFirstLook.Model;

namespace XamarinFormsFirstLook
{
    public class RESTViewModel : INotifyPropertyChanged
    {
        private string station;

        public string StationName {
            get { return station; }
            set {
                station = value;
                NotifyPropertyChanged();
            }
        }

        private long el;

        public long Elevation {
            get { return el; }
            set {
                el = value;
                NotifyPropertyChanged();
            }
        }

        private long temp;

        public long Temperature {
            get { return temp; }
            set {
                temp = value;
                NotifyPropertyChanged();
            }
        }

        private long humid;

        public long Humidity {
            get { return humid; }
            set {
                humid = value;
                NotifyPropertyChanged();
            }
        }

        public async Task GetWeatherAsync(string url) {
            HttpClient client = new HttpClient();
            client.BaseAddress = new Uri(url);
            var response = await client.GetAsync(client.BaseAddress);
            response.EnsureSuccessStatusCode();
            var JsonResult = response.Content.ReadAsStringAsync().Result;
            var weather =
                JsonConvert.DeserializeObject<WeatherResult>(JsonResult);
            SetValues(weather);
        }

        private void SetValues(WeatherResult weather) {
            var stationName = weather.weatherObservation.stationName;
            var elevation = weather.weatherObservation.elevation;
            var temperature = weather.weatherObservation.temperature;
            var humidity = weather.weatherObservation.humidity;

            StationName = stationName;
            Elevation = elevation;
            Temperature = temperature;
            Humidity = humidity;
        }



        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged([CallerMemberName] string propertyName = "") {
            if (PropertyChanged != null) {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage
	xmlns="http://xamarin.com/schemas/2014/forms"
	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
	x:Class="XamarinFormsFirstLook.RESTPage">
    <ContentPage.Content>
        <StackLayout
            Padding="30">
            <StackLayout
                Orientation="Horizontal">
                <Label
                    Text="Latitude"
                    WidthRequest="130" />
                <Entry
                    x:Name="Lat"
                    WidthRequest="150" />
            </StackLayout>
            <StackLayout
                Orientation="Horizontal">
                <Label
                    Text="Longitude"
                    WidthRequest="130" />
                <Entry
                    x:Name="Lon"
                    WidthRequest="150" />
            </StackLayout>
            <Button
                x:Name="Search"
                Clicked="OnClicked"
                WidthRequest="75"
                Text="Search"
                TextColor="White"
                BackgroundColor="Blue" />
            <StackLayout
                Orientation="Horizontal">
                <Label
                    Text="Location: "
                    TextColor="Green"
                    WidthRequest="130" />
                <Label
                    Text="{Binding StationName}" />
            </StackLayout>
            <StackLayout
                Orientation="Horizontal">
                <Label
                    Text="Elevation: "
                    TextColor="Green"
                    WidthRequest="130" />
                <Label
                    Text="{Binding Elevation}" />
            </StackLayout>
            <StackLayout
                Orientation="Horizontal">
                <Label
                    Text="Temperature: "
                    TextColor="Green"
                    WidthRequest="130" />
                <Label
                    Text="{Binding Temperature}" />
            </StackLayout>
            <StackLayout
                Orientation="Horizontal">
                <Label
                    Text="Humidity: "
                    TextColor="Green"
                    WidthRequest="130" />
                <Label
                    Text="{Binding Humidity}" />
            </StackLayout>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

using System;
using System.Collections.Generic;

using Xamarin.Forms;

namespace XamarinFormsFirstLook
{
	public partial class RESTPage : ContentPage
	{
	    RESTViewModel vm;

	    public RESTPage() {
	        vm = new RESTViewModel();
	        BindingContext = vm;
	        InitializeComponent();
		}

	    private async void OnClicked(object sender, EventArgs e)
	    {
	        var longitude = double.Parse(Lon.Text);
	        var latitude = double.Parse(Lat.Text);

	        var url = string.Format("http://api.geonames.org/findNearByWeatherJSON?lat={0}&lng={1}&username=tausiq", latitude, longitude);
	        await vm.GetWeatherAsync(url);
	    }
	}
}

SQLite database

Make sure you have package: sqlite-net-pcl in all projects

using System.Collections.Generic;
using System.Linq;
using SQLite;
using Xamarin.Forms;
using XamarinFormsFirstLook.Model;

namespace XamarinFormsFirstLook.Data
{
    public class ContactDatabase
    {
        SQLiteConnection database;
        static object locker = new object();

        public ContactDatabase() {


            database = DependencyService.Get<ISQLite>().GetConnection();

            database.CreateTable<Contact>();

        }

        public int SaveContact(Contact contact) {
            lock (locker) {
                if (contact.ID != 0) {
                    database.Update(contact);
                    return contact.ID;
                } else {
                    return database.Insert(contact);
                }
            }
        }

        public IEnumerable<Contact> GetContacts() {
            lock (locker) {
                return (from c in database.Table<Contact>()
                    select c).ToList();
            }
        }

        public Contact GetContect(int id) {
            lock (locker) {
                return database.Table<Contact>().Where(c => c.ID == id).FirstOrDefault();
            }
        }

        public int DeleteContact(int id) {
            lock (locker) {
                return database.Delete<Contact>(id);
            }
        }
    }
}
using Xamarin.Forms;
using XamarinFormsFirstLook.Data;

namespace XamarinFormsFirstLook
{
	public partial class App : Application
	{
		public App()
		{
			InitializeComponent();

			MainPage = new NavigationPage(new XamarinFormsFirstLookPage());
		}

	    static ContactDatabase database;

	    public static ContactDatabase Database {
	        get {
	            if (database == null) {
	                database = new ContactDatabase();
	            }
	            return database;
	        }
	    }

	    protected override void OnStart()
		{
			// Handle when your app starts
		}

		protected override void OnSleep()
		{
			// Handle when your app sleeps
		}

		protected override void OnResume()
		{
			// Handle when your app resumes
		}
	}
}

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage
	xmlns="http://xamarin.com/schemas/2014/forms"
	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
	x:Class="XamarinFormsFirstLook.ContactEntryPage">
    <ContentPage.Content>
        <StackLayout
            Padding="40">
            <Entry
                x:Name="FirstName"
                Placeholder="First Name" />
            <Entry
                x:Name="LastName"
                Placeholder="Last Name" />
            <Entry
                x:Name="Email"
                Placeholder="Email" />
            <StackLayout
                Orientation="Horizontal">
                <Label
                    Text="Favorite?" />
                <Switch
                    x:Name="IsFavorite" />
            </StackLayout>
            <StackLayout
                Orientation="Horizontal">
                <Button
                    x:Name="Save"
                    Text="Save"
                    Clicked="OnSave" />
                <Button
                    x:Name="Cancel"
                    Text="Cancel"
                    Clicked="OnCancel" />
                <Button
                    x:Name="Review"
                    Text="Review"
                    Clicked="OnReview" />
            </StackLayout>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

using System;
using System.Collections.Generic;

using Xamarin.Forms;
using XamarinFormsFirstLook.Model;

namespace XamarinFormsFirstLook
{
	public partial class ContactEntryPage : ContentPage
	{
	    private int updateID = 0;

	    public ContactEntryPage() {
			InitializeComponent();
		}

	    public ContactEntryPage(int id)
	    {
	        InitializeComponent();
	        var contact = App.Database.GetContect(id);
	        FirstName.Text = contact.FirstName;
	        LastName.Text = contact.LastName;
	        Email.Text = contact.Email;
	        IsFavorite.IsToggled = contact.IsFavorite;
	        updateID = id;
	    }

	    public void OnSave(object o, EventArgs e) {
	        Contact contact = new Contact();
	        contact.FirstName = FirstName.Text;
	        contact.LastName = LastName.Text;
	        contact.Email = Email.Text;
	        contact.IsFavorite = IsFavorite.IsToggled;
	        contact.ID = updateID;
	        Clear();
	        App.Database.SaveContact(contact);
	        Navigation.PopAsync(true);
	    }

	    private void OnCancel(object o, EventArgs e) {
	        Clear();
	    }

	    private void OnReview(object o, EventArgs e) {
	        Navigation.PopAsync(true);
	    }

	    private void Clear() {
	        FirstName.Text = LastName.Text = Email.Text = string.Empty;
	        IsFavorite.IsToggled = false;
	    }
	}
}

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage
	xmlns="http://xamarin.com/schemas/2014/forms"
	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
	x:Class="XamarinFormsFirstLook.ContactListPage">
    <ContentPage.Content>
        <StackLayout
            Padding="40">
            <Label
                Text="Contacts"
                FontSize="20" />
            <Button Text="New Entry" Clicked="OnNewEntry" />
            <ListView
                x:Name="ContactList"
                ItemTapped="OnItemTapped">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <ViewCell>
                            <ViewCell.View>
                                <StackLayout
                                    Padding="10">
                                    <StackLayout
                                        Orientation="Horizontal">
                                        <Label
                                            Text="{Binding FirstName}"
                                            FontSize="14"
                                            FontAttributes="Bold"
                                            TextColor="Blue">
                                            <Label.Triggers>
                                                <DataTrigger
                                                    TargetType="Label"
                                                    Binding="{Binding Favorite}"
                                                    Value="True">
                                                    <Setter
                                                        Property="TextColor"
                                                        Value="Red" />
                                                </DataTrigger>
                                            </Label.Triggers>
                                        </Label>
                                        <Label
                                            Text="{Binding LastName}"
                                            FontSize="14"
                                            FontAttributes="Bold"
                                            TextColor="Blue">
                                            <Label.Triggers>
                                                <DataTrigger
                                                    TargetType="Label"
                                                    Binding="{Binding Favorite}"
                                                    Value="True">
                                                    <Setter
                                                        Property="TextColor"
                                                        Value="Red" />
                                                </DataTrigger>
                                            </Label.Triggers>
                                        </Label>
                                    </StackLayout>
                                    <StackLayout
                                        Orientation="Horizontal">
                                        <Label
                                            Text="{Binding Email}"
                                            FontSize="10" />
                                    </StackLayout>
                                </StackLayout>
                            </ViewCell.View>
                        </ViewCell>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

using System;
using System.Collections.Generic;

using Xamarin.Forms;
using XamarinFormsFirstLook.Model;

namespace XamarinFormsFirstLook
{
	public partial class ContactListPage : ContentPage
	{
		public ContactListPage() {
			InitializeComponent();
		}

	    public void OnItemTapped(object o, ItemTappedEventArgs e) {
	        var contact = e.Item as Contact;
	        Navigation.PushAsync(new ContactEntryPage(contact.ID));
	    }

	    protected override void OnAppearing() {
	        base.OnAppearing();
	        ContactList.ItemsSource = App.Database.GetContacts();
	    }

	    protected void OnNewEntry(object o, EventArgs e) {
	        Navigation.PushAsync(new ContactEntryPage());
	    }
	}
}

In iOS project,

using System;
using System.IO;
using SQLite;
using Xamarin.Forms;
using XamarinFormsFirstLook.Data;
using XamarinFormsFirstLook.iOS;

[assembly: Dependency(typeof(SQLite_IOS))]
namespace XamarinFormsFirstLook.iOS
{
    public class SQLite_IOS: ISQLite
    {
        public SQLite_IOS()
        {
        }

        public SQLite.SQLiteConnection GetConnection()
        {
            var sqliteFilename = "Contacts.db";
            //			string documentsPath = Environment.GetFolderPath (Environment.SpecialFolder.Personal); // Documents folder
            //			string libraryPath = Path.Combine (documentsPath, "..", "Library"); // Library folder
            //			var path = Path.Combine(libraryPath, sqliteFilename);

            var path = "/users/shahab/Contacts.db";

            // This is where we copy in the prepopulated database
            if (!File.Exists(path))
            {
                File.Copy(sqliteFilename, path);
            }

            var conn = new SQLite.SQLiteConnection(path);

            // Return the database connection
            return conn;
        }
    }
}

Full Project

Full project can be downloaded from here

A Quick Review of C# 6.0


nameof

When we rename an identifier and the identifier name is referenced in a string then the effect of renaming won’t affect the string.

static void setUser(User user)
{
    if (user == null)
    {
        throw new ArgumentNullException("user", "User is null");
    }
}

Renaming user (#3) will not affect the string "user" (#5)

To resolve this issue, we can use nameof

static void setUser(User user)
{
    if (user == null)
    {
        throw new ArgumentNullException(nameof(user), "User is null");
    }
}

Type safety will be imposed if we use nameof

String interpolation

Old way

const string city = "Dhaka";
const string area = "Dhanmondi";
const string country = "Bangladesh";

var displayAddress = string.Format("Address: {0}, {1}, {2}", area, city, country);

New way

const string city = "Dhaka";
const string area = "Dhanmondi";
const string country = "Bangladesh";

var displayAddress = $"Address: {area}, {city}, {country}";

Another example

var formattedString = $"Today: {DateTime.Now.ToLongDateString()}\n" +
                      $"Dollar: {5:C}";

Console.WriteLine(formattedString);

/*
Today: Sunday, October 16, 2016
Dollar: $5.00
*/

Null conditional operator

Old way

int? age = (user == null) ? (int?) null : user.Age;

// This will crash if user == null
Console.WriteLine($"Name: {user.Fullname}");

New way

int? age2 = user?.Age;

// prints blank if user == null
Console.WriteLine($"Name: {user?.Fullname}");

// default value
int? age3 = user?.Age ?? 0;

// You can chain null checking
Console.WriteLine($"Length: {user?.Fullname?.Length}");

Index initializer

Old way

var dict = new Dictionary<string, string>()
{
    { "Name", "John Doe" },
    { "Profession", "Soft Engg."}
};

New way

var newDict = new Dictionary<string, string>()
{
    ["Name"] = "New John Doe",
    ["Profession"] = "New Soft Engg."
};

Method extension

Suppose we have a class called UserDB

using System.Collections;
using System.Collections.Generic;

namespace AQuickReviewCSharp6
{
    public class UserDB : IEnumerable<User>
    {
        List<User> users = new List<User>();

        public IEnumerator<User> GetEnumerator()
        {
            return users.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        public User Insert(User anUser)
        {
            users.Add(anUser);
            return anUser;
        }
    }
}

Notice that, there is no Add method. Now, if we would like to make an UserDB object and use index initializer then we will get error.

var userCollection = new UserDB()
{
    new User { Fullname = "User 01", Age = 25 },
    new User() { Fullname = "User 02", Age = 30 }
};

Cannot resolve symbol 'Add'

To resolve this we can use extension and add a new method named Add

static class UserDBExtension
{
    public static User Add(this UserDB db, User anUser)
    {
        db.Insert(anUser);
        return anUser;
    }
}

await in catch and finally block

private static async void AMethod()
{
    try
    {
        throw new Exception("Error");
    }
    catch (Exception ex)
    {
        await log("Catch: ", ex);
    }
    finally
    {
        await log("Finally: ", null);
    }
}

private static async Task log(String log, Exception ex)
{
    using (var file = File.AppendText("app.log"))
    {
        await file.WriteLineAsync($"{log} {ex?.ToString()}");
    }
}

Exception filter

You can add exception filter, pretty much like if-else if-else

try
{
    throw new Exception("Error");
}
catch (Exception ex) when (ex.Message.Contains("Warning"))
{
    // Just an warning
}
catch (Exception ex)
{
    // Handle exception
}
finally
{
    Console.WriteLine("Finally");
}

Remember: You need to return a boolean (true) if you handled the case, so that further catch clauses will not be executed.

Auto property initializer

We can initialize a property without using constructor.

public class User
{
    public string Fullname { get; set; } = "Great user";
    public int Age { get; set; } = 20;
}

This is also applicable for getter only properties

public class User
{
    public string Fullname { get; set; } = "Great user";
    public int Age { get; set; } = 20;
    public string Country { get; } = "Australia";
}

Few short hand techniques

Old way

static private string name = "John Doe";

static public string Name
{
    get { return name; }
}

New way

static public string Name = "John Doe";

Old way

static public string GetFullName(string firstName, string lastName)
{
    return String.Format("{0} {1}", firstName, lastName);
}

New way

static public string GetFullName(string firstName, string lastName) => $"{firstName} {lastName}";

Old way

static public User GetUser(string firstName, string lastName)
{
    return new User(firstName, lastName);
}

New way

static public User GetUser(string firstName, string lastName) => new User(firstName, lastName);

static using

using System;
using static System.Console;

public static void Main(string[] args)
{
    WriteLine("Hello World");
}

Android: Gradle First Look


Introduction

Gradle favors convention over configuration. It means, Gradle provides default values for settings and properties. This makes Gradle very easy to get started with. However, if you would like to change/override Gradle default settings and properties, you can do that easily.

Gradle uses Groovy DSL (Domain Specific Language) as it’s configuration lanugage. Groovy is a dynamic language for the Java Virtual Machine (JVM).

Gradle supports three different kinds of repositories.

  1. Maven
  2. Ivy
  3. Static files (mostly *.jar or .aar)

Dependencies are fetched from repositories during the execution phase. Gradle keeps a local cache, so a particular dependency will be downloaded for once only.

Gradle also allows you to build other than Java projects. If you want to manage your JS/C++ projects you can do that using Gradle.

We only need to say what we need, not how to achieve it and Gradle will make it happen. For example, we can add a single line to our build file and Gradle will download the dependency from a remote repository and also sub dependencies and it will make sure all the classes are available to our project.

Installation

Download Gradle from, https://gradle.org/gradle-download/
Make sure to add the Gradle/bin path to your Environment variable.

In MacOS, if you have homebrew installed, then you can run the following command,

~$ brew update
~$ brew install gradle

First task

Let’s create our first task in gradle.

task firstTask {
	println "Hello Gradle"
}

Now we will run our first task.

~$ gradle firstTask
Starting a Gradle Daemon (subsequent builds will be faster)
Hello Gradle
:firstTask UP-TO-DATE

BUILD SUCCESSFUL

Total time: 3.838 secs

All available tasks

~$ gradle tasks
Hello Gradle
:tasks

------------------------------------------------------------
All tasks runnable from root project
------------------------------------------------------------

Build Setup tasks
-----------------
init - Initializes a new Gradle build. [incubating]
wrapper - Generates Gradle wrapper files. [incubating]

Help tasks
----------
buildEnvironment - Displays all buildscript dependencies declared in root project 'Temp'.
components - Displays the components produced by root project 'Temp'. [incubating]
dependencies - Displays all dependencies declared in root project 'Temp'.
dependencyInsight - Displays the insight into a specific dependency in root project 'Temp'.
help - Displays a help message.
model - Displays the configuration model of root project 'Temp'. [incubating]
projects - Displays the sub-projects of root project 'Temp'.
properties - Displays the properties of root project 'Temp'.
tasks - Displays the tasks runnable from root project 'Temp'.

Other tasks
-----------
firstTask

To see all tasks and more detail, run gradle tasks --all

To see more detail about a task, run gradle help --task <task>

BUILD SUCCESSFUL

Total time: 1.008 secs

Build a simple Java project

  1. Create this project structure, /SimpleJava/src/main/java/com/genericslab/simplejava
  2. Create a Java file inside simplejava folder
  3. Create a build.gradle file inside SimpleJava fodler, parallel with src folder.
package com.genericslab.simplejava;

public class Main {
	public static void main (String... args) {
		System.out.println("Hello Java!!!");
	}
}
apply plugin: 'java' 

After this, run the ~ $ gradle tasks command again and see the avialable tasks.

~$ gradle tasks
:tasks

------------------------------------------------------------
All tasks runnable from root project
------------------------------------------------------------

Build tasks
-----------
assemble - Assembles the outputs of this project.
build - Assembles and tests this project.
buildDependents - Assembles and tests this project and all projects that depend on it.
buildNeeded - Assembles and tests this project and all projects it depends on.
classes - Assembles main classes.
clean - Deletes the build directory.
jar - Assembles a jar archive containing the main classes.
testClasses - Assembles test classes.

Build Setup tasks
-----------------
init - Initializes a new Gradle build. [incubating]
wrapper - Generates Gradle wrapper files. [incubating]

Documentation tasks
-------------------
javadoc - Generates Javadoc API documentation for the main source code.

Help tasks
----------
buildEnvironment - Displays all buildscript dependencies declared in root project 'SimpleJava'.
components - Displays the components produced by root project 'SimpleJava'. [incubating]
dependencies - Displays all dependencies declared in root project 'SimpleJava'.
dependencyInsight - Displays the insight into a specific dependency in root project 'SimpleJava'.
help - Displays a help message.
model - Displays the configuration model of root project 'SimpleJava'. [incubating]
projects - Displays the sub-projects of root project 'SimpleJava'.
properties - Displays the properties of root project 'SimpleJava'.
tasks - Displays the tasks runnable from root project 'SimpleJava'.

Verification tasks
------------------
check - Runs all checks.
test - Runs the unit tests.

Rules
-----
Pattern: clean<TaskName>: Cleans the output files of a task.
Pattern: build<ConfigurationName>: Assembles the artifacts of a configuration.
Pattern: upload<ConfigurationName>: Assembles and uploads the artifacts belonging to a configuration.

To see all tasks and more detail, run gradle tasks --all

To see more detail about a task, run gradle help --task <task>

BUILD SUCCESSFUL

Total time: 1.657 secs

As you can see, we have got a number of additional Build Tasks because we had added java plugins.
Let’s run ~ $ gradle build

~$ gradle build
:compileJava
:processResources UP-TO-DATE
:classes
:jar
:assemble
:compileTestJava UP-TO-DATE
:processTestResources UP-TO-DATE
:testClasses UP-TO-DATE
:test UP-TO-DATE
:check UP-TO-DATE
:build

BUILD SUCCESSFUL

Total time: 1.448 secs

A build directory has been generated. You can find a Main.class file in the following directory,
~SimpleJava/build/classes/main/com/genericslab/simplejava

Let’s run it.

~$ java -cp build/classes/main/ com.genericslab.simplejava.Main
Hello Java!!!

Run build with a specific version of Gradle (Gradle Wrapper)

You need to have Gradle already installed.

apply plugin: 'java'

task wrapper(type: Wrapper) {
	gradleVersion = '2.6'
}
~$ gradle wrapper

After running the wrapper task, you will see a folder named gradle and a script file named gradlew and a .bat file named gradlew.bat

From now on, you need to use gradlew instead of gradle to use the particular gradle version 2.6. Any further command started with gradlew will first install the Gradle version 2.6 (if not installed already).

If you have built an application that need to use a particular Gradle version, or you might want to run the application without any hassel in other machine then it is a preferable way to use a wrapper.

Tasks

Task is the unit that Gradle executes. Each task has a lifecycle and may contain properties. Task can also contain dependencies of other tasks.

Let’s create a task

// project level task 
project.task "TaskA"


// in theory, it is a local level task 
// however, practically it is same as before 
// because we are now in project context 
task "TaskB"

// We can add description of a task 
TaskB.description = "This is a description for TaskB"

// Action of a task 
TaskA {
	doLast {
		println "Action#1 for TaskA"
	}
}

// We can define the task and define action together
task "TaskC" {
	doLast {
		println "Action#1 for TaskC"
	}
}

// If we define multiple actions inside a task, 
// actions will be appended
TaskA {
	doLast {
		println "Action#2 for TaskA"
	}
}

// define, description and actions all in one 
task "TaskD" {
	description "This is a description for TaskD"
	doLast {
		println "Action#1 for TaskD"
	}
}

Run ~$ gradle tasks in command line.

~$ gradle tasks
:tasks

------------------------------------------------------------
All tasks runnable from root project
------------------------------------------------------------

Build Setup tasks
-----------------
init - Initializes a new Gradle build. [incubating]
wrapper - Generates Gradle wrapper files. [incubating]

Help tasks
----------
buildEnvironment - Displays all buildscript dependencies declared in root project 'Temp'.
components - Displays the components produced by root project 'Temp'. [incubating]
dependencies - Displays all dependencies declared in root project 'Temp'.
dependencyInsight - Displays the insight into a specific dependency in root project 'Temp'.
help - Displays a help message.
model - Displays the configuration model of root project 'Temp'. [incubating]
projects - Displays the sub-projects of root project 'Temp'.
properties - Displays the properties of root project 'Temp'.
tasks - Displays the tasks runnable from root project 'Temp'.

Other tasks
-----------
TaskA
TaskB - This is a description for TaskB
TaskC
TaskD - This is a description for TaskD

To see all tasks and more detail, run gradle tasks --all

To see more detail about a task, run gradle help --task <task>

BUILD SUCCESSFUL

Total time: 0.852 secs

Task Dependencies

// define, description and actions all in one 
task "TaskD" {
	description "This is a description for TaskD"
	doLast {
		println "Action#1 for TaskD"
	}
}

// TaskA is dependent on TaskC
// means, TaskC will auto executed when we run TaskA 
TaskA.dependsOn TaskC 

// one task must execute after another task 
TaskB .mustRunAfter TaskA 

// one task should execute after another task 
// avoids circular dependencies 
TaskB.shouldRunAfter TaskA, TaskB 

/*
Remember, mustRunAfter and shouldRunAfer will not kick in 
automatically. If we run both tasks together, or, the tasks
have dependencies on one another, only then those two 
keywords will be meaningful. 

What if we would like to run a task after another task, 
even we don't call it separately, or don't have dependencies.
Similar to final block, we can use finalizedBy 
*/

// might be very usefule for db migration 
// after the migration you might want to run a task for cleanup 
TaskB.finalizedBy TaskC 

Run ~$ gradle TaskA

~$ gradle TaskA
:TaskC
Action#1 for TaskC
:TaskA
Action#1 for TaskA
Action#2 for TaskA

BUILD SUCCESSFUL

Total time: 0.908 secs

Define properties

 
def buildName = "Awesome-20160902a"
println "Build name: $buildName"

// global scope
project.ext.versionName = "Awesome=20160902b"
println "Version name: $project.ext.versionName"


<h3>Use built-in task: Copy</h3>


task copyFiles (type: Copy) {
	exclude 'file1.txt', 'file2.txt' // do not copy these files
	from 'src'  // define the source folder 
	from 'dest' // define the destiantion folder 
}

// this can be re-written to 

def spec = copySpec {
	exclude 'file1.txt', 'file2.txt' // do not copy these files
	from 'src'
}

task copyFilesAgain (type: Copy) {
	with spec 
	into 'dest' 
}

// another spec variable 
def spec = copySpec {
	exclude {
		// iterator: it 
		// exclude all pngs 
		it.file.name.endsWith("png")
	}
	from 'src'
}

Sourceset

Gradle Android projects follows this folder structure:

src/main/java
src/main/res
src/main/jniLibs
src/androidTest/java
src/test/java

if you do not like to change your current folder structure then you can tell Gradle where to look for specific files

android {
    sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src']
            resources.srcDirs = ['src']
            aidl.srcDirs = ['src']
            renderscript.srcDirs = ['src']
            res.srcDirs = ['res']
            assets.srcDirs = ['assets']
        }

        androidTest.setRoot('tests')
    }
}

Gradle daemon

Everytime we run ~$ gradle build, Gradle launches JVM and starts from the beginning. Instead if Gradle could run as a service and could reuse already runned JVM then it would have been great!

Voila! Gradle can do that and it's called daemon.

Run ~$ gradle --daemon build and you might be prompted to give a permission and gradle daemon will be started.

If you would like to run --daemon all the time, instead of per command basis then write the following code,

or.gradle.daemon=true

in your project's gradle.properties file. That will ensure daemon will run on your project.

If you would like run daemon irrespective of projects, that means for all projects, then add the line in your ~/.gradle/gradle.properties file.

Android: Instrumentation Testing using Espresso


Introduction

Android provides a number of extra components beyond Java, for example, Activity, Service etc. Testing these extra components you will be required Instrumentation testing and it needs to be run on device/emulators. Espresso is an official instrumentation testing framework by Google.

Installation

Add this line in app level build.gradle in dependencies

androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.1'

add this line inside defaultConfig

testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

For more information,

  1. Android dev
  2. Google github

Project Structure

An androidTest folder should automatically be generated when you created the Android application. For example,

In Android view,

Screenshot at Sep 15 11-44-37.png

Or, in Project view,

Screenshot at Sep 15 11-46-31.png

If not,

  1. Create a folder named androidTest inside src
  2. Create a folder named java inside androidTest

Now we will create our first test class.

  1. Go to the MainActivity.java class and click on MainActivity class name
  2. Select Navigate (from menu)
  3. Select Test (Shift + Cmd + T)
  4. Select, Create New Test…

Select JUnit4 and the dialog should look like this,

Screenshot at Sep 15 11-56-52.png

Click OK.

Check the correct directory is selected. We need to select androidTest directory,

Screenshot at Sep 15 11-57-34.png

Click OK.

Now Sync Gradle.

If you get the following error,

Error:Conflict with dependency 'com.android.support:support-annotations'. Resolved versions for app (24.2.1) and test app (23.0.1) differ. See http://g.co/androidstudio/app-test-app-conflict for details.

The add the following line in dependencies

androidTestCompile 'com.android.support:support-annotations:24.2.1'

Note that the above line version number need to match with the expected version number indicated with the error.

Now let’s go to the newly created MainActivityTest.java


package com.genericslab.espressodemo;

import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;

import org.junit.Rule;
import org.junit.runner.RunWith;

@RunWith(AndroidJUnit4.class)
public class MainActivityTest {

    // This will launch the MainActivity before testing each method/case.
    @Rule
    public ActivityTestRule<MainActivity> activityTestRule = new ActivityTestRule<>(MainActivity.class);

}

Now we will write our first test case

@RunWith(AndroidJUnit4.class)
public class MainActivityTest {

    // This will launch the MainActivity before testing each method/case.
    @Rule
    public ActivityTestRule<MainActivity> activityTestRule = new ActivityTestRule<>(MainActivity.class);

    @Test
    public void testCase1() {
        // Find a view with id = R.id.text
        // Check the text of that view matches with string = R.string.app_name
        onView(withId(R.id.text)).check(matches(withText(R.string.app_name)));
    }
}

Now Right click on the file MainActivityTest.java from project explorer and select “Create MainActivityTest…” -> OK.
Click on Run.

Now we will add our second test case

@Test
public void testCase2() {

    // Open options menu, whether as overflow or using a physical button
    // This will open the option menu as a pop up menu. Next we will click on an item.
    // If you need context then pass, InstrumentationRegistry.getTargetContext()
    openActionBarOverflowOrOptionsMenu(InstrumentationRegistry.getTargetContext());

    // From the options menu, we are going to click on an item having text = R.string.label_help
    onView(withText(R.string.label_help)).perform(click());

    // alternatively, you can leverage id property.
    onView(withId(R.id.menu_help)).perform(click());

    // verifying
    onView(withId(R.id.text)).check(matches(withText(R.string.label_updated)));
}