Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Introduction to Android Development

Introduction to Android Development

The basics, best practices and the future of Android development

Sérgio Santos

April 06, 2016

Transcript

62 slides
  1. Overview • Basics • Architecture • Level 1 - Databases,

    APIs, Compatibility • Level 2 - Testing, Dependency Injection • Future
  2. Activities (code) public class HomeActivity extends Activity { @Override protected

    void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_home); } }
  3. Activities (intents) Intent intent = new Intent(this, HomeActivity.class); startActivity(intent); Uri

    browerUri = Uri.parse("http://www.google.com"); Intent browserIntent = new Intent(Intent.ACTION_VIEW, browerUri); startActivity(browserIntent);
  4. Application Manifest <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="io.bloco.intro"> <uses-permission android:name="android.permission.INTERNET"/>

    <!-- Rest of permissions --> <application android:icon="@mipmap/ic_launcher" android:label="@string/app_name"> <activity android:name=".HomeActivity" android:label="@string/home"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> <activity android:name=".AnotherActivity" android:label="@string/another"> <!-- Rest of activities --> </manifest>
  5. Application Build apply plugin: 'com.android.application' android { compileSdkVersion 23 buildToolsVersion

    "23.2.1" defaultConfig { minSdkVersion 17 targetSdkVersion 23 versionCode 1 versionName "1.0" } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:appcompat-v7:23.2.1' // Rest of dependencies }
  6. Using resources public class HomeActivity extends Activity { @Override protected

    void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_home); Button sendButton = (Button) findViewById(R.id.send); EditText messageEditText = (EditText) findViewById(R.id.message); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String message = messageEditText.getText(); Toast.makeText(this, message, Toast.LENGTH_LONG).show(); } }); } }
  7. Custom Views <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <io.bloco.intro.AwesomeEditText android:id="@+id/message" android:layout_width="wrap_content"

    android:layout_height="wrap_content" android:hint="@string/message" /> <Button android:id="@+id/send" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/send" /> </LinearLayout>
  8. Custom Views class AwesomeEditText extends EditText { public AwesomeEditText(Context context,

    AttributeSet attrs) { super(context, attrs); } @Override public Editable getText() { return super.getText().append(" (awesome!)"); } }
  9. Data binding <layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> <variable name="user" type="io.bloco.intro.User"/> </data> <LinearLayout

    android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{user.firstName}"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{user.lastName}"/> </LinearLayout> </layout>
  10. Data binding @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); HomeActivityBinding

    binding = DataBindingUtil.setContentView(this,R.layout.activity_home); User user = new User("Sérgio", "Santos"); binding.setUser(user); }
  11. Content Providers // Run query Cursor cur = null; ContentResolver

    cr = getContentResolver(); Uri uri = Calendars.CONTENT_URI; String selection = "((" + Calendars.ACCOUNT_NAME + " = ?) AND (" + Calendars.ACCOUNT_TYPE + " = ?) AND (" + Calendars.OWNER_ACCOUNT + " = ?))"; String[] selectionArgs = new String[] {"[email protected]", "com.google", "[email protected]"}; // Submit the query and get a Cursor object back. cur = cr.query(uri, EVENT_PROJECTION, selection, selectionArgs, null);
  12. Realm Realm realm = Realm.getInstance(this); // All writes are wrapped

    in a transaction to facilitate safe multi threading realm.beginTransaction(); // Add a person Person person = realm.createObject(Person.class); person.setName("Young Person"); person.setAge(14); realm.commitTransaction(); RealmResults<User> result = realm.where(User.class) .greaterThan("age", 10) // implicit AND .beginGroup() .equalTo("name", "Peter") .or() .contains("name", "Jo") .endGroup() .findAll();
  13. Retrofit public interface TwitterService { @GET("timeline/{userId}") Call<List<Tweet>> listTweets(@Path("userId") String userId);

    } Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://api.twitter.com/") .build(); TwitterService twitterService = retrofit.create(TwitterService.class);
  14. Retrofit twitterService .listTweets("sdsantos" ) .enqueue(new Callback<List<Tweet>> { @Override public void

    onSuccess(Call<List<Tweet>> call, Response<List<Tweet>> response) { List<Tweet> tweets = request.body(); // Do something with tweets } @Override public void onError(ApiError apiError) { // Show error } });
  15. Instrumentation Testing with Espresso @RunWith(AndroidJUnit4.class) public class CalculatorActivityTest { @Rule

    public ActivityTestRule<CalculatorActivity> activityTestRule = new ActivityTestRule<>(CalculatorActivity.class); @Test public void testSum() throws Exception { onView(withId(R.id.calculator_input)) .perform(typeText("2 + 2")) onView(withText("=")) .perform(click()); onView(withId(R.id.calculator_result)) .check(matches(withText("4"))); } }
  16. Unit Testing with Mockito class Controller { private final Database

    database; private final Screen screen; public Controller(Database database, Screen screen) { this.database = database; this.screen = screen; } public void check() { List<String> fruits = database.getFruits(); if (fruits.isEmpty()) { screen.showEmptyMessage(); } else { screen.showFruits(fruits); } } }
  17. Unit Testing with Mockito public class ControllerTest extends AndroidTestCase {

    private Controller controller; private Database database; private Screen screen; @Override protected void setUp() throws Exception { super.setUp(); database = mock(Database.class); screen = mock(Screen.class); controller = new Controller(database, screen); } // Tests... } // Tests public void testCheckWithFruit() { List<String> fruits = new ArrayList<>(); fruits.add("banana"); fruits.add("apple"); when(database.getFruits()).thenReturn(fruits); controller.check(); verify(screen).showFruits(eq(fruits)); } public void testCheckEmpty() { List<String> emptyFruits = new ArrayList<>(); when(database.getFruits()).thenReturn(emptyFruits); controller.check(); verify(screen).showEmptyMessage(); }
  18. Dependencies // Avoid class Foo { public Foo() { Bar

    bar = new Bar(); // or Bar.getInstance() bar.something(); } } new Foo(); // Better class Foo { public Foo(Bar bar) { bar.something(); } } new Foo(new Bar());
  19. Dependencies // Perfect interface Bar { void something() } class

    MyBar implements Bar { @Override public void something() { // ... } } class Foo { public Foo(Bar bar) { bar.something(); } } new Foo(new MyBar());
  20. Dependency Injection // Goal class Foo { @Inject public Foo(Bar

    bar) { bar.something(); } } Dagger v1: http://square.github.io/dagger/ Dagger v2: http://google.github.io/dagger/
  21. Resources • Google Codelabs: https://codelabs.developers.google.com • Android development like a

    pro: https://speakerdeck.com/rallat/android-development-like-a-pro • Fernando Cejas: http://fernandocejas.com • Kotlin 101: https://speakerdeck.com/ivanbruel/kotlin-101 • Bloco’s blog: https://bloco.io/blog

More Decks by Sérgio Santos

Other Decks in Programming