使用Retrofit+RxJava+MVP打造一款MaterialDesign风格的APP

BucRrn 8年前
   <p>为了熟悉使用一些开源框架,便决定利用业余时间写一个APP来熟悉这些框架的使用。提前踩一踩坑,方便以后在公司的项目中使用。使用的接口是聚合数据的和干货集中营的,非常感谢。</p>    <p><strong>效果图</strong></p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/33aa27a667a72b79a87543ac4d921987.gif"></p>    <p><strong>用到的主流框架</strong></p>    <ul>     <li>首页侧滑栏使用DrawerLayout+NavigationView实现的</li>     <li>使用Realm数据库实现本地收藏</li>     <li>使用Retrofit+RxJava+RxAndroid实现网络请求,并对返回结果进行了简单的封装</li>     <li>对RecyclerView的Adapter和ViewHolder进行封装,实现了上拉加载</li>     <li>使用CoordinatorLayout+AppBarLayout+CollapsingToolbarLayout实现了炫酷的滑动动画</li>     <li>使用Glide实现了图片的加载</li>     <li>使用PhotoView实现了图片的缩放</li>     <li>日历使用开源的material-calendarview</li>     <li>实现了SwipeRefreshLayout首次进入自动刷新</li>    </ul>    <h3><strong>一、使用DrawerLayout+NavigationView实现侧滑栏</strong></h3>    <pre>  <code class="language-java"><?xml version="1.0" encoding="utf-8"?><android.support.v4.widget.DrawerLayout       xmlns:android="http://schemas.android.com/apk/res/android"       xmlns:app="http://schemas.android.com/apk/res-auto"       android:id="@+id/drawerLayout"       android:layout_width="match_parent"       android:layout_height="match_parent">          <LinearLayout           android:layout_width="match_parent"           android:layout_height="match_parent"           android:orientation="vertical">             <android.support.v7.widget.Toolbar                android:id="@+id/toolbar"               android:layout_width="match_parent"               android:layout_height="wrap_content"               app:titleTextColor="@android:color/white" />              <FrameLayout               android:id="@+id/fl_main"               android:layout_width="match_parent"               android:layout_height="match_parent"></FrameLayout>       </LinearLayout>          <android.support.design.widget.NavigationView           android:id="@+id/navigation"           android:layout_width="match_parent"           android:layout_height="match_parent"           android:layout_gravity="start"           android:fitsSystemWindows="true"           app:headerLayout="@layout/drawer_header"           app:menu="@menu/drawer_menu">       </android.support.design.widget.NavigationView></android.support.v4.widget.DrawerLayout>    </code></pre>    <p>DrawerLayout是Androidv4包里自带的控件,支持左滑和右滑,android:layout_gravity="leftt"代表左滑界面(或者start),android:layout_gravity="right"代码右滑的界面(或者end),不加layout_gravity的就是主界面。代码里可以添加ActionBarDrawerToggle控制侧滑栏展示与隐藏。</p>    <pre>  <code class="language-java">ActionBarDrawerToggle mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, mToolBar, R.string.open, R.string.close);   mDrawerToggle.syncState();   mDrawer.addDrawerListener(mDrawerToggle);    </code></pre>    <p>NavigationView是Google在5.0之后推出的一个控件,主要作为菜单控件使用,分为上下部分,上面的部分为headerLayout,可以自定义布局,下面的部分为menu,作为导航菜单的菜单项</p>    <pre>  <code class="language-java"><?xml version="1.0" encoding="utf-8"?><menu xmlns:android="http://schemas.android.com/apk/res/android">       <item           android:id="@+id/drawer_todayInHistory"           android:checkable="true"           android:icon="@drawable/ic_history"           android:title="历史上的今天" />       <item           android:id="@+id/drawer_gril"           android:checkable="true"           android:icon="@drawable/icon_gril"           android:title="妹纸" />       <item           android:id="@+id/drawer_like"           android:checkable="true"           android:icon="@drawable/ic_unlike"           android:title="收藏" />       <item           android:id="@+id/drawer_about"           android:checkable="true"           android:icon="@drawable/ic_about"           android:title="关于" /></menu>    </code></pre>    <p><strong>点击事件:</strong></p>    <pre>  <code class="language-java">navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {         @Override         public boolean onNavigationItemSelected(MenuItem item) {             //在这里处理item的点击事件             return true;         }     });    </code></pre>    <p><strong>获取头部(headerLayout)内控件:</strong></p>    <pre>  <code class="language-java">View headView=navigationView.getHeaderView(0);   </code></pre>    <p><strong>设置菜单列表图标颜色:</strong></p>    <p>默认情况下,菜单图标颜色为灰色,可以通过一下设置图标颜色</p>    <pre>  <code class="language-java">app:itemIconTint=""   </code></pre>    <p>添加分割线:</p>    <p>只需将菜单分成多个Group,每个Group设置一个Id,那么Group之间就会有分割线:</p>    <pre>  <code class="language-java"><menuxmlns:android="http://schemas.android.com/apk/res/android">   <groupandroid:id="@+id/g1">   <item   android:id="@+id/favorite"   android:icon="@mipmap/ic_launcher"   android:title="历史上的今天"/>   <item   android:id="@+id/wallet"   android:icon="@mipmap/ic_launcher"   android:title="收藏"/>   </group>   <groupandroid:id="@+id/g2">   <item   android:id="@+id/photo"   android:icon="@mipmap/ic_launcher"   android:title="妹子"/>   </group>   <item   android:id="@+id/file"   android:icon="@mipmap/ic_launcher"   android:title="关于"/>   </menu>    </code></pre>    <h3><strong>二、Glide加载图片</strong></h3>    <p><strong>设置绑定生命周期</strong></p>    <pre>  <code class="language-java">Glide.with(Context context);// 绑定Context     Glide.with(Activity activity);// 绑定Activity     Glide.with(FragmentActivity activity);// 绑定FragmentActivity     Glide.with(Fragment fragment);// 绑定Fragment    </code></pre>    <p><strong>常规用法:</strong></p>    <pre>  <code class="language-java">Glide.with(context)                   .load(imageUrl)//图片路径                   .placeholder(R.drawable.ic_launcher)//设置加载中图片                   .error(R.drawable.ic_launcher)//设置加载失败图片                   .skipMemoryCache(true)//设置跳过内存缓存                   .diskCacheStrategy(DiskCacheStrategy.ALL)//设置缓存策略:all:缓存源资源和转换后的资源/none:不作任何磁盘缓存 /source:缓存源资源 /result:缓存转换后的资源                   .priority(Priority.NORMAL)//设置下载优先级                   .animate(R.anim.item_alpha_in)//设置加载动画                   .thumbnail(0.1f)//设置缩略图支持(先加载缩略图,再加载全图)                   .override(400,400)//设置加载尺寸                   .centerCrop()//设置动态变换                   .into(imageView);    </code></pre>    <p><strong>加载Git图片:</strong></p>    <pre>  <code class="language-java">Glide.with(this).load(imageUrl).asGif().into(imageView);   </code></pre>    <p><strong>动态缓存清理:</strong></p>    <pre>  <code class="language-java">Glide.get(this).clearDiskCache();//清理磁盘缓存 需要在子线程中执行 Glide.get(this).clearMemory();//清理内存缓存 可以在UI主线程中进行   </code></pre>    <p><strong>加载圆角图片或圆形图片:</strong></p>    <pre>  <code class="language-java">Glide.with(this).load(imageUrl).transform(new GlideRoundTransform(this)).into(imageView);   </code></pre>    <p>需要自定义Transform,这里提供一个圆角和一个圆形的Transform:</p>    <p><strong>圆角转换:</strong></p>    <pre>  <code class="language-java">public class GlideRoundTransform extends BitmapTransformation {          private static float radius = 0f;          public GlideRoundTransform(Context context) {           this(context, 4);       }          public GlideRoundTransform(Context context, int dp) {           super(context);           this.radius = Resources.getSystem().getDisplayMetrics().density * dp;       }          @Override protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {           return roundCrop(pool, toTransform);       }          private static Bitmap roundCrop(BitmapPool pool, Bitmap source) {           if (source == null) return null;              Bitmap result = pool.get(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888);           if (result == null) {               result = Bitmap.createBitmap(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888);           }              Canvas canvas = new Canvas(result);           Paint paint = new Paint();           paint.setShader(new BitmapShader(source, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP));           paint.setAntiAlias(true);           RectF rectF = new RectF(0f, 0f, source.getWidth(), source.getHeight());           canvas.drawRoundRect(rectF, radius, radius, paint);           return result;       }          @Override public String getId() {           return getClass().getName() + Math.round(radius);       }   }    </code></pre>    <p><strong>圆形图片转换:</strong></p>    <pre>  <code class="language-java">public class GlideCircleTransform extends BitmapTransformation {       public GlideCircleTransform(Context context) {           super(context);       }          @Override protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {           return circleCrop(pool, toTransform);       }          private static Bitmap circleCrop(BitmapPool pool, Bitmap source) {           if (source == null) return null;              int size = Math.min(source.getWidth(), source.getHeight());           int x = (source.getWidth() - size) / 2;           int y = (source.getHeight() - size) / 2;              // TODO this could be acquired from the pool too           Bitmap squared = Bitmap.createBitmap(source, x, y, size, size);              Bitmap result = pool.get(size, size, Bitmap.Config.ARGB_8888);           if (result == null) {               result = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);           }              Canvas canvas = new Canvas(result);           Paint paint = new Paint();           paint.setShader(new BitmapShader(squared, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP));           paint.setAntiAlias(true);           float r = size / 2f;           canvas.drawCircle(r, r, r, paint);           return result;       }          @Override public String getId() {           return getClass().getName();       }   }    </code></pre>    <p><strong>获取Bitmap</strong></p>    <pre>  <code class="language-java">Glide.with(this)                   .load(imageUrl)                   .asBitmap()                   .into(new SimpleTarget<Bitmap>() {                       @Override                       public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {                           imageView.setImageBitmap(mBitmap);                       }                   });    </code></pre>    <p> </p>    <p>来自:http://mobile.51cto.com/android-524410.htm</p>    <p> </p>