Use Retrofit+RxJava+MVP to create a Material Design style APP

Use Retrofit+RxJava+MVP to create a Material Design style APP

In order to get familiar with the use of some open source frameworks, I decided to use my spare time to write an APP to get familiar with the use of these frameworks. Step on the pits in advance to facilitate future use in the company's projects. The interfaces used are aggregated data and dry goods concentration camp, thank you very much.

Rendering

Mainstream frameworks used

  • The home page side slide bar is implemented using DrawerLayout+NavigationView
  • Using Realm database to implement local collection
  • Use Retrofit+RxJava+RxAndroid to implement network requests and simply encapsulate the returned results
  • Encapsulate the Adapter and ViewHolder of RecyclerView to achieve pull-up loading
  • Use CoordinatorLayout+AppBarLayout+CollapsingToolbarLayout to achieve a cool sliding animation
  • Use Glide to load pictures
  • Use PhotoView to achieve image zoom
  • The calendar uses the open source material-calendarview
  • Implemented SwipeRefreshLayout to automatically refresh for the first time

1. Use DrawerLayout+NavigationView to implement the side slide bar

  1. <?xml version= "1.0" encoding= "utf-8" ?><android.support.v4.widget.DrawerLayout
  2. xmlns:android= "http://schemas.android.com/apk/res/android"  
  3. xmlns:app= "http://schemas.android.com/apk/res-auto"  
  4. android:id= "@+id/drawerLayout"  
  5. android:layout_width= "match_parent"  
  6. android:layout_height= "match_parent" >
  7.  
  8. <LinearLayout
  9. android:layout_width= "match_parent"  
  10. android:layout_height= "match_parent"  
  11. android:orientation= "vertical" >
  12.  
  13. <android.support.v7.widget.Toolbar
  14. android:id= "@+id/toolbar"  
  15. android:layout_width= "match_parent"  
  16. android:layout_height= "wrap_content"  
  17. app:titleTextColor= "@android:color/white" />
  18.  
  19. <FrameLayout
  20. android:id= "@+id/fl_main"  
  21. android:layout_width= "match_parent"  
  22. android:layout_height= "match_parent" ></FrameLayout>
  23. </LinearLayout>
  24.  
  25. <android.support.design.widget.NavigationView
  26. android:id= "@+id/navigation"  
  27. android:layout_width= "match_parent"  
  28. android:layout_height= "match_parent"  
  29. android:layout_gravity= "start"  
  30. android:fitsSystemWindows= "true"  
  31. app:headerLayout= "@layout/drawer_header"  
  32. app:menu= "@menu/drawer_menu" >
  33. </android.support.design.widget.NavigationView></android.support.v4.widget.DrawerLayout>

DrawerLayout is a built-in control in the Androidv4 package, which supports left and right sliding. android:layout_gravity="leftt" represents the left sliding interface (or start), android:layout_gravity="right" represents the right sliding interface (or end), and the main interface is the one without layout_gravity. You can add ActionBarDrawerToggle in the code to control the display and hiding of the side sliding bar.

  1. ActionBarDrawerToggle mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, mToolBar, R.string. open , R.string. close );
  2. mDrawerToggle.syncState();
  3. mDrawer.addDrawerListener(mDrawerToggle);

NavigationView is a control launched by Google after 5.0. It is mainly used as a menu control. It is divided into upper and lower parts. The upper part is headerLayout, which can customize the layout, and the lower part is menu, which is used as the menu item of the navigation menu.

  1. <?xml version= "1.0" encoding= "utf-8" ?><menu xmlns:android= "http://schemas.android.com/apk/res/android" >
  2. <item
  3. android:id= "@+id/drawer_todayInHistory"  
  4. android:checkable= "true"  
  5. android:icon= "@drawable/ic_history"  
  6. android:title= "Today in History" />
  7. <item
  8. android:id= "@+id/drawer_gril"  
  9. android:checkable= "true"  
  10. android:icon= "@drawable/icon_gril"  
  11. android:title= "Girl" />
  12. <item
  13. android:id= "@+id/drawer_like"  
  14. android:checkable= "true"  
  15. android:icon= "@drawable/ic_unlike"  
  16. android:title= "Collection" />
  17. <item
  18. android:id= "@+id/drawer_about"  
  19. android:checkable= "true"  
  20. android:icon= "@drawable/ic_about"  
  21. android:title= "About" /></menu>

Click event:

  1. navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
  2. @Override
  3. public boolean onNavigationItemSelected(MenuItem item) {
  4. //Handle the item click event here
  5. return   true ;
  6. }
  7. });

Get the controls in the header (headerLayout):

  1. View headView=navigationView.getHeaderView(0);

Set the menu list icon color:

By default, the menu icon color is gray. You can set the icon color by

  1. app:itemIconTint= ""  

Add a dividing line:

Just divide the menu into multiple groups, set an ID for each group, and there will be a dividing line between the groups:

  1. <menuxmlns:android= "http://schemas.android.com/apk/res/android" >
  2. <groupandroid:id= "@+id/g1" >
  3. <item
  4. android:id= "@+id/favorite"  
  5. android:icon= "@mipmap/ic_launcher"  
  6. android:title= "Today in History" />
  7. <item
  8. android:id= "@+id/wallet"  
  9. android:icon= "@mipmap/ic_launcher"  
  10. android:title= "Collection" />
  11. </ group >
  12. <groupandroid:id= "@+id/g2" >
  13. <item
  14. android:id= "@+id/photo"  
  15. android:icon= "@mipmap/ic_launcher"  
  16. android:title= "Girl" />
  17. </ group >
  18. <item
  19. android:id= "@+id/file"  
  20. android:icon= "@mipmap/ic_launcher"  
  21. android:title= "About" />
  22. </menu>

