SlideShare a Scribd company logo
1 of 101
Download to read offline
Artyom Okun
31/7/18
Advanced sessions
Networking
2
Networking is Huge Topic
Letā€™s Talk Dugri
Networking is Huge Topic
Retrofit
RESTHTTP
Web ServicesOkHttp
Nice to Meet You
ā— Name - Artyom
ā— Age - 32
ā— At Android Academy for 4 years
ā— 2 of them as Mentor
ā— Work @Colu as Mobile Developer(yes iOS too)
Meet Colu App
Retrofit
What is Retrofit?
ā€¢Retrofit is a type-safe HTTP client for Android
ā€¢Uses an abstraction, by defining interfaces representing APIs
ā€¢Can be ā€upgradedā€ with different type adapter, JSON parsers, interceptors, call
adapters
ā€¢Uses by default OkHttp as HTTP engine
Retrofit Refresher - Steps to Initialisation
1. Add Retrofit dependency in build.gradle
2. Add permission in AndroidManifest.xml
3. Create an Interface abstraction representing server APIs
4. Create ServiceProvider.java
1. Declare BaseURL for all requests
2. Create and configure OkHttp client
3. Create Retrofit Instance and add OkHttp and BaseUrl to it
4. Expose retrofit.create() method
Retrofit Refresher
dependencies {
compile ā€˜com.squareup.retrofit2:retrofit:2.4.0ā€™
}
build.gradle
AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
Retrofit Refresher
public interface ColuService {
@GET(ā€œ/businessesā€)
@Headers("Content-Type: application/json")
Call<List<Business>> getBusinessesAroundMe(@Query("orderedBy") String orderedBy,
@Query("radius") int inRadius);
...
}
Retrofit Refresher
public class ServiceProvider {
//...
}
Retrofit Refresher
// Base URL for all requests
private static final String BASE_URL = ā€œhttps://coluserver.com/ā€œ;
ServiceProvider.java
Retrofit Refresher
ServiceProvider.java
private static OkHttpClient httpClient = new OkHttpClient.Builder()
...
.build();
Retrofit Refresher
ServiceProvider.java
private static OkHttpClient httpClient = new OkHttpClient.Builder()
...
.build();
Retrofit Refresher
ServiceProvider.java
private static Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(httpClient)
...
.build();
Retrofit Refresher
ServiceProvider.java
private static Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(httpClient)
...
.build();
Retrofit Refresher
ServiceProvider.java
private static Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(httpClient)
...
.build();
Retrofit Refresher
ServiceProvider.java
public static <S> S createService(Class<S> serviceClass) {
return retrofit.create(serviceClass);
}
Why is everything static in ServiceProvider.java?
ā€¢We want same configurations on each Service
ā€¢Alternatives:
A. Use Dependency Injection
B. Use Singleton
Make a Network Call
public class MainActivity extends AppCompatActivity {
private ColuService mColuService;
@Override
protected void onCreate(Bundle savedInstanceState) {
...
mColuService = ServiceProvider.createService(ColuService.class);
getBusinesses();
}
Make a Network Call
public class MainActivity extends AppCompatActivity {
private ColuService mColuService;
@Override
protected void onCreate(Bundle savedInstanceState) {
...
mColuService = ServiceProvider.createService(ColuService.class);
getBusinesses();
}
Make a Network Call
public class MainActivity extends AppCompatActivity {
private ColuService mColuService;
@Override
protected void onCreate(Bundle savedInstanceState) {
...
mColuService = ServiceProvider.createService(ColuService.class);
getBusinesses();
}
Make a Network Call
public class MainActivity extends AppCompatActivity {
private ColuService mColuService;
@Override
protected void onCreate(Bundle savedInstanceState) {
...
mColuService = ServiceProvider.createService(ColuService.class);
getBusinesses();
}
Make a Network Call
public class MainActivity extends AppCompatActivity {
private void getBusinesses() {
mColuService
.getBusinessesAroundMe(ā€œAZā€, 20)
.enqueue(new Callback<List<Business>>() {
// ...
});
Make a Network Call
public class MainActivity extends AppCompatActivity {
.enqueue(new Callback<List<Business>>() {
@Override
public void onResponse(@NonNull Call<List<Business>> call,
@NonNull Response<List<Business>> response) {
// Check response
}
@Override
public void onFailure(@NonNull Call<List<Business>> call,
@NonNull Throwable t) {
}
Make a Network Call
public class MainActivity extends AppCompatActivity {
.enqueue(new Callback<List<Business>>() {
@Override
public void onResponse(@NonNull Call<List<Business>> call,
@NonNull Response<List<Business>> response) {
// Check response
}
@Override
public void onFailure(@NonNull Call<List<Business>> call,
@NonNull Throwable t) {
}
Make a Network Call
@Override
public void onResponse(@NonNull Call<List<Business>> call,
@NonNull Response<List<Business>> response) {
// Check response
if (response.code() == 200) {
// Do awesome stuff
} else {
// Handle other response codes
}
}
Status Codes
ā€¢ 1xx - Informational Messages (Less useful)
ā€¢ 2xx - Successful
ā€¢ 3xx - Another action (i.e. Not Modified)
ā€¢ 4xx - Client error (i.e. bad request)
ā€¢ 5xx - Server error (i.e. requested resource was not found)
Questions?
ā— It is style of software architecture
ā— Stands for REpresentational State Transfer
ā— Uses HTTP Protocol
ā— Can transfer any data
ā— Data often being transferred as JSON
REST
Endpoints Interface Abstraction
public interface ColuService {
@GET(ā€œ/businessesā€)
@Headers("Content-Type: application/json")
Call<List<Business>> getBusinessesAroundMe(@Query("orderedBy") String orderedBy,
@Query("radius") int inRadius);
...
}
Colu Server
Businesses Table
business_id
[ {
"name": ā€œā€¦.ā€
ā€œlocation": ā€œā€¦ā€
ā€¦
Host (BASE_URL)
https://coluserver.com/
public interface ColuService {
@GET(ā€œ/businessesā€)
@Headers("Content-Type: application/json")
Call<List<Business>> getBusinessesAroundMe(@Query("orderedBy") String orderedBy,
@Query("radius") int inRadius);
...
}
Logical Path to Data on Server
Colu Server
Businesses Table
business_id
[ {
"name": ā€œā€¦.ā€
ā€œlocation": ā€œā€¦ā€
ā€¦
Path
https://coluserver.com/businesses
Host (BASE_URL)
public interface ColuService {
@GET(ā€œ/businessesā€)
@Headers("Content-Type: application/json")
Call<List<Business>> getBusinessesAroundMe(@Query("orderedBy") String orderedBy,
@Query("radius") int inRadius);
...
}
What to Do With Data
Colu Server
Businesses Table
business_id
[ {
"name": ā€œā€¦.ā€
ā€œlocation": ā€œā€¦ā€
ā€¦
Path
https://coluserver.com/businesses
Host (BASE_URL)Action Verb
GET
HTTP Action Verbs
HTTP ACTION VERB OPERATION MEANING
POST Create new resource in database
GET Retrieve data from database
PUT Update data in database
PATCH Partially update data in database
DELETE Delete data from database
public interface ColuService {
@GET(ā€œ/businessesā€)
@Headers("Content-Type: application/json")
Call<List<Business>> getBusinessesAroundMe(@Query("orderedBy") String orderedBy,
@Query("radius") int inRadius);
...
}
What to Do With Data
Colu Server
Businesses Table
business_id
[ {
"name": ā€œā€¦.ā€
ā€œlocation": ā€œā€¦ā€
ā€¦
Path
https://coluserver.com/businesses?orderedBy=AZ&radius=20
Host (BASE_URL) Query ParamsAction Verb
GET
public interface ColuService {
@GET(ā€œ/businessesā€)
@Headers("Content-Type: application/json")
Call<List<Business>> getBusinessesAroundMe(@Query("orderedBy") String orderedBy,
@Query("radius") int inRadius);
...
}
What to Do With Data
JSON to Java
public class Business {
private String id;
private String accountId;
private String name;
private String normalizedName;
...
{
"data": [
{
"id": "34o23i4jn23423",
"accountId": "eirjweorknwe93n54354",
"name": "blessed falafel",
"...": "..."
},
{
"...": "..."
}
],
"total": 5000,
"limit": 100,
"offset": 200,
Pro Tip - Use POJO Generator Plugins
i.e. RoboPOJOGenerator
https://github.com/robohorse/RoboPOJOGenerato
r
Create JSON Converter Factory
build.gradle
dependencies {
// Add Gson Converter
compile ā€˜com.squareup.retrofit2:converter-gson:2.8.5ā€™
}
Add JSON Converter Factory
ServiceProvider.java
private static Retrofit.Builder builder =
new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create());
public interface ColuService {
@GET(ā€œ/businessesā€)
@Headers("Content-Type: application/json")
Call<List<Business>> getBusinessesAroundMe(@Query("orderedBy") String orderedBy,
@Query("radius") int inRadius);
...
}
What to Do With Data
Call object
ā€¢ Call<List<Business>> - Retrofit will take the response body and try to
convert it to Java objects.Ā 
ā€¢ Call<ResponseBody> - This makes the raw response payload available, but
skips the mapping to Java objects
ā€¢ Call<Void> - Skips response Ā 
Download Large Files
Use @Streaming - It will tell Retrofit that instead of moving the entire file into memory, it'll pass
along the bytes right
@Streaming
@GET("/businesses")
Call<ResponseBody> getAllBusinessesInCountry(@Query("countryCode") String
countryCode);
Manipulate Call objects
public class MainActivity extends AppCompatActivity {
private Call<List<Business>> mGetBusinessesCall;
private void getBusinessesAroundMe() {
mGetBusinessesCall = mColuService.getBusinessesAroundMe(ā€œAZā€, 20);
mGetBusinessesCall.enqueue(
new Callback<List<Business>>() {
ā€¦
}
Manipulate Call objects
public class MainActivity extends AppCompatActivity {
@Override
protected void onDestroy() {
super.onDestroy();
mGetBusinessesCall.cancel();
}
public interface ColuService {
@GET(ā€œ/businessesā€)
@Headers("Content-Type: application/json")
Call<List<Business>> getBusinessesAroundMe(@Query("orderedBy") String orderedBy,
@Query("radius") int inRadius);
...
}
What to Do With Data
Headers == Request/Response MetaData
ā€¢ Content-Type: application/json
ā€¢ Authorization: <Your Token>
ā€¢ Etag
ā€¢ If-Modified-Since
ā€¢ X-Api-Version
ā€¢ X-WhatEverYouWant
ā€¢ ā€¦
Print Request/Response
HttpLogging Interceptor
dependencies {
implementation "com.squareup.okhttp3:logging-interceptor:3.10.0"
}
build.gradle
Enable Http Logging
ServiceProvider.java
private static OkHttpClient.Builder httpClient =
new OkHttpClient.Builder()
...
.addInterceptor(new HttpLoggingInterceptor()
.setLevel(HttpLoggingInterceptor.Level.BODY));
Log Request in Logcat
**************************** REQUEST *******************************
Url: https://coluserver.com/businesses?orderedBy=AZ&radius=20
Method: GET
Headers:
content-type: application/json;
X-Colu-ApiVersion: 5
X-Colu-Device-Identifier: fc531e38666948e043c6ab...
Authorization: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9....
*************************** REQUEST END *******************
Response Log
***************************** RESPONSE *****************************
Code: 200
Headers:
date: Fri, 27 Jul 2018 07:24:44 GMT
content-type: application/json; charset=utf-8
...
etag: W/"b-EFAlOux7Kcr/ZEgGkn2r+oFAbu4"
Body:
{"businesses":[
{
"id":"aj28j..."
}
]}
***************************** RESPONSE END *****************************
Response Log
***************************** RESPONSE ******************
Code: 200
Headers:
date: Fri, 27 Jul 2018 07:24:44 GMT
content-type: application/json; charset=utf-8
...
etag: W/ā€œb-EFAlOux7Kcr/ZEgGkn2r+oFAbu4"
Body:
{"businesses":[
{
"id":"aj28j..."
}
]}
***************************** RESPONSE END *************
Headers
Response Log
***************************** RESPONSE ******************
Code: 200
Headers:
date: Fri, 27 Jul 2018 07:24:44 GMT
content-type: application/json; charset=utf-8
...
etag: W/ā€œb-EFAlOux7Kcr/ZEgGkn2r+oFAbu4"
Body:
{"businesses":[
{
"id":"aj28j..."
}
]}
***************************** RESPONSE END *************
Optional Body
private static HttpLoggingInterceptor loggingInterceptor =
new HttpLoggingInterceptor()
.setLevel(HttpLoggingInterceptor.Level.BODY);
private static OkHttpClient.Builder httpClient =
new OkHttpClient.Builder()
...
.addInterceptor(loggingInterceptor);
Enable Http Logging
ServiceProvider.java
?
Interceptors
Called Once
Application Interceptors
Multiple Calls
Network Interceptors
public class MyInterceptor implements Interceptor {
@Override
public Response intercept(@NonNull Chain chain) throws IOException {
}
}
Custom Interceptors Implementation
public class MyInterceptor implements Interceptor {
@Override
public Response intercept(@NonNull Chain chain) throws IOException {
}
}
Custom Interceptors Implementation
Custom Interceptor Use Case
Authentication Flow
Request Without Authorization
GET https://coluserver.com/businesses
401 Unauthorized
Get Authentication Token
{
"username": "artyom",
"password": "123456"
}
200 OK
{
"token": ā€œ437fh97b..ā€,
}
Save Token in
Storage
POST https://coluserver.com/login
Add Token To Each Request
200 OK + Response Body
Header Authorization: 437fh97b..
GET https://coluserver.com/businesses
@Override
public Response intercept(@NonNull Chain chain) throws IOException {
// Original Request
Request original = chain.request();
// Get previously saved Authentication token
String token = Storage.getInstance().getToken();
Add Token To Each Request - Right Way
@Override
public Response intercept(@NonNull Chain chain) throws IOException {
// Original Request
Request original = chain.request();
// Get previously saved Authentication token
String token = Storage.getInstance().getToken();
Add Token To Each Request - Right Way
@Override
public Response intercept(@NonNull Chain chain) throws IOException {
// Original Request
Request original = chain.request();
// Get previously saved Authentication token
String token = Storage.getInstance().getToken();
Add Token To Each Request - Right Way
@Override
public Response intercept(@NonNull Chain chain) throws IOException {
// Request customization: add request headers
Request.Builder requestBuilder = original.newBuilder()
.header("Authorization", token);
// Modified request
Request request = requestBuilder.build();
// Continue with request
return chain.proceed(request);
Add Token To Each Request - Right Way
@Override
public Response intercept(@NonNull Chain chain) throws IOException {
// Request customization: add request headers
Request.Builder requestBuilder = original.newBuilder()
.header("Authorization", token);
// Modified request
Request request = requestBuilder.build();
// Continue with request
return chain.proceed(request);
Add Token To Each Request - Right Way
@Override
public Response intercept(@NonNull Chain chain) throws IOException {
// Request customization: add request headers
Request.Builder requestBuilder = original.newBuilder()
.header("Authorization", token);
// Modified request
Request request = requestBuilder.build();
// Continue with request
return chain.proceed(request);
Add Token To Each Request - Right Way
ServiceProvider.java
private static OkHttpClient.Builder httpClient =
new OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
// ...
// ...
.addInterceptor(new AuthenticationInterceptor()));
Add Token To Each Request - Right Way
Control Interceptors Functionality
Control Interceptors Functionality
public interface ColuService {
//. . .
@POST("/users/login")
@Headers("AppInternal-NoAuth:true")
Call<LoginResponse> login(@Body LoginRequest credentials);
}
The trick: Create fake headers to signal the Interceptors what to do
Check Internal Headers Within Interceptors
AuthenticationInterceptor.java
// Original Request
Request request = chain.request();
// if NoAuth-flag header is presenting, no authentication will be added
if (request.header("AppInternal-NoAuth") != null) {
// Remove internal header from request
request = request.newBuilder()
.removeHeader("AppInternal-NoAuth")
.build();
} else {
Check Internal Headers Within Interceptors
AuthenticationInterceptor.java
// Original Request
Request request = chain.request();
// if NoAuth-flag header is presenting, no authentication will be added
if (request.header("AppInternal-NoAuth") != null) {
// Remove internal header from request
request = request.newBuilder()
.removeHeader("AppInternal-NoAuth")
.build();
} else {
Check Internal Headers Within Interceptors
AuthenticationInterceptor.java
// Original Request
Request request = chain.request();
// if NoAuth-flag header is presenting, no authentication will be added
if (request.header("AppInternal-NoAuth") != null) {
// Remove internal header from request
request = request.newBuilder()
.removeHeader("AppInternal-NoAuth")
.build();
} else {
Check Internal Headers Within Interceptors
AuthenticationInterceptor.java
// Original Request
Request request = chain.request();
// if NoAuth-flag header is presenting, no authentication will be added
if (request.header("AppInternal-NoAuth") != null) {
// Remove internal header from request
request = request.newBuilder()
.removeHeader("AppInternal-NoAuth")
.build();
} else {
Check Internal Headers Within Interceptors
AuthenticationInterceptor.java
// Get previously saved Authentication token
String token = Storage.getInstance().getToken();
// Request customization: add request headers
request = request.newBuilder()
.header("Authorization", token)
.build();
}
// Continue with request
return chain.proceed(request);
Check Internal Headers Within Interceptors
AuthenticationInterceptor.java
// Get previously saved Authentication token
String token = Storage.getInstance().getToken();
// Request customization: add request headers
request = request.newBuilder()
.header("Authorization", token)
.build();
}
// Continue with request
return chain.proceed(request);
Check Internal Headers Within Interceptors
AuthenticationInterceptor.java
// Get previously saved Authentication token
String token = Storage.getInstance().getToken();
// Request customization: add request headers
request = request.newBuilder()
.header("Authorization", token)
.build();
}
// Continue with request
return chain.proceed(request);
Optimization
Use Cache
200 OK
GET https://coluserver.com/businesses
{"businesses":[
{
"id":"aj28j..."
}ā€¦
]}
Use Cache
HTTP Cache Strategies
1. Etag/If-None-Match (HashCode based)
2. If-Modified-Since/Last-Modified (Timestamp basef)
Etag/If-None-Match
200 OK + Response Body
Header ETag: X
304 Not Modified (No body included)
Header If-None-Match: X
Cached response
Will be used
GET https://coluserver.com/businesses
GET https://coluserver.com/businesses
If-Modified-Since/Last-Modified
200 OK + Response Body
Header Last-Modified: X
304 Not Modified (No body included)
Header If-Modified-Since: X
Cached response
Will be used
GET https://coluserver.com/businesses
GET https://coluserver.com/businesses
Server Caching Configuration
ā€¢ ā€œCache Control : no-storeā€
Disabled
Enabled, requires verification
Enabled, no need to verify during max-age
ā€¢ ā€œCache Control : must-revalidate, max-age=120ā€
ā€¢ ā€œCache Control : no-cacheā€
Enable Caching in Application
ServiceProvider.java
private static int cacheSize = 10 * 1024 * 1024; // 10 MB
private static Cache cache = new Cache(StorageUtils.
getCacheFolder(MyApplication.getAppContext()),
cacheSize);
private static OkHttpClient.Builder httpClient =
new OkHttpClient.Builder()
.cache(cache)
...
ServiceProvider.java
private static int cacheSize = 10 * 1024 * 1024; // 10 MB
private static Cache cache = new Cache(StorageUtils.
getCacheFolder(MyApplication.getAppContext()),
cacheSize);
private static OkHttpClient.Builder httpClient =
new OkHttpClient.Builder()
.cache(cache)
...
Enable Caching in Application
ServiceProvider.java
private static int cacheSize = 10 * 1024 * 1024; // 10 MB
private static Cache cache = new Cache(StorageUtils.
getCacheFolder(MyApplication.getAppContext()),
cacheSize);
private static OkHttpClient.Builder httpClient =
new OkHttpClient.Builder()
.cache(cache)
...
Enable Caching in Application
What Was Improved
1. Internet traffic saved
2. Faster response
3. Better experience + Cost savings
Explore More
ā€¢ Future Studio Retrofit Tutorials -
https://futurestud.io/tutorials/retrofit-getting-started-and-android-client
ā€¢ HTTP Caching by Ilya Grigorik -
https://developers.google.com/web/fundamentals/performance/optimizing-content-efficienc
y/http-caching
Questions?
Colu is Hiring! CV to artyom@colu.com
Daniel
Roi
Yehuda
Hi
Thank You!

More Related Content

What's hot

Building High Performance and Reliable Windows Phone 8 Apps
Building High Performance and Reliable Windows Phone 8 AppsBuilding High Performance and Reliable Windows Phone 8 Apps
Building High Performance and Reliable Windows Phone 8 AppsMichele Capra
Ā 
JavaScript
JavaScriptJavaScript
JavaScriptSunil OS
Ā 
OSCON Google App Engine Codelab - July 2010
OSCON Google App Engine Codelab - July 2010OSCON Google App Engine Codelab - July 2010
OSCON Google App Engine Codelab - July 2010ikailan
Ā 
Test and profile your Windows Phone 8 App
Test and profile your Windows Phone 8 AppTest and profile your Windows Phone 8 App
Test and profile your Windows Phone 8 AppMichele Capra
Ā 
Greach 2019 - Creating Micronaut Configurations
Greach 2019 - Creating Micronaut ConfigurationsGreach 2019 - Creating Micronaut Configurations
Greach 2019 - Creating Micronaut ConfigurationsIvĆ”n LĆ³pez MartĆ­n
Ā 
A Little Backbone For Your App
A Little Backbone For Your AppA Little Backbone For Your App
A Little Backbone For Your AppLuca Mearelli
Ā 
Java Configuration Deep Dive with Spring
Java Configuration Deep Dive with SpringJava Configuration Deep Dive with Spring
Java Configuration Deep Dive with SpringJoshua Long
Ā 
And now you have two problems. Ruby regular expressions for fun and profit by...
And now you have two problems. Ruby regular expressions for fun and profit by...And now you have two problems. Ruby regular expressions for fun and profit by...
And now you have two problems. Ruby regular expressions for fun and profit by...Codemotion
Ā 
Controlling The Cloud With Python
Controlling The Cloud With PythonControlling The Cloud With Python
Controlling The Cloud With PythonLuca Mearelli
Ā 
Graphql, REST and Apollo
Graphql, REST and ApolloGraphql, REST and Apollo
Graphql, REST and ApolloChristoffer Noring
Ā 
Multi Client Development with Spring
Multi Client Development with SpringMulti Client Development with Spring
Multi Client Development with SpringJoshua Long
Ā 
How to perform debounce in react
How to perform debounce in reactHow to perform debounce in react
How to perform debounce in reactBOSC Tech Labs
Ā 
Incremental Type Safety in React Apollo
Incremental Type Safety in React Apollo Incremental Type Safety in React Apollo
Incremental Type Safety in React Apollo Evans Hauser
Ā 
Play + scala + reactive mongo
Play + scala + reactive mongoPlay + scala + reactive mongo
Play + scala + reactive mongoMax Kremer
Ā 
Appengine Java Night #2b
Appengine Java Night #2bAppengine Java Night #2b
Appengine Java Night #2bShinichi Ogawa
Ā 

What's hot (20)

SERVIET
SERVIETSERVIET
SERVIET
Ā 
Building High Performance and Reliable Windows Phone 8 Apps
Building High Performance and Reliable Windows Phone 8 AppsBuilding High Performance and Reliable Windows Phone 8 Apps
Building High Performance and Reliable Windows Phone 8 Apps
Ā 
JavaScript
JavaScriptJavaScript
JavaScript
Ā 
OSCON Google App Engine Codelab - July 2010
OSCON Google App Engine Codelab - July 2010OSCON Google App Engine Codelab - July 2010
OSCON Google App Engine Codelab - July 2010
Ā 
Test and profile your Windows Phone 8 App
Test and profile your Windows Phone 8 AppTest and profile your Windows Phone 8 App
Test and profile your Windows Phone 8 App
Ā 
Greach 2019 - Creating Micronaut Configurations
Greach 2019 - Creating Micronaut ConfigurationsGreach 2019 - Creating Micronaut Configurations
Greach 2019 - Creating Micronaut Configurations
Ā 
A Little Backbone For Your App
A Little Backbone For Your AppA Little Backbone For Your App
A Little Backbone For Your App
Ā 
Spring 4 - A&BP CC
Spring 4 - A&BP CCSpring 4 - A&BP CC
Spring 4 - A&BP CC
Ā 
Java Configuration Deep Dive with Spring
Java Configuration Deep Dive with SpringJava Configuration Deep Dive with Spring
Java Configuration Deep Dive with Spring
Ā 
And now you have two problems. Ruby regular expressions for fun and profit by...
And now you have two problems. Ruby regular expressions for fun and profit by...And now you have two problems. Ruby regular expressions for fun and profit by...
And now you have two problems. Ruby regular expressions for fun and profit by...
Ā 
XML-Motor
XML-MotorXML-Motor
XML-Motor
Ā 
Controlling The Cloud With Python
Controlling The Cloud With PythonControlling The Cloud With Python
Controlling The Cloud With Python
Ā 
Graphql, REST and Apollo
Graphql, REST and ApolloGraphql, REST and Apollo
Graphql, REST and Apollo
Ā 
Play!ng with scala
Play!ng with scalaPlay!ng with scala
Play!ng with scala
Ā 
Multi Client Development with Spring
Multi Client Development with SpringMulti Client Development with Spring
Multi Client Development with Spring
Ā 
How to perform debounce in react
How to perform debounce in reactHow to perform debounce in react
How to perform debounce in react
Ā 
Incremental Type Safety in React Apollo
Incremental Type Safety in React Apollo Incremental Type Safety in React Apollo
Incremental Type Safety in React Apollo
Ā 
Play + scala + reactive mongo
Play + scala + reactive mongoPlay + scala + reactive mongo
Play + scala + reactive mongo
Ā 
Finatra v2
Finatra v2Finatra v2
Finatra v2
Ā 
Appengine Java Night #2b
Appengine Java Night #2bAppengine Java Night #2b
Appengine Java Night #2b
Ā 

Similar to Advanced #2 networking

Jasigsakai12 columbia-customizes-cas
Jasigsakai12 columbia-customizes-casJasigsakai12 columbia-customizes-cas
Jasigsakai12 columbia-customizes-casellentuck
Ā 
May 2010 - RestEasy
May 2010 - RestEasyMay 2010 - RestEasy
May 2010 - RestEasyJBug Italy
Ā 
Implement Service Broker with Spring Boot #cf_tokyo
Implement Service Broker with Spring Boot #cf_tokyoImplement Service Broker with Spring Boot #cf_tokyo
Implement Service Broker with Spring Boot #cf_tokyoToshiaki Maki
Ā 
The Full Power of ASP.NET Web API
The Full Power of ASP.NET Web APIThe Full Power of ASP.NET Web API
The Full Power of ASP.NET Web APIEyal Vardi
Ā 
ASP.NET Web API
ASP.NET Web APIASP.NET Web API
ASP.NET Web APIhabib_786
Ā 
create-netflix-clone-04-server-continued_transcript.pdf
create-netflix-clone-04-server-continued_transcript.pdfcreate-netflix-clone-04-server-continued_transcript.pdf
create-netflix-clone-04-server-continued_transcript.pdfShaiAlmog1
Ā 
Spring and Cloud Foundry; a Marriage Made in Heaven
Spring and Cloud Foundry; a Marriage Made in HeavenSpring and Cloud Foundry; a Marriage Made in Heaven
Spring and Cloud Foundry; a Marriage Made in HeavenJoshua Long
Ā 
Extending Retrofit for fun and profit
Extending Retrofit for fun and profitExtending Retrofit for fun and profit
Extending Retrofit for fun and profitMatthew Clarke
Ā 
Retrofit library for android
Retrofit library for androidRetrofit library for android
Retrofit library for androidInnovationM
Ā 
Retrofit Library In Android
Retrofit Library In AndroidRetrofit Library In Android
Retrofit Library In AndroidInnovationM
Ā 
Retrofit 2 - O que devemos saber
Retrofit 2 - O que devemos saberRetrofit 2 - O que devemos saber
Retrofit 2 - O que devemos saberBruno Vieira
Ā 
L2 Web App Development Guest Lecture At University of Surrey 20/11/09
L2 Web App Development Guest Lecture At University of Surrey 20/11/09L2 Web App Development Guest Lecture At University of Surrey 20/11/09
L2 Web App Development Guest Lecture At University of Surrey 20/11/09Daniel Bryant
Ā 
My way to clean android - Android day salamanca edition
My way to clean android - Android day salamanca editionMy way to clean android - Android day salamanca edition
My way to clean android - Android day salamanca editionChristian Panadero
Ā 
How To Manage API Request with AXIOS on a React Native App
How To Manage API Request with AXIOS on a React Native AppHow To Manage API Request with AXIOS on a React Native App
How To Manage API Request with AXIOS on a React Native AppAndolasoft Inc
Ā 
HTTP Whiteboard - OSGI Compendium 6.0 - How web apps should have been! - R Auge
HTTP Whiteboard - OSGI Compendium 6.0 - How web apps should have been! - R AugeHTTP Whiteboard - OSGI Compendium 6.0 - How web apps should have been! - R Auge
HTTP Whiteboard - OSGI Compendium 6.0 - How web apps should have been! - R Augemfrancis
Ā 
My way to clean android (EN) - Android day salamanca edition
My way to clean android (EN) - Android day salamanca editionMy way to clean android (EN) - Android day salamanca edition
My way to clean android (EN) - Android day salamanca editionChristian Panadero
Ā 
Backbone.js ā€” Introduction to client-side JavaScript MVC
Backbone.js ā€” Introduction to client-side JavaScript MVCBackbone.js ā€” Introduction to client-side JavaScript MVC
Backbone.js ā€” Introduction to client-side JavaScript MVCpootsbook
Ā 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For BeginnersJonathan Wage
Ā 

Similar to Advanced #2 networking (20)

Jasigsakai12 columbia-customizes-cas
Jasigsakai12 columbia-customizes-casJasigsakai12 columbia-customizes-cas
Jasigsakai12 columbia-customizes-cas
Ā 
RESTEasy
RESTEasyRESTEasy
RESTEasy
Ā 
May 2010 - RestEasy
May 2010 - RestEasyMay 2010 - RestEasy
May 2010 - RestEasy
Ā 
Implement Service Broker with Spring Boot #cf_tokyo
Implement Service Broker with Spring Boot #cf_tokyoImplement Service Broker with Spring Boot #cf_tokyo
Implement Service Broker with Spring Boot #cf_tokyo
Ā 
The Full Power of ASP.NET Web API
The Full Power of ASP.NET Web APIThe Full Power of ASP.NET Web API
The Full Power of ASP.NET Web API
Ā 
ASP.NET Web API
ASP.NET Web APIASP.NET Web API
ASP.NET Web API
Ā 
create-netflix-clone-04-server-continued_transcript.pdf
create-netflix-clone-04-server-continued_transcript.pdfcreate-netflix-clone-04-server-continued_transcript.pdf
create-netflix-clone-04-server-continued_transcript.pdf
Ā 
Spring and Cloud Foundry; a Marriage Made in Heaven
Spring and Cloud Foundry; a Marriage Made in HeavenSpring and Cloud Foundry; a Marriage Made in Heaven
Spring and Cloud Foundry; a Marriage Made in Heaven
Ā 
Servlets
ServletsServlets
Servlets
Ā 
Extending Retrofit for fun and profit
Extending Retrofit for fun and profitExtending Retrofit for fun and profit
Extending Retrofit for fun and profit
Ā 
Retrofit library for android
Retrofit library for androidRetrofit library for android
Retrofit library for android
Ā 
Retrofit Library In Android
Retrofit Library In AndroidRetrofit Library In Android
Retrofit Library In Android
Ā 
Retrofit 2 - O que devemos saber
Retrofit 2 - O que devemos saberRetrofit 2 - O que devemos saber
Retrofit 2 - O que devemos saber
Ā 
L2 Web App Development Guest Lecture At University of Surrey 20/11/09
L2 Web App Development Guest Lecture At University of Surrey 20/11/09L2 Web App Development Guest Lecture At University of Surrey 20/11/09
L2 Web App Development Guest Lecture At University of Surrey 20/11/09
Ā 
My way to clean android - Android day salamanca edition
My way to clean android - Android day salamanca editionMy way to clean android - Android day salamanca edition
My way to clean android - Android day salamanca edition
Ā 
How To Manage API Request with AXIOS on a React Native App
How To Manage API Request with AXIOS on a React Native AppHow To Manage API Request with AXIOS on a React Native App
How To Manage API Request with AXIOS on a React Native App
Ā 
HTTP Whiteboard - OSGI Compendium 6.0 - How web apps should have been! - R Auge
HTTP Whiteboard - OSGI Compendium 6.0 - How web apps should have been! - R AugeHTTP Whiteboard - OSGI Compendium 6.0 - How web apps should have been! - R Auge
HTTP Whiteboard - OSGI Compendium 6.0 - How web apps should have been! - R Auge
Ā 
My way to clean android (EN) - Android day salamanca edition
My way to clean android (EN) - Android day salamanca editionMy way to clean android (EN) - Android day salamanca edition
My way to clean android (EN) - Android day salamanca edition
Ā 
Backbone.js ā€” Introduction to client-side JavaScript MVC
Backbone.js ā€” Introduction to client-side JavaScript MVCBackbone.js ā€” Introduction to client-side JavaScript MVC
Backbone.js ā€” Introduction to client-side JavaScript MVC
Ā 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For Beginners
Ā 

More from Vitali Pekelis

Droidkaigi2019thagikura 190208135940
Droidkaigi2019thagikura 190208135940Droidkaigi2019thagikura 190208135940
Droidkaigi2019thagikura 190208135940Vitali Pekelis
Ā 
Google i o &amp; android q changes 2019
Google i o &amp; android q changes 2019Google i o &amp; android q changes 2019
Google i o &amp; android q changes 2019Vitali Pekelis
Ā 
Advanced #6 clean architecture
Advanced #6  clean architectureAdvanced #6  clean architecture
Advanced #6 clean architectureVitali Pekelis
Ā 
Advanced #4 GPU & Animations
Advanced #4   GPU & AnimationsAdvanced #4   GPU & Animations
Advanced #4 GPU & AnimationsVitali Pekelis
Ā 
Advanced #2 threading
Advanced #2   threadingAdvanced #2   threading
Advanced #2 threadingVitali Pekelis
Ā 
Advanced #1 cpu, memory
Advanced #1   cpu, memoryAdvanced #1   cpu, memory
Advanced #1 cpu, memoryVitali Pekelis
Ā 
All the support you need. Support libs in Android
All the support you need. Support libs in AndroidAll the support you need. Support libs in Android
All the support you need. Support libs in AndroidVitali Pekelis
Ā 
How to build Sdk? Best practices
How to build Sdk? Best practicesHow to build Sdk? Best practices
How to build Sdk? Best practicesVitali Pekelis
Ā 
Android design patterns
Android design patternsAndroid design patterns
Android design patternsVitali Pekelis
Ā 
Advanced #3 threading
Advanced #3  threading Advanced #3  threading
Advanced #3 threading Vitali Pekelis
Ā 
Mobile ui fruit or delicious sweets
Mobile ui  fruit or delicious sweetsMobile ui  fruit or delicious sweets
Mobile ui fruit or delicious sweetsVitali Pekelis
Ā 
Lecture #4 c loaders and co.
Lecture #4 c   loaders and co.Lecture #4 c   loaders and co.
Lecture #4 c loaders and co.Vitali Pekelis
Ā 
Session #4 b content providers
Session #4 b  content providersSession #4 b  content providers
Session #4 b content providersVitali Pekelis
Ā 
Advanced #2 - ui perf
 Advanced #2 - ui perf Advanced #2 - ui perf
Advanced #2 - ui perfVitali Pekelis
Ā 
Android design lecture #3
Android design   lecture #3Android design   lecture #3
Android design lecture #3Vitali Pekelis
Ā 
From newbie to ...
From newbie to ...From newbie to ...
From newbie to ...Vitali Pekelis
Ā 

More from Vitali Pekelis (20)

Droidkaigi2019thagikura 190208135940
Droidkaigi2019thagikura 190208135940Droidkaigi2019thagikura 190208135940
Droidkaigi2019thagikura 190208135940
Ā 
Droidkaigi 2019
Droidkaigi 2019Droidkaigi 2019
Droidkaigi 2019
Ā 
Google i o &amp; android q changes 2019
Google i o &amp; android q changes 2019Google i o &amp; android q changes 2019
Google i o &amp; android q changes 2019
Ā 
Android Q 2019
Android Q 2019Android Q 2019
Android Q 2019
Ā 
Advanced #6 clean architecture
Advanced #6  clean architectureAdvanced #6  clean architecture
Advanced #6 clean architecture
Ā 
Advanced #4 GPU & Animations
Advanced #4   GPU & AnimationsAdvanced #4   GPU & Animations
Advanced #4 GPU & Animations
Ā 
Advanced #2 threading
Advanced #2   threadingAdvanced #2   threading
Advanced #2 threading
Ā 
Advanced #1 cpu, memory
Advanced #1   cpu, memoryAdvanced #1   cpu, memory
Advanced #1 cpu, memory
Ā 
All the support you need. Support libs in Android
All the support you need. Support libs in AndroidAll the support you need. Support libs in Android
All the support you need. Support libs in Android
Ā 
How to build Sdk? Best practices
How to build Sdk? Best practicesHow to build Sdk? Best practices
How to build Sdk? Best practices
Ā 
Di &amp; dagger
Di &amp; daggerDi &amp; dagger
Di &amp; dagger
Ā 
Android design patterns
Android design patternsAndroid design patterns
Android design patterns
Ā 
Advanced #3 threading
Advanced #3  threading Advanced #3  threading
Advanced #3 threading
Ā 
Mobile ui fruit or delicious sweets
Mobile ui  fruit or delicious sweetsMobile ui  fruit or delicious sweets
Mobile ui fruit or delicious sweets
Ā 
Lecture #4 c loaders and co.
Lecture #4 c   loaders and co.Lecture #4 c   loaders and co.
Lecture #4 c loaders and co.
Ā 
Session #4 b content providers
Session #4 b  content providersSession #4 b  content providers
Session #4 b content providers
Ā 
Advanced #2 - ui perf
 Advanced #2 - ui perf Advanced #2 - ui perf
Advanced #2 - ui perf
Ā 
Android meetup
Android meetupAndroid meetup
Android meetup
Ā 
Android design lecture #3
Android design   lecture #3Android design   lecture #3
Android design lecture #3
Ā 
From newbie to ...
From newbie to ...From newbie to ...
From newbie to ...
Ā 

Recently uploaded

The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is insideshinachiaurasa2
Ā 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...masabamasaba
Ā 
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2
Ā 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplatePresentation.STUDIO
Ā 
WSO2CON 2024 - Building the API First Enterprise ā€“ Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise ā€“ Running an API Program, fr...WSO2CON 2024 - Building the API First Enterprise ā€“ Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise ā€“ Running an API Program, fr...WSO2
Ā 
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburgmasabamasaba
Ā 
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park %in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park masabamasaba
Ā 
WSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2
Ā 
%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benoni%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benonimasabamasaba
Ā 
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...masabamasaba
Ā 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...SelfMade bd
Ā 
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...WSO2
Ā 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnAmarnathKambale
Ā 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...masabamasaba
Ā 
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...Jittipong Loespradit
Ā 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfWilly Marroquin (WillyDevNET)
Ā 
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Bert Jan Schrijver
Ā 
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...chiefasafspells
Ā 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisamasabamasaba
Ā 

Recently uploaded (20)

The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is inside
Ā 
Abortion Pill Prices Tembisa [(+27832195400*)] šŸ„ Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] šŸ„ Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] šŸ„ Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] šŸ„ Women's Abortion Clinic in T...
Ā 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
Ā 
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
Ā 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
Ā 
WSO2CON 2024 - Building the API First Enterprise ā€“ Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise ā€“ Running an API Program, fr...WSO2CON 2024 - Building the API First Enterprise ā€“ Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise ā€“ Running an API Program, fr...
Ā 
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
Ā 
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park %in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
Ā 
WSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go Platformless
Ā 
%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benoni%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benoni
Ā 
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
Ā 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Ā 
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
Ā 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
Ā 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
Ā 
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
Ā 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
Ā 
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Ā 
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Ā 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
Ā 

Advanced #2 networking

  • 2. Networking is Huge Topic Letā€™s Talk Dugri
  • 3. Networking is Huge Topic Retrofit RESTHTTP Web ServicesOkHttp
  • 4. Nice to Meet You ā— Name - Artyom ā— Age - 32 ā— At Android Academy for 4 years ā— 2 of them as Mentor ā— Work @Colu as Mobile Developer(yes iOS too)
  • 7. What is Retrofit? ā€¢Retrofit is a type-safe HTTP client for Android ā€¢Uses an abstraction, by defining interfaces representing APIs ā€¢Can be ā€upgradedā€ with different type adapter, JSON parsers, interceptors, call adapters ā€¢Uses by default OkHttp as HTTP engine
  • 8. Retrofit Refresher - Steps to Initialisation 1. Add Retrofit dependency in build.gradle 2. Add permission in AndroidManifest.xml 3. Create an Interface abstraction representing server APIs 4. Create ServiceProvider.java 1. Declare BaseURL for all requests 2. Create and configure OkHttp client 3. Create Retrofit Instance and add OkHttp and BaseUrl to it 4. Expose retrofit.create() method
  • 9. Retrofit Refresher dependencies { compile ā€˜com.squareup.retrofit2:retrofit:2.4.0ā€™ } build.gradle AndroidManifest.xml <uses-permission android:name="android.permission.INTERNET" />
  • 10. Retrofit Refresher public interface ColuService { @GET(ā€œ/businessesā€) @Headers("Content-Type: application/json") Call<List<Business>> getBusinessesAroundMe(@Query("orderedBy") String orderedBy, @Query("radius") int inRadius); ... }
  • 11. Retrofit Refresher public class ServiceProvider { //... }
  • 12. Retrofit Refresher // Base URL for all requests private static final String BASE_URL = ā€œhttps://coluserver.com/ā€œ; ServiceProvider.java
  • 13. Retrofit Refresher ServiceProvider.java private static OkHttpClient httpClient = new OkHttpClient.Builder() ... .build();
  • 14. Retrofit Refresher ServiceProvider.java private static OkHttpClient httpClient = new OkHttpClient.Builder() ... .build();
  • 15. Retrofit Refresher ServiceProvider.java private static Retrofit retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .client(httpClient) ... .build();
  • 16. Retrofit Refresher ServiceProvider.java private static Retrofit retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .client(httpClient) ... .build();
  • 17. Retrofit Refresher ServiceProvider.java private static Retrofit retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .client(httpClient) ... .build();
  • 18. Retrofit Refresher ServiceProvider.java public static <S> S createService(Class<S> serviceClass) { return retrofit.create(serviceClass); }
  • 19. Why is everything static in ServiceProvider.java? ā€¢We want same configurations on each Service ā€¢Alternatives: A. Use Dependency Injection B. Use Singleton
  • 20. Make a Network Call public class MainActivity extends AppCompatActivity { private ColuService mColuService; @Override protected void onCreate(Bundle savedInstanceState) { ... mColuService = ServiceProvider.createService(ColuService.class); getBusinesses(); }
  • 21. Make a Network Call public class MainActivity extends AppCompatActivity { private ColuService mColuService; @Override protected void onCreate(Bundle savedInstanceState) { ... mColuService = ServiceProvider.createService(ColuService.class); getBusinesses(); }
  • 22. Make a Network Call public class MainActivity extends AppCompatActivity { private ColuService mColuService; @Override protected void onCreate(Bundle savedInstanceState) { ... mColuService = ServiceProvider.createService(ColuService.class); getBusinesses(); }
  • 23. Make a Network Call public class MainActivity extends AppCompatActivity { private ColuService mColuService; @Override protected void onCreate(Bundle savedInstanceState) { ... mColuService = ServiceProvider.createService(ColuService.class); getBusinesses(); }
  • 24. Make a Network Call public class MainActivity extends AppCompatActivity { private void getBusinesses() { mColuService .getBusinessesAroundMe(ā€œAZā€, 20) .enqueue(new Callback<List<Business>>() { // ... });
  • 25. Make a Network Call public class MainActivity extends AppCompatActivity { .enqueue(new Callback<List<Business>>() { @Override public void onResponse(@NonNull Call<List<Business>> call, @NonNull Response<List<Business>> response) { // Check response } @Override public void onFailure(@NonNull Call<List<Business>> call, @NonNull Throwable t) { }
  • 26. Make a Network Call public class MainActivity extends AppCompatActivity { .enqueue(new Callback<List<Business>>() { @Override public void onResponse(@NonNull Call<List<Business>> call, @NonNull Response<List<Business>> response) { // Check response } @Override public void onFailure(@NonNull Call<List<Business>> call, @NonNull Throwable t) { }
  • 27. Make a Network Call @Override public void onResponse(@NonNull Call<List<Business>> call, @NonNull Response<List<Business>> response) { // Check response if (response.code() == 200) { // Do awesome stuff } else { // Handle other response codes } }
  • 28. Status Codes ā€¢ 1xx - Informational Messages (Less useful) ā€¢ 2xx - Successful ā€¢ 3xx - Another action (i.e. Not Modified) ā€¢ 4xx - Client error (i.e. bad request) ā€¢ 5xx - Server error (i.e. requested resource was not found)
  • 30.
  • 31. ā— It is style of software architecture ā— Stands for REpresentational State Transfer ā— Uses HTTP Protocol ā— Can transfer any data ā— Data often being transferred as JSON REST
  • 32. Endpoints Interface Abstraction public interface ColuService { @GET(ā€œ/businessesā€) @Headers("Content-Type: application/json") Call<List<Business>> getBusinessesAroundMe(@Query("orderedBy") String orderedBy, @Query("radius") int inRadius); ... }
  • 33. Colu Server Businesses Table business_id [ { "name": ā€œā€¦.ā€ ā€œlocation": ā€œā€¦ā€ ā€¦ Host (BASE_URL) https://coluserver.com/
  • 34. public interface ColuService { @GET(ā€œ/businessesā€) @Headers("Content-Type: application/json") Call<List<Business>> getBusinessesAroundMe(@Query("orderedBy") String orderedBy, @Query("radius") int inRadius); ... } Logical Path to Data on Server
  • 35. Colu Server Businesses Table business_id [ { "name": ā€œā€¦.ā€ ā€œlocation": ā€œā€¦ā€ ā€¦ Path https://coluserver.com/businesses Host (BASE_URL)
  • 36. public interface ColuService { @GET(ā€œ/businessesā€) @Headers("Content-Type: application/json") Call<List<Business>> getBusinessesAroundMe(@Query("orderedBy") String orderedBy, @Query("radius") int inRadius); ... } What to Do With Data
  • 37. Colu Server Businesses Table business_id [ { "name": ā€œā€¦.ā€ ā€œlocation": ā€œā€¦ā€ ā€¦ Path https://coluserver.com/businesses Host (BASE_URL)Action Verb GET
  • 38. HTTP Action Verbs HTTP ACTION VERB OPERATION MEANING POST Create new resource in database GET Retrieve data from database PUT Update data in database PATCH Partially update data in database DELETE Delete data from database
  • 39. public interface ColuService { @GET(ā€œ/businessesā€) @Headers("Content-Type: application/json") Call<List<Business>> getBusinessesAroundMe(@Query("orderedBy") String orderedBy, @Query("radius") int inRadius); ... } What to Do With Data
  • 40. Colu Server Businesses Table business_id [ { "name": ā€œā€¦.ā€ ā€œlocation": ā€œā€¦ā€ ā€¦ Path https://coluserver.com/businesses?orderedBy=AZ&radius=20 Host (BASE_URL) Query ParamsAction Verb GET
  • 41. public interface ColuService { @GET(ā€œ/businessesā€) @Headers("Content-Type: application/json") Call<List<Business>> getBusinessesAroundMe(@Query("orderedBy") String orderedBy, @Query("radius") int inRadius); ... } What to Do With Data
  • 42. JSON to Java public class Business { private String id; private String accountId; private String name; private String normalizedName; ... { "data": [ { "id": "34o23i4jn23423", "accountId": "eirjweorknwe93n54354", "name": "blessed falafel", "...": "..." }, { "...": "..." } ], "total": 5000, "limit": 100, "offset": 200,
  • 43. Pro Tip - Use POJO Generator Plugins i.e. RoboPOJOGenerator https://github.com/robohorse/RoboPOJOGenerato r
  • 44. Create JSON Converter Factory build.gradle dependencies { // Add Gson Converter compile ā€˜com.squareup.retrofit2:converter-gson:2.8.5ā€™ }
  • 45. Add JSON Converter Factory ServiceProvider.java private static Retrofit.Builder builder = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create());
  • 46. public interface ColuService { @GET(ā€œ/businessesā€) @Headers("Content-Type: application/json") Call<List<Business>> getBusinessesAroundMe(@Query("orderedBy") String orderedBy, @Query("radius") int inRadius); ... } What to Do With Data
  • 47. Call object ā€¢ Call<List<Business>> - Retrofit will take the response body and try to convert it to Java objects.Ā  ā€¢ Call<ResponseBody> - This makes the raw response payload available, but skips the mapping to Java objects ā€¢ Call<Void> - Skips response Ā 
  • 48. Download Large Files Use @Streaming - It will tell Retrofit that instead of moving the entire file into memory, it'll pass along the bytes right @Streaming @GET("/businesses") Call<ResponseBody> getAllBusinessesInCountry(@Query("countryCode") String countryCode);
  • 49. Manipulate Call objects public class MainActivity extends AppCompatActivity { private Call<List<Business>> mGetBusinessesCall; private void getBusinessesAroundMe() { mGetBusinessesCall = mColuService.getBusinessesAroundMe(ā€œAZā€, 20); mGetBusinessesCall.enqueue( new Callback<List<Business>>() { ā€¦ }
  • 50. Manipulate Call objects public class MainActivity extends AppCompatActivity { @Override protected void onDestroy() { super.onDestroy(); mGetBusinessesCall.cancel(); }
  • 51. public interface ColuService { @GET(ā€œ/businessesā€) @Headers("Content-Type: application/json") Call<List<Business>> getBusinessesAroundMe(@Query("orderedBy") String orderedBy, @Query("radius") int inRadius); ... } What to Do With Data
  • 52. Headers == Request/Response MetaData ā€¢ Content-Type: application/json ā€¢ Authorization: <Your Token> ā€¢ Etag ā€¢ If-Modified-Since ā€¢ X-Api-Version ā€¢ X-WhatEverYouWant ā€¢ ā€¦
  • 54. HttpLogging Interceptor dependencies { implementation "com.squareup.okhttp3:logging-interceptor:3.10.0" } build.gradle
  • 55. Enable Http Logging ServiceProvider.java private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder() ... .addInterceptor(new HttpLoggingInterceptor() .setLevel(HttpLoggingInterceptor.Level.BODY));
  • 56. Log Request in Logcat **************************** REQUEST ******************************* Url: https://coluserver.com/businesses?orderedBy=AZ&radius=20 Method: GET Headers: content-type: application/json; X-Colu-ApiVersion: 5 X-Colu-Device-Identifier: fc531e38666948e043c6ab... Authorization: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.... *************************** REQUEST END *******************
  • 57. Response Log ***************************** RESPONSE ***************************** Code: 200 Headers: date: Fri, 27 Jul 2018 07:24:44 GMT content-type: application/json; charset=utf-8 ... etag: W/"b-EFAlOux7Kcr/ZEgGkn2r+oFAbu4" Body: {"businesses":[ { "id":"aj28j..." } ]} ***************************** RESPONSE END *****************************
  • 58. Response Log ***************************** RESPONSE ****************** Code: 200 Headers: date: Fri, 27 Jul 2018 07:24:44 GMT content-type: application/json; charset=utf-8 ... etag: W/ā€œb-EFAlOux7Kcr/ZEgGkn2r+oFAbu4" Body: {"businesses":[ { "id":"aj28j..." } ]} ***************************** RESPONSE END ************* Headers
  • 59. Response Log ***************************** RESPONSE ****************** Code: 200 Headers: date: Fri, 27 Jul 2018 07:24:44 GMT content-type: application/json; charset=utf-8 ... etag: W/ā€œb-EFAlOux7Kcr/ZEgGkn2r+oFAbu4" Body: {"businesses":[ { "id":"aj28j..." } ]} ***************************** RESPONSE END ************* Optional Body
  • 60. private static HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor() .setLevel(HttpLoggingInterceptor.Level.BODY); private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder() ... .addInterceptor(loggingInterceptor); Enable Http Logging ServiceProvider.java ?
  • 64. public class MyInterceptor implements Interceptor { @Override public Response intercept(@NonNull Chain chain) throws IOException { } } Custom Interceptors Implementation
  • 65. public class MyInterceptor implements Interceptor { @Override public Response intercept(@NonNull Chain chain) throws IOException { } } Custom Interceptors Implementation
  • 68. Request Without Authorization GET https://coluserver.com/businesses 401 Unauthorized
  • 69. Get Authentication Token { "username": "artyom", "password": "123456" } 200 OK { "token": ā€œ437fh97b..ā€, } Save Token in Storage POST https://coluserver.com/login
  • 70. Add Token To Each Request 200 OK + Response Body Header Authorization: 437fh97b.. GET https://coluserver.com/businesses
  • 71. @Override public Response intercept(@NonNull Chain chain) throws IOException { // Original Request Request original = chain.request(); // Get previously saved Authentication token String token = Storage.getInstance().getToken(); Add Token To Each Request - Right Way
  • 72. @Override public Response intercept(@NonNull Chain chain) throws IOException { // Original Request Request original = chain.request(); // Get previously saved Authentication token String token = Storage.getInstance().getToken(); Add Token To Each Request - Right Way
  • 73. @Override public Response intercept(@NonNull Chain chain) throws IOException { // Original Request Request original = chain.request(); // Get previously saved Authentication token String token = Storage.getInstance().getToken(); Add Token To Each Request - Right Way
  • 74. @Override public Response intercept(@NonNull Chain chain) throws IOException { // Request customization: add request headers Request.Builder requestBuilder = original.newBuilder() .header("Authorization", token); // Modified request Request request = requestBuilder.build(); // Continue with request return chain.proceed(request); Add Token To Each Request - Right Way
  • 75. @Override public Response intercept(@NonNull Chain chain) throws IOException { // Request customization: add request headers Request.Builder requestBuilder = original.newBuilder() .header("Authorization", token); // Modified request Request request = requestBuilder.build(); // Continue with request return chain.proceed(request); Add Token To Each Request - Right Way
  • 76. @Override public Response intercept(@NonNull Chain chain) throws IOException { // Request customization: add request headers Request.Builder requestBuilder = original.newBuilder() .header("Authorization", token); // Modified request Request request = requestBuilder.build(); // Continue with request return chain.proceed(request); Add Token To Each Request - Right Way
  • 77. ServiceProvider.java private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder() .connectTimeout(30, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS) .writeTimeout(30, TimeUnit.SECONDS) // ... // ... .addInterceptor(new AuthenticationInterceptor())); Add Token To Each Request - Right Way
  • 79. Control Interceptors Functionality public interface ColuService { //. . . @POST("/users/login") @Headers("AppInternal-NoAuth:true") Call<LoginResponse> login(@Body LoginRequest credentials); } The trick: Create fake headers to signal the Interceptors what to do
  • 80. Check Internal Headers Within Interceptors AuthenticationInterceptor.java // Original Request Request request = chain.request(); // if NoAuth-flag header is presenting, no authentication will be added if (request.header("AppInternal-NoAuth") != null) { // Remove internal header from request request = request.newBuilder() .removeHeader("AppInternal-NoAuth") .build(); } else {
  • 81. Check Internal Headers Within Interceptors AuthenticationInterceptor.java // Original Request Request request = chain.request(); // if NoAuth-flag header is presenting, no authentication will be added if (request.header("AppInternal-NoAuth") != null) { // Remove internal header from request request = request.newBuilder() .removeHeader("AppInternal-NoAuth") .build(); } else {
  • 82. Check Internal Headers Within Interceptors AuthenticationInterceptor.java // Original Request Request request = chain.request(); // if NoAuth-flag header is presenting, no authentication will be added if (request.header("AppInternal-NoAuth") != null) { // Remove internal header from request request = request.newBuilder() .removeHeader("AppInternal-NoAuth") .build(); } else {
  • 83. Check Internal Headers Within Interceptors AuthenticationInterceptor.java // Original Request Request request = chain.request(); // if NoAuth-flag header is presenting, no authentication will be added if (request.header("AppInternal-NoAuth") != null) { // Remove internal header from request request = request.newBuilder() .removeHeader("AppInternal-NoAuth") .build(); } else {
  • 84. Check Internal Headers Within Interceptors AuthenticationInterceptor.java // Get previously saved Authentication token String token = Storage.getInstance().getToken(); // Request customization: add request headers request = request.newBuilder() .header("Authorization", token) .build(); } // Continue with request return chain.proceed(request);
  • 85. Check Internal Headers Within Interceptors AuthenticationInterceptor.java // Get previously saved Authentication token String token = Storage.getInstance().getToken(); // Request customization: add request headers request = request.newBuilder() .header("Authorization", token) .build(); } // Continue with request return chain.proceed(request);
  • 86. Check Internal Headers Within Interceptors AuthenticationInterceptor.java // Get previously saved Authentication token String token = Storage.getInstance().getToken(); // Request customization: add request headers request = request.newBuilder() .header("Authorization", token) .build(); } // Continue with request return chain.proceed(request);
  • 90. HTTP Cache Strategies 1. Etag/If-None-Match (HashCode based) 2. If-Modified-Since/Last-Modified (Timestamp basef)
  • 91. Etag/If-None-Match 200 OK + Response Body Header ETag: X 304 Not Modified (No body included) Header If-None-Match: X Cached response Will be used GET https://coluserver.com/businesses GET https://coluserver.com/businesses
  • 92. If-Modified-Since/Last-Modified 200 OK + Response Body Header Last-Modified: X 304 Not Modified (No body included) Header If-Modified-Since: X Cached response Will be used GET https://coluserver.com/businesses GET https://coluserver.com/businesses
  • 93. Server Caching Configuration ā€¢ ā€œCache Control : no-storeā€ Disabled Enabled, requires verification Enabled, no need to verify during max-age ā€¢ ā€œCache Control : must-revalidate, max-age=120ā€ ā€¢ ā€œCache Control : no-cacheā€
  • 94. Enable Caching in Application ServiceProvider.java private static int cacheSize = 10 * 1024 * 1024; // 10 MB private static Cache cache = new Cache(StorageUtils. getCacheFolder(MyApplication.getAppContext()), cacheSize); private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder() .cache(cache) ...
  • 95. ServiceProvider.java private static int cacheSize = 10 * 1024 * 1024; // 10 MB private static Cache cache = new Cache(StorageUtils. getCacheFolder(MyApplication.getAppContext()), cacheSize); private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder() .cache(cache) ... Enable Caching in Application
  • 96. ServiceProvider.java private static int cacheSize = 10 * 1024 * 1024; // 10 MB private static Cache cache = new Cache(StorageUtils. getCacheFolder(MyApplication.getAppContext()), cacheSize); private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder() .cache(cache) ... Enable Caching in Application
  • 97. What Was Improved 1. Internet traffic saved 2. Faster response 3. Better experience + Cost savings
  • 98. Explore More ā€¢ Future Studio Retrofit Tutorials - https://futurestud.io/tutorials/retrofit-getting-started-and-android-client ā€¢ HTTP Caching by Ilya Grigorik - https://developers.google.com/web/fundamentals/performance/optimizing-content-efficienc y/http-caching
  • 100. Colu is Hiring! CV to artyom@colu.com Daniel Roi Yehuda Hi