modern android development
TRANSCRIPT
Modern Android Development
Computas24.09.2015
Khiem-Kim Ho Xuan
Agenda
• Code behind• Material Design• Pattern recommended to use
01.05.20233
Code behind
• Libraries:• ButterKnife• Square Otto Event Bus• Google Play Services• Support libraries
• Material design• Retrofit• Dagger2• Picasso
01.05.20234
ButterKnife v7.0.1• Annotate fields with @Bind
• ButterKnife will find the binded ID to the component, layout or resource ids.• Why?
• Slow reflection. ButterKnife makes sure that the code is generated to perform the view lookups. Bind delegates to the generated code.
• Resource Binding• Bind resources. You need to specify the Bind. For example @BindString,
@BindDrawable, @BindColor, @BindDimen• Non-Activity Binding
• Use @Bind to connect the component or Array. But need to specify @Bind({,….})• Listener
• Bind listeners for example annotate @OnClick({….}) or @OnItemSelected({…})• Reset Bind
• Need to clean the bindings when destroying an Activity or a Fragment using @UnBind.
01.05.20235
Square Otto Event Bus v1.3.8• Decouple parts of the application for communication.• Acts as a pub-sub.• Publish
• Tell Subscribers that an action has occured
• Subscribe• Receive notification that an event has occured• Annotate method with @Subscribe
• Register to a bus• Need to call bus.register(this). In order to receive events
bus.post(new AnswerAvailableEvent(42));
@Subscribe public void answerAvailable(AnswerAvailableEvent event) { // TODO: React to the event somehow! }
01.05.20236
Retrofit v2.0• Turns HTTP API into a Java interface• Uses Annotations to describe HTTP request:
• URL parameter replacement and query parameter support• Object convertsion to request body (JSON, protocol buffer)• Multipart request body and file upload
• Request Method
• Request Body
• Multipart
• Header
@GET("/group/{id}/users") List<User> groupList(@Path("id") int groupId);
@POST("/users/new") Call<User> createUser(@Body User user);
@Multipart @PUT("/user/photo") Call<User> updateUser(@Part("photo") RequestBody photo, @Part("description") RequestBody description);
@Headers({ "Accept: application/vnd.github.v3.full+json", "User-Agent: Retrofit-Sample-App" }) @GET("/users/{username}") Call<User> getUser(@Path("username") String username);
01.05.20237
Dagger2• Dependency Injection making application loosely coupled.• Annotations:
• @Module: classes whose methods provide dependencies• @Provides: methods within module classes• @Inject: request a dependency (a constructor, field or a method)• @Component: bridge interface between modules and injection
@Modulepublic class VehicleModule { @Provides @Singleton Motor provideMotor(){ return new Motor(); } @Provides @Singleton Vehicle provideVehicle(){ return new Vehicle(new Motor()); }}
@Injectpublic Vehicle(Motor motor){ this.motor = motor;}
@Singleton@Component(modules = {VehicleModule.class})public interface VehicleComponent { Vehicle provideVehicle(); } // connect @modules with @inject
01.05.20238
Dagger2• When everything is ready
• Obtain instance of the interface and invoke its method.• Do it inside onCreate method!
• Why Dagger2?• No reflection: graph validation, configuration and precondition done at compile time.• Performance gain
public class MainActivity extends ActionBarActivity { Vehicle mVehicle; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); VehicleComponent component = Dagger_VehicleComponent.builder().vehicleModule(new VehicleModule()).build(); mVehicle = component.provideVehicle(); Toast.makeText(this, String.valueOf(vehicle.getSpeed()), Toast.LENGTH_SHORT).show(); }}
01.05.20239
Picasso v2.5.2• Load image into a view based on url or from memory• Picasso handles:
• ImageView recycling and download cancelation in an adapter• Complex image transformations with minimal memory usage• Automatic memory and disk caching.• Has placeholders in case of loading or failed loading image.
Picasso.with(context) .load(url) .placeholder(R.drawable.user_placeholder) .error(R.drawable.user_placeholder_error) .into(imageView);
Material Design
• Make all apps flat as paper,• responsive animations!• Right color and shadow depths• Get inspired!
• http://www.materialup.com/
Material Design
• Use Androids Design library:• com.android.support.design
• Snackbar!• Like Toast, but shows a message at the bottom of
the screen
Snackbar.make(mDrawerLayout, "Your message", Snackbar.LENGTH_SHORT).setAction(getString(R.string.text_undo), this).show();
01.05.202312
Shared Element Transition
• Animate different UI states in an application.• Built on
• Scene: Defines UI states in an application• Transition: Defines the animated change between two scenes
• Need to define transition in style.xml and also
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android"><changeBounds> <targets> <target android:targetId="@id/ivPosterImage" /> <target android:targetId="@id/detailed_image" /> </targets></changeBounds><changeImageTransform> <targets> <target android:targetId="@id/ivPosterImage" /> <target android:targetId="@id/detailed_image" /> </targets></changeImageTransform></transitionSet>
01.05.202313
Shared Element Transition<style name="AppTheme" parent="AppTheme.Base"> <item name="android:windowContentTransitions">true</item> <item name="android:windowAllowEnterTransitionOverlap">true</item> <item name="android:windowAllowReturnTransitionOverlap">true</item> <item name="android:windowIsTranslucent">true</item> <!-- specify enter and exit transitions --> <item name="android:windowEnterTransition">@transition/fade</item> <item name="android:windowExitTransition">@transition/fade</item>
<!-- specify shared element transitions --> <item name="android:windowSharedElementEnterTransition"> @transition/change_image_transform </item><transitionSet xmlns:android="http://schemas.android.com/apk/res/android"> <changeBounds> <targets> <target android:targetId="@id/ivPosterImage" /> <target android:targetId="@id/detailed_image" /> </targets> </changeBounds> <changeImageTransform> <targets> <target android:targetId="@id/ivPosterImage" /> <target android:targetId="@id/detailed_image" /> </targets> </changeImageTransform></transitionSet> <item name="android:windowSharedElementExitTransition"> @transition/change_image_transform </item></style>
01.05.202314
Floating Action Button
• fabSize: set the size of the button• Normal: 56dp• Mini: 40dp
• backgroundTint: set the background color of this instance
• rippleColor set color of the ripple effect when pressed
• src: set the icon displayed within the FAB<android.support.design.widget.FloatingActionButtonandroid:id=”@+id/fab_normal”android:layout_width=”wrap_content”android:layout_height=”wrap_content”android:src=”@drawable/ic_plus”app:fabSize=”normal” />
01.05.202315
EditText Floating Labels
• Display floating labels above EditText fields.• Gives focus or hint of float.• Useful to use while data is being input• You can also add Error message
<android.support.design.widget.TextInputLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content">
<EditTextandroid:id="@+id/edit_text_email"android:layout_width="match_parent"/></android.support.design.widget.TextInputLayout>
setErrorEnabled(true);setError(getString(R.string.text_error_message));
01.05.202316
Navigation View• Placed within a DrawerLayout
<android.support.v4.widget.DrawerLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:id="@+id/drawer_layout"android:layout_width="match_parent"android:layout_height="match_parent"android:fitsSystemWindows="true">
<FrameLayoutandroid:id="@+id/main_content_frame"android:layout_width="match_parent"android:layout_height="match_parent" />
<android.support.design.widget.NavigationViewandroid:id="@+id/navigation_view"android:layout_width="wrap_content"android:layout_height="match_parent"android:layout_gravity="start"app:headerLayout="@layout/navigation_header"app:menu="@menu/drawer" />
</android.support.v4.widget.DrawerLayout>
01.05.202317
TabLayout• tabMode: set the layout to fixed or scrollable• tabGravity: set gravity of the tab, either filled (distributed to all available space
between individual tabs) or centre (position tabs in the center of the TabLayout)• setText() and setIcon()
• Listeners:• OnTabSelectedListener• TabLayoutOnPageChangeListener• ViewPagerOnTabSelectedListener
<android.support.design.widget.TabLayoutandroid:id="@+id/sliding_tabs"android:layout_width="match_parent"android:layout_height="wrap_content"app:tabMode="fixed"app:tabGravity="fill" />
ViewPager pager = (ViewPager)rootView.findViewById(R.id.viewPager);pager.setAdapter(new MyPagerAdapter(getActivity().getSupportFragmentManager()));
TabLayout tabLayout = (TabLayout) rootView.findViewById(R.id.sliding_tabs);tabLayout.addTab(tabLayout.newTab().setText("Tab One"));tabLayout.addTab(tabLayout.newTab().setText("Tab Two"));tabLayout.addTab(tabLayout.newTab().setText("Tab Three"));tabLayout.setupWithViewPager(pager);
01.05.202318
Coordinator Layout• Super FrameLayout
• Adds transition view basedon motion of other components• Lets us adapt layouts based on scroll events.
• Set the property layout_scrollFlags• enterAlways – view will become visible when a downward scroll event occurs• enterAlwaysCollapsed – if view has minHeight, it will only enter at a that height and expand fully once the scrolling view reached the top.
<android.support.design.widget.CoordinatorLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent">
<android.support.v7.widget.RecyclerViewandroid:layout_width="match_parent"android:layout_height="match_parent"app:layout_behavior="@string/appbar_scrolling_view_behavior" /><android.support.design.widget.AppBarLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content">
<android.support.v7.widget.Toolbarapp:layout_scrollFlags="scroll|enterAlways" /><android.support.design.widget.TabLayout/> </android.support.design.widget.AppBarLayout></android.support.design.widget.CoordinatorLayout>
01.05.202319
Support Toolbar
• Use• com.android.support.appcompat-v7:<versionnumber>• Remember to style the toolbar!
<android.support.v7.widget.Toolbar android:id=”@+id/my_awesome_toolbar” android:layout_height=”wrap_content” android:layout_width=”match_parent” android:minHeight=”?attr/actionBarSize” android:background=”?attr/colorPrimary” />
@Overridepublic void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.blah);
Toolbar toolbar = (Toolbar) findViewById(R.id.my_awesome_toolbar); setSupportActionBar(toolbar);}
<style name="Theme.MyTheme" parent="Theme.AppCompat.Light"> <!-- Set AppCompat’s actionBarStyle --> <item name="actionBarStyle">@style/MyActionBarStyle</item>
<!-- Set AppCompat’s color theming attrs --> <item name="colorPrimary">@color/my_awesome_red</item> <item name="colorPrimaryDark">@color/my_awesome_darker_red</item> <!-- The rest of your attributes --></style>
01.05.202320
Pattern recommended to use
• Model-View-Presenter (MVP)
• User interacts with the View.• There is one-to-one relationship between View and Presenter means one View is mapped to
only one Presenter.• View has a reference to Presenter but View has not reference to Model.• Provides two way communication between View and Presenter.
01.05.202321
Firmu – The Cinema Locator App
• Google Play Store• (Later on Windows Store and IOS).• Highly inspired by Material Design and modern
mobile development.• Feedback on the app please
01.05.202322
Pitch (Beta version)
• Google Play Store• (Later on Windows Store and IOS).• Highly inspired by Material Design and modern
mobile development.• Feedback on the app please
23 © Computas AS 01.05.2023
Questions?
Computas AS Tel +47 67 83 10 00Lysaker Torg 45, pb 482 Fax +47 67 83 10 011327 Lysaker Org.nr: NO 986 352 325 MVANorway www.computas.com
Khiem-Kim Ho Xuan