2. Glide loading pictures

Setting the binding lifecycle

  1. Glide. with (Context context); // Bind Context
  2. Glide. with (Activity activity); // Bind Activity
  3. Glide. with (FragmentActivity activity);// Bind FragmentActivity
  4. Glide. with (Fragment fragment);// Bind Fragment

General usage:

  1. Glide. with (context)
  2. .load (imageUrl) //image path
  3. .placeholder(R.drawable.ic_launcher) //Set the loading image
  4. .error(R.drawable.ic_launcher) //Set the image that failed to load
  5. .skipMemoryCache( true ) //Set to skip memory cache
  6. .diskCacheStrategy(DiskCacheStrategy. ALL ) //Set cache strategy: all : cache source resources and converted resources / none: do not cache any disk resources / source: cache source resources / result: cache converted resources
  7. .priority(Priority.NORMAL) //Set download priority
  8. .animate(R.anim.item_alpha_in) //Set loading animation
  9. .thumbnail(0.1f) //Set thumbnail support (load thumbnails first, then load full images)
  10. .override(400,400) //Set loading size
  11. .centerCrop() //Set dynamic transformation
  12. . into (imageView);

Load the Git image:

  1. Glide. with (this). load (imageUrl).asGif(). into (imageView);

Dynamic cache cleaning:

  1. Glide.get(this).clearDiskCache(); //Clear the disk cache. Need to be executed in the child thread. Glide.get(this).clearMemory(); //Clear the memory cache. Can be done in the UI main thread.

Load rounded corner images or circular images:

  1. Glide. with (this). load (imageUrl).transform(new GlideRoundTransform(this)). into (imageView);

A custom Transform is required. Here is a Transform for rounded corners and a circle:

Round Corner Conversion:

  1. public class GlideRoundTransform extends BitmapTransformation {
  2.  
  3. private static   float radius = 0f;
  4.  
  5. public GlideRoundTransform(Context context) {
  6. this(context, 4);
  7. }
  8.  
  9. public GlideRoundTransform(Context context, int dp) {
  10. super(context);
  11. this.radius = Resources.getSystem().getDisplayMetrics().density * dp;
  12. }
  13.  
  14. @Override protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
  15. return roundCrop(pool, toTransform);
  16. }
  17.  
  18. private static Bitmap roundCrop(BitmapPool pool, Bitmap source) {
  19. if (source == null ) return   null ;
  20.  
  21. Bitmap result = pool.get(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888);
  22. if (result == null ) {
  23. result = Bitmap.createBitmap(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888);
  24. }
  25.  
  26. Canvas canvas = new Canvas(result);
  27. Paint paint = new Paint();
  28. paint.setShader(new BitmapShader(source, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP));
  29. paint.setAntiAlias( true );
  30. RectF rectF = new RectF(0f, 0f, source.getWidth(), source.getHeight());
  31. canvas.drawRoundRect(rectF, radius, radius, paint);
  32. return result;
  33. }
  34.  
  35. @Override public String getId() {
  36. return getClass().getName() + Math.round(radius);
  37. }
  38. }

Circular image conversion:

  1. public class GlideCircleTransform extends BitmapTransformation {
  2. public GlideCircleTransform(Context context) {
  3. super(context);
  4. }
  5.  
  6. @Override protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
  7. return circleCrop(pool, toTransform);
  8. }
  9.  
  10. private static Bitmap circleCrop(BitmapPool pool, Bitmap source) {
  11. if (source == null ) return   null ;
  12.  
  13. int   size = Math. min (source.getWidth(), source.getHeight());
  14. int x = (source.getWidth() - size ) / 2;
  15. int y = (source.getHeight() - size ) / 2;
  16.  
  17. // TODO this could be acquired from the pool too
  18. Bitmap squared = Bitmap.createBitmap(source, x, y, size , size );
  19.  
  20. Bitmap result = pool.get( size , size , Bitmap.Config.ARGB_8888);
  21. if (result == null ) {
  22. result = Bitmap.createBitmap( size , size , Bitmap.Config.ARGB_8888);
  23. }
  24.  
  25. Canvas canvas = new Canvas(result);
  26. Paint paint = new Paint();
  27. paint.setShader(new BitmapShader(squared, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP));
  28. paint.setAntiAlias( true );
  29. float r = size / 2f;
  30. canvas.drawCircle(r, r, r, paint);
  31. return result;
  32. }
  33.  
  34. @Override public String getId() {
  35. return getClass().getName();
  36. }
  37. }

Get Bitmap

  1. Glide.with ( this)
  2. .load (imageUrl)
  3. .asBitmap()
  4. . into (new SimpleTarget<Bitmap>() {
  5. @Override
  6. public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
  7. imageView.setImageBitmap(mBitmap);
  8. }
  9. });

<<:  MVP architecture in Android development

>>:  Android obfuscation from entry to mastery

Recommend

I abandoned my iPhone and switched to Android, but I didn’t miss it at all

This is a self-narration of a 24-year-old boy, Se...

Dear advertiser, what misunderstanding do you have about advertising creativity?

A few days ago, a colleague sent me an App screen...

The dilemma of TV boxes: Are users forced to become the final winners?

In just three months, the TV box was sentenced to...

Four charts to help you understand how Uber is taking away taxi business

Uber and Lyft began a 120-day trial in Portland i...

Why are foldable phones popular but not commercially successful?

Two years ago, foldable phones were popular for a...

How are those who always do manicures doing now?

Manicure has become an indispensable part of wome...

Xiaohongshu marketing method!

The "Insight Report on the Rise of Domestic ...

How to solve lactose intolerance in milk?

Milk has become an indispensable drink for our da...