1. 启动界面设置为某张图片
在styles.xml文件中自定义一个主题,主题的属性中设置windowBackground为某张既定照片。
1 |
|
接着在manifest的配置文件中设定启动activity的theme属性:
1 | <activity |
2. Retrofit的使用
向某个服务器请求网络时使用@GET注解,对于请求的参数用@Query来来标注。将所有的请求全部写在一个接口文件(ApiService.java)中方便调用,该文件形式为:
1 | public interface ApiService { |
对于请求得到的数据用RxJava中的Observable<\T>来存储。这样在得到数据后可以通过使用RxJava的链式调用来回调请求成功或失败的方法,其中T为请求数据的实体类(Entity),该Entity以返回数据的json形式定义参数。
1 | apiService.getSplash(client, version, time, deviceId) |
3. 判断网络类型是否是wifi
利用ConnectivityManager来判断。
1 | public static boolean isWifi(Context context) { |
4. 根据url下载图片
下载图片用okhttp来实现,传入图片的url地址,分别重写成功和失败的回调函数,在成功的回调函数中保存图片。
1 | public static void download(String url) { |
对于请求的客户端可以添加一个拦截器(Interceptor)来实现对请求和返回数据的修改:
1 | public static final OkHttpClient client = new OkHttpClient.Builder() |
5. Dagger2
MVP模式下每一个Presenter都需要有一个对应的View(Activity/Fragment),具体体现为在每一个View中需要实例化一个Presenter对象,实例化Presenter对象的操作可以通过@Inject注解来实现。
在Activity中注解Presenter对象表示需要使用Presenter的一个实例,如在SplashActivity中:
1 |
|
对于依赖的提供方Presenter,则将注解@Inject作用于其构造函数,表示该类提供一个实例,SplashPresenter中的具体实现为:
1 | private SplashContract.View view; |
SplashPresenter中提供注解的构造函数又包含两个参数View和ApiService,这两个参数可以通过注解@Module、@Provides、@Component实现。
@Module、@Provides应用于Module类,Module类中用@Provides标识的函数为提供依赖的地方,如:
1 |
|
Component类为联系Module和需要注入的类(Activity)之间的桥梁,在Component类中通过inject方法将Module注入到Activity中,如:
1 |
|
dependencies表示在注入时还需要依赖其他Component提供的@Provides方法,此时Activity调用inject方法时会把SplashModule和NetComponent的内容注入到调用的Activity中。
网络组件的注入可以在Application中实现,表示启动初始化的一些参数,这样在用到的时候直接get就可。
如在SplashActivity中调用:
1 | DaggerSplashComponent.builder() |
此时表示将SplashComponent中包含的模块SplashModule、依赖的其他组件NetComponent全部注入到SplashActivity中,此时
1 |
|
等价于
1 | SplashPresenter presenter = new SplashPresenter(this, getApiService); |
6. 系统权限设置
主要使用EasyPermissions框架,实现该框架中的callback,主要的callback方法有:
1 | public void onPermissionsGranted(int requestCode, List<String> perms); |
在onPermissionsGranted中实现权限获取成功后的操作,一般为recreate()方法;
1 | public void onPermissionsGranted(int requestCode, List<String> perms) { |
在onPermissionsDenied中实现权限被拒绝后的操作,比如弹出对话框让用户自己选择是否授权:
1 | public void onPermissionsDenied(int requestCode, List<String> perms) { |
在权限允许后,可以通过注解@AfterPermissionGranted(PERMISSION_REQUEST_CODE)来标识需要执行的方法,在此方法中进行view的加载等。
1 | (PERMISSION_REQUEST_CODE) |
7. SlidingMenu添加左右的滑动Menu
SlidingMenu用于添加界面左边、右边隐藏的菜单Fragment。
对于左右都需要添加的场景,需设置:
1 | slidingMenu.setMode(SlidingMenu.LEFT_RIGHT); |
同时设置slidingMenu依附于此activity:
1 | slidingMenu.attachToActivity(this, SlidingMenu.SLIDING_CONTENT); |
接着添加左右各自的Fragment:
1 | slidingMenu.setMenu(R.layout.left_menu); |
点击某个图标,显示相应的Fragment:
1 | ({R.id.left_slide, R.id.right_slide}) |
当显示的Fragment关闭时,需要重新显示Activity,通过RxBus发出事件来实现:
具体的,在Activity中的onCreate方法中添加观察对象,
1 | subscription = RxBus.getInstance().toObservable(Event.class) |
当菜单Fragment点击关闭按钮时,发出事件:
1 | ({R.id.right_slide_close, R.id.search, R.id.home_page_tv, R.id.words_tv, R.id.voice_tv, R.id.video_tv, R.id.calendar_tv}) |
其中Event为自定义的事件类。
8. Dialog显示每日运势卡片
每到新的一天,第一次打开app时显示运势卡片。
实现方案:自定义“偏好设置”类(PreferenceUtils),在其中分别通过setPrefString、getPrefString方法进行日期的写入和读取;每一次启动app时判断当前日期和记录的日期是否相同,不相同则显示运势卡片。
具体的,PreferenceUtils类:
1 | public class PreferenceUtils { |
每次启动app时,在onCreate方法中获取当前日期:
1 |
|
如果当前日期和存入的日期不相等,则说明是新的一天,此时调用loadRecommend方法(通过presenter得到具体的数据):
1 | private void loadRecommend() { |
getRecommend方法利用RxJava首先调用网络获得数据,对于获得到的数据在onNext中控制View并进行显示(showLunar)。
1 |
|
showLunar方法用于显示LunarDialog,每次显示时设置当前日期:
1 |
|
9. ScrollView滑动时动态显示Toolbar颜色
布局文件中滑动的标签为<ObservableScrollView>,同时设置Toolbar,具体表现为:
1 | <com.github.ksoichiro.android.observablescrollview.ObservableScrollView |
Activity中实现ObservableScrollViewCallbacks接口,实现onScrollChanged方法,在该方法中动态改变颜色:
1 | public void onScrollChanged(int i, boolean b, boolean b1) { |
其中mParallaxImageHeight在onCreate的时候赋值设置
1 | mParallaxImageHeight = getResources().getDimensionPixelSize(R.dimen.parallax_image_height); |
9. Handler的使用
该项目中,Handler有两种用处:
- 作为通信的一种方式
在加载HTML数据时,首先获得HTML的Document类型数据doc,接着对doc进行解析。将解析的方法放在一个Handler中,当得到doc时发出一个消息,此时Handler再进行doc的解析。
1 | private void loadHtmlString(final String paramString) { |
1 | private Handler handler = new Handler() { |
- 在其中开启一个子线程执行相应操作(如:当正在播放时,实时更新seekBar进度的显示)
1 | Handler handleProgress = new Handler(); |
当正在播放时Handler提交(post)该线程:
1 | private void playTimer() { |
当activity销毁时,取消线程的回调:
1 |
|
9. 自定义垂直ViewPager
setWillNotDraw:重写ViewGroup的onDraw方法,需要将该属性设置为false;
setDescendantFocusability:设置ViewGroup的子View获得焦点的能力,FOCUS_AFTER_DESCENDANTS
该参数表明子View优先处理焦点,如果所有的子View都没有处理,则 ViewGroup 自身再处理;
Interpolator:设置动画的插值属性;
getScaledPagingTouchSlop:触发移动事件的最小距离,如果小于这个距离就不触发移动控件,viewPager用这个来判断是否翻页;
AccessibilityDelegate:对view做一个检测,包括view的点击,选中,滑动,touch,文本变化及描述等等,可以用来做一些数据统计或者分析;
setDrawingCacheEnable:提高绘图速度。
10. 写一个RxBus类
1 | public class RxBus { |
11. 文件操作
- 获取文件夹大小
1 | private float getDirSize(File file) { |
- 创建文件夹
1 | public static void createSdDir() { |
- 判断文件是否存在
1 | public static boolean isFileExist(String paramString) { |
- 创建文件
1 | public static File createFile(String fileName) throws IOException{ |
- 获取文件夹中所有文件名字
1 | public static List<String> getAllAD(){ |