├── .gitignore ├── README.md ├── build.gradle ├── fastandroid ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── hunter │ │ └── fastandroid │ │ └── ApplicationTest.java │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── hunter │ │ └── fastandroid │ │ ├── app │ │ ├── ActivityManager.java │ │ ├── BaseApplication.java │ │ ├── Constants.java │ │ ├── DaoManager.java │ │ ├── ServiceManager.java │ │ ├── Setting.java │ │ ├── URLs.java │ │ └── UserManager.java │ │ ├── base │ │ ├── BaseActivity.java │ │ ├── BaseFragment.java │ │ ├── BasePresenter.java │ │ ├── BaseRecyclerAdapter.java │ │ ├── CustomBaseAdapter.java │ │ ├── CustomFragmentPagerAdapter.java │ │ ├── CustomPagerAdapter.java │ │ ├── IBaseView.java │ │ └── RecyclerViewHolder.java │ │ ├── exception │ │ ├── ApiException.java │ │ └── CommonException.java │ │ ├── presenter │ │ └── TestPresenter.java │ │ ├── rx │ │ ├── CommonSubscriber.java │ │ ├── JsonResponseFunc.java │ │ ├── JsonResponseObserver.java │ │ ├── ResponseObserver.java │ │ └── ResponseSubscriber.java │ │ ├── service │ │ └── TestService.java │ │ ├── ui │ │ ├── activity │ │ │ ├── LoginActivity.java │ │ │ └── MainActivity.java │ │ ├── adapter │ │ │ └── BookAdapter.java │ │ ├── interfaces │ │ │ └── ITestView.java │ │ └── widget │ │ │ ├── CountDownButton.java │ │ │ ├── CustomGridView.java │ │ │ ├── CustomListView.java │ │ │ ├── CustomProgress.java │ │ │ ├── NoZoomControllWebView.java │ │ │ └── TitleBar.java │ │ ├── utils │ │ ├── CommonUtils.java │ │ ├── DateUtils.java │ │ ├── DialogUtils.java │ │ ├── FileInfoUtils.java │ │ ├── ImageLoadUtils.java │ │ ├── MyStringUtils.java │ │ ├── NetUtils.java │ │ ├── NumberUtils.java │ │ ├── PixelUtils.java │ │ ├── SdCardUtils.java │ │ └── SystemUtils.java │ │ └── vo │ │ ├── Book.java │ │ ├── DoubanResponse.java │ │ ├── JsonResponse.java │ │ ├── Page.java │ │ └── User.java │ └── res │ ├── anim │ ├── push_left_in.xml │ ├── push_left_out.xml │ ├── push_right_in.xml │ └── push_right_out.xml │ ├── drawable │ └── bg_progress.xml │ ├── layout │ ├── activity_main.xml │ ├── common_header.xml │ ├── common_header_leftbutton.xml │ ├── common_header_rightbutton.xml │ ├── include_title_bar.xml │ ├── item_book.xml │ ├── layout_back.xml │ └── progress.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ ├── ic_launcher.png │ └── nav_back.png │ ├── mipmap-xxhdpi │ ├── ic_launcher.png │ └── nav_back.png │ ├── mipmap-xxxhdpi │ └── ic_launcher.png │ └── values │ ├── color.xml │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── gradlew ├── gradlew.bat ├── res ├── alipay.jpg └── wxpay.jpg └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea 5 | .DS_Store 6 | /build 7 | /captures 8 | gradle 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FastAndroid 2.1 因为简单,所以快速 2 |

官方交流群:310262562

3 |

如有疑问或建议,可联系作者微信:han54001 (请备注交流FA)

4 | 全新改版 5 | 6 | 1.图片加载库改为 glide
7 | 2.更新butterknife
8 | 3.加入Rxjava & retrofit
9 | 4.更改MVP结构,更加方便快捷
10 | 5.精简框架,更加轻便快捷
11 | 12 |

更新日志

13 | 14 |

2017.1.11

15 | 1.新增 GreenDao 3.2 支持
16 | 2.新增 RxLifecycle 支持
17 | 18 |

2017.6.20

19 | 1.新增演示代码(无法运行,仅作为使用演示)
20 | 21 |

2018.8.21

22 | 1.全新支持RxJava2.0
23 | 2.替换所有旧版本的依赖
24 | 3.剔除无用的demo
25 | 26 |

2018.8.27

27 | 1.使用"豆瓣图书Api V2--搜索图书"接口作为演示 28 | 29 | # 捐助 30 | 31 | FastAndroid 是免费开源项目,不会收取任何费用。作者维护这个项目需要耗费不少精力,如果FastAndroid帮到了你,你可以捐款让这个项目变得更好。当然,无论是否捐款,都感谢您对本项目的支持。 32 | 33 | **捐款是纯粹自愿的捐助行为,我将非常感谢您的捐助,但您本人并不会因为您的捐款而获得比其他不捐款用户更多的权利,望理解。** 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | 5 | repositories { 6 | google() 7 | jcenter() 8 | mavenCentral() // add repository 9 | } 10 | dependencies { 11 | classpath 'com.android.tools.build:gradle:3.3.0-alpha03' 12 | classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2' // add plugin 13 | 14 | // NOTE: Do not place your application dependencies here; they belong 15 | // in the individual module build.gradle files 16 | } 17 | } 18 | 19 | allprojects { 20 | repositories { 21 | google() 22 | jcenter() 23 | } 24 | } 25 | 26 | task clean(type: Delete) { 27 | delete rootProject.buildDir 28 | } 29 | -------------------------------------------------------------------------------- /fastandroid/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /fastandroid/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'org.greenrobot.greendao' // apply plugin 3 | 4 | android { 5 | compileSdkVersion 27 6 | defaultConfig { 7 | applicationId "com.hunter.fastandroid" 8 | minSdkVersion 18 9 | targetSdkVersion 26 10 | versionCode 201 11 | versionName "2.0.1" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | greendao{ 20 | schemaVersion 1 21 | daoPackage 'cache.greendao' 22 | } 23 | } 24 | 25 | 26 | dependencies { 27 | implementation fileTree(dir: 'libs', include: ['*.jar']) 28 | implementation 'com.android.support:appcompat-v7:27.1.1' 29 | implementation 'com.android.support:recyclerview-v7:27.1.1' 30 | // Glide 31 | implementation 'com.github.bumptech.glide:glide:4.8.0' 32 | annotationProcessor 'com.github.bumptech.glide:compiler:4.8.0' 33 | // Butterknife 34 | implementation 'com.jakewharton:butterknife:8.8.1' 35 | annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1' 36 | // RxJava 37 | implementation 'io.reactivex.rxjava2:rxjava:2.2.0' 38 | // RxAndroid 39 | implementation 'io.reactivex.rxjava2:rxandroid:2.1.0' 40 | // RxLifecycle 41 | implementation 'com.trello.rxlifecycle2:rxlifecycle-components:2.2.2' 42 | // Retrofit 43 | implementation 'com.squareup.retrofit2:retrofit:2.4.0' 44 | implementation 'com.squareup.retrofit2:converter-gson:2.4.0' 45 | implementation 'com.squareup.retrofit2:adapter-rxjava2:2.4.0' 46 | // Okhttp 47 | implementation 'com.squareup.okhttp3:okhttp:3.11.0' 48 | implementation 'com.squareup.okhttp3:logging-interceptor:3.11.0' 49 | // Gson 50 | implementation 'com.google.code.gson:gson:2.8.5' 51 | // GreenDao 52 | implementation 'org.greenrobot:greendao:3.2.2' 53 | // Logger 54 | implementation 'com.orhanobut:logger:2.2.0' 55 | // SystemBarTint 56 | implementation 'com.readystatesoftware.systembartint:systembartint:1.0.3' 57 | // AVLoadingIndicatorView 58 | implementation 'com.wang.avi:library:2.1.3' 59 | } 60 | -------------------------------------------------------------------------------- /fastandroid/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in D:\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /fastandroid/src/androidTest/java/com/hunter/fastandroid/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /fastandroid/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 16 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/app/ActivityManager.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.app; 2 | 3 | /** 4 | * Created by Administrator on 2017/6/7. 5 | */ 6 | 7 | import android.app.Activity; 8 | 9 | import java.util.Stack; 10 | 11 | /** 12 | * activity管理类 13 | * 14 | */ 15 | public class ActivityManager { 16 | /** 17 | * 接收activity的Stack 18 | */ 19 | private static Stack activityStack = new Stack<>(); 20 | private static ActivityManager activityManager = new ActivityManager(); 21 | 22 | private ActivityManager(){} 23 | 24 | /** 25 | * 单实例 26 | * 27 | * @return 28 | */ 29 | public static ActivityManager getInstance() { 30 | return activityManager; 31 | } 32 | 33 | 34 | /** 35 | * 将activity移出栈 36 | * 37 | * @param activity 38 | */ 39 | public void popActivity(Activity activity) { 40 | if (activity != null) { 41 | activityStack.remove(activity); 42 | } 43 | } 44 | 45 | /** 46 | * 结束指定activity 47 | * 48 | * @param activity 49 | */ 50 | public void endActivity(Activity activity) { 51 | if (activity != null) { 52 | activity.finish(); 53 | activityStack.remove(activity); 54 | activity = null; 55 | } 56 | } 57 | 58 | /** 59 | * 获得当前的activity(即最上层) 60 | * 61 | * @return 62 | */ 63 | public Activity currentActivity() { 64 | Activity activity = null; 65 | if (!activityStack.empty()) 66 | activity = activityStack.lastElement(); 67 | return activity; 68 | } 69 | 70 | /** 71 | * 将activity推入栈内 72 | * 73 | * @param activity 74 | */ 75 | public void pushActivity(Activity activity) { 76 | if (activityStack == null) { 77 | activityStack = new Stack(); 78 | } 79 | activityStack.add(activity); 80 | } 81 | 82 | /** 83 | * 弹出除cls外的所有activity 84 | * 85 | * @param cls 86 | */ 87 | public void popAllActivityExceptOne(Class cls) { 88 | while (true) { 89 | Activity activity = currentActivity(); 90 | if (activity == null) { 91 | break; 92 | } 93 | if (activity.getClass().equals(cls)) { 94 | break; 95 | } 96 | popActivity(activity); 97 | } 98 | } 99 | 100 | /** 101 | * 结束除cls之外的所有activity,执行结果都会清空Stack 102 | * 103 | * @param cls 104 | */ 105 | public void finishAllActivityExceptOne(Class cls) { 106 | while (!activityStack.empty()) { 107 | Activity activity = currentActivity(); 108 | if (activity.getClass().equals(cls)) { 109 | popActivity(activity); 110 | } else { 111 | endActivity(activity); 112 | } 113 | } 114 | } 115 | 116 | /** 117 | * 结束所有activity 118 | */ 119 | public void finishAllActivity() { 120 | while (!activityStack.empty()) { 121 | Activity activity = currentActivity(); 122 | endActivity(activity); 123 | } 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/app/BaseApplication.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.app; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | 6 | import com.orhanobut.logger.AndroidLogAdapter; 7 | import com.orhanobut.logger.Logger; 8 | 9 | /** 10 | * 自定义应用入口 11 | * 12 | * @author Hunter 13 | */ 14 | public class BaseApplication extends Application { 15 | private static BaseApplication mInstance; 16 | 17 | public static Context getInstance() { 18 | return mInstance; 19 | } 20 | 21 | @Override 22 | public void onCreate() { 23 | super.onCreate(); 24 | 25 | mInstance = this; 26 | 27 | Logger.addLogAdapter(new AndroidLogAdapter()); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/app/Constants.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.app; 2 | 3 | /** 4 | * 全局变量存储类 5 | * 6 | * @author Hunter 7 | */ 8 | public class Constants { 9 | 10 | // 数据库名称 11 | public static final String DATABASE_NAME = "leshow"; 12 | 13 | } 14 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/app/DaoManager.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.app; 2 | 3 | import cache.greendao.DaoMaster; 4 | import cache.greendao.DaoSession; 5 | import cache.greendao.UserDao; 6 | 7 | /** 8 | * GreenDao 操作管理器 9 | * 10 | * @author Hunter 11 | */ 12 | public class DaoManager { 13 | private static DaoManager instance; 14 | 15 | private DaoSession daoSession; 16 | 17 | private DaoManager() { 18 | } 19 | 20 | public static DaoManager getInstance() { 21 | if (instance == null) { 22 | synchronized (DaoManager.class) { 23 | if (instance == null) 24 | instance = new DaoManager(); 25 | } 26 | } 27 | 28 | return instance; 29 | } 30 | 31 | private DaoSession getDaoSession() { 32 | if (daoSession == null) { 33 | // 可在此自定义版本升级时的操作,当前默认为删除旧版本所有数据 34 | daoSession = DaoMaster.newDevSession(BaseApplication.getInstance(), Constants.DATABASE_NAME); 35 | } 36 | 37 | return daoSession; 38 | } 39 | 40 | public UserDao getUserDao() { 41 | return getDaoSession().getUserDao(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/app/ServiceManager.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.app; 2 | 3 | import com.hunter.fastandroid.utils.CommonUtils; 4 | 5 | import java.io.IOException; 6 | import java.util.TreeSet; 7 | 8 | import okhttp3.HttpUrl; 9 | import okhttp3.Interceptor; 10 | import okhttp3.OkHttpClient; 11 | import okhttp3.Request; 12 | import okhttp3.Response; 13 | import okhttp3.logging.HttpLoggingInterceptor; 14 | import retrofit2.Retrofit; 15 | import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; 16 | import retrofit2.converter.gson.GsonConverterFactory; 17 | 18 | /** 19 | * Retrofit Service管理器 20 | * 21 | * @author Hunter 22 | */ 23 | public class ServiceManager { 24 | private static ServiceManager instance; 25 | 26 | private ServiceManager() { 27 | 28 | } 29 | 30 | public static ServiceManager getInstance() { 31 | if (instance == null) { 32 | instance = new ServiceManager(); 33 | } 34 | 35 | return instance; 36 | } 37 | 38 | public T getService(Class t) { 39 | return getService(URLs.BASE_URL, t); 40 | } 41 | 42 | public T getService(String baseUrl, Class t) { 43 | HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(); 44 | httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); 45 | OkHttpClient.Builder builder = new OkHttpClient.Builder() 46 | .addInterceptor(httpLoggingInterceptor) 47 | .addInterceptor(new Interceptor() { 48 | @Override 49 | public Response intercept(Chain chain) throws IOException { 50 | Request request = chain.request(); 51 | 52 | HttpUrl url = request.url(); 53 | TreeSet sortParams = new TreeSet<>(url.queryParameterNames()); 54 | StringBuilder stringBuilder = new StringBuilder(); 55 | 56 | for(String param : sortParams){ 57 | String paramValue = url.queryParameter(param); 58 | stringBuilder.append(param + ":" + paramValue + "&"); 59 | } 60 | 61 | String sign = CommonUtils.EncryptMD5(stringBuilder.toString() + "abc123"); 62 | 63 | Request build = request.newBuilder() 64 | .addHeader("appVersion", "") 65 | .addHeader("uid", "") 66 | .addHeader("time", "") 67 | .addHeader("sign", sign) 68 | .build(); 69 | 70 | return chain.proceed(build); 71 | } 72 | }); 73 | 74 | Retrofit retrofit = new Retrofit.Builder() 75 | .baseUrl(baseUrl) 76 | .client(builder.build()) 77 | .addConverterFactory(GsonConverterFactory.create()) 78 | .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) 79 | .build(); 80 | 81 | return retrofit.create(t); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/app/Setting.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.app; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.content.SharedPreferences; 6 | import android.content.SharedPreferences.Editor; 7 | 8 | /** 9 | * 配置文件操作类 10 | * 11 | * @author Hunter 12 | */ 13 | public class Setting { 14 | 15 | private SharedPreferences mSharedPreferences; 16 | private Editor mEditor; 17 | 18 | public Setting(Context context, String name) { 19 | mSharedPreferences = context.getSharedPreferences(name, 20 | Activity.MODE_PRIVATE); 21 | } 22 | 23 | /** 24 | * 加载一个String数据 25 | * 26 | * @param key 目标数据的key 27 | * @return 目标数据, 无则返回空字符串 28 | */ 29 | public String loadString(String key) { 30 | return mSharedPreferences.getString(key, ""); 31 | } 32 | 33 | /** 34 | * 加载一个int类型的数据 35 | * 36 | * @param key 目标数据的key 37 | * @return 目标数据, 无则返回-1 38 | */ 39 | public int loadInt(String key) { 40 | return mSharedPreferences.getInt(key, -1); 41 | } 42 | 43 | /** 44 | * 加载一个long类型的数据 45 | * 46 | * @param key 目标数据的key 47 | * @return 目标数据, 无则返回-1 48 | */ 49 | public long loadLong(String key) { 50 | return mSharedPreferences.getLong(key, -1); 51 | } 52 | 53 | /** 54 | * 加载一个boolean类型的数据 55 | * 56 | * @param key 目标数据的key 57 | * @return 目标数据, 无则返回false 58 | */ 59 | public boolean loadBoolean(String key) { 60 | return mSharedPreferences.getBoolean(key, false); 61 | } 62 | 63 | /** 64 | * 加载一个float类型的数据 65 | * 66 | * @param key 目标数据的key 67 | * @return 目标数据, 无则返回-1 68 | */ 69 | public float loadFloat(String key) { 70 | return mSharedPreferences.getFloat(key, -1); 71 | } 72 | 73 | /** 74 | * 以k-v形式保存一个String数据 75 | */ 76 | public void saveString(String key, String value) { 77 | if (mEditor == null) 78 | mEditor = mSharedPreferences.edit(); 79 | 80 | mEditor.putString(key, value); 81 | mEditor.commit(); 82 | } 83 | 84 | /** 85 | * 以k-v保存一个int类型的数据 86 | */ 87 | public void saveInt(String key, int value) { 88 | if (mEditor == null) 89 | mEditor = mSharedPreferences.edit(); 90 | 91 | mEditor.putInt(key, value); 92 | mEditor.commit(); 93 | } 94 | 95 | /** 96 | * 以k-v保存一个long类型的数据 97 | */ 98 | public void saveLong(String key, long value) { 99 | if (mEditor == null) 100 | mEditor = mSharedPreferences.edit(); 101 | 102 | mEditor.putLong(key, value); 103 | mEditor.commit(); 104 | } 105 | 106 | /** 107 | * 以k-v保存一个boolean类型的数据 108 | */ 109 | public void saveBoolean(String key, boolean value) { 110 | if (mEditor == null) 111 | mEditor = mSharedPreferences.edit(); 112 | 113 | mEditor.putBoolean(key, value); 114 | mEditor.commit(); 115 | } 116 | 117 | /** 118 | * 以k-v保存一个float类型的数据 119 | */ 120 | public void saveFloat(String key, float value) { 121 | if (mEditor == null) 122 | mEditor = mSharedPreferences.edit(); 123 | 124 | mEditor.putFloat(key, value); 125 | mEditor.commit(); 126 | } 127 | 128 | /** 129 | * 清空数据 130 | */ 131 | public void clear() { 132 | if (mEditor == null) 133 | mEditor = mSharedPreferences.edit(); 134 | 135 | mEditor.clear(); 136 | mEditor.commit(); 137 | } 138 | 139 | } 140 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/app/URLs.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.app; 2 | 3 | /** 4 | * URL路径处理类 5 | * 6 | * @author Hunter 7 | */ 8 | public class URLs { 9 | public static final String BASE_URL = "https://api.douban.com/v2/"; 10 | public static final String MODUEL_BOOK = "book"; 11 | 12 | public static final String SEARCH = "/search"; 13 | } 14 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/app/UserManager.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.app; 2 | 3 | import com.hunter.fastandroid.vo.User; 4 | 5 | import java.util.List; 6 | 7 | import cache.greendao.UserDao; 8 | 9 | /** 10 | * Created by Administrator on 2017/1/10. 11 | */ 12 | public class UserManager { 13 | private static UserManager instance; 14 | private User currentUser; 15 | 16 | private UserManager() { 17 | } 18 | 19 | public static UserManager getInstance() { 20 | if (instance == null) { 21 | synchronized (UserManager.class) { 22 | if (instance == null) 23 | instance = new UserManager(); 24 | } 25 | } 26 | 27 | return instance; 28 | } 29 | 30 | /** 31 | * 保存用户信息,该方法一般用于登录成功后调用 (用户数据先放入内存,然后序列化到本地.如果本地已存在,则更新) 32 | * 33 | * @param user 34 | */ 35 | public void setCurrentUser(User user) { 36 | currentUser = user; 37 | 38 | DaoManager daoManager = DaoManager.getInstance(); 39 | UserDao userDao = daoManager.getUserDao(); 40 | userDao.insertOrReplace(user); 41 | } 42 | 43 | /** 44 | * 清空用户信息,包括内存以及本地的数据 45 | */ 46 | public void clearUserInfo() { 47 | currentUser = null; 48 | 49 | DaoManager daoManager = DaoManager.getInstance(); 50 | UserDao userDao = daoManager.getUserDao(); 51 | userDao.deleteAll(); 52 | } 53 | 54 | /** 55 | * 获取用户ID 56 | * @return 57 | */ 58 | public String getCurrentUserID() { 59 | if (getCurrentUser() == null) return ""; 60 | 61 | return String.valueOf(getCurrentUser().getId()); 62 | } 63 | 64 | 65 | /** 66 | * 获取用户令牌 67 | * @return 68 | */ 69 | public String getCurrentUserToken() { 70 | if (currentUser == null) return ""; 71 | 72 | return currentUser.getUserToken(); 73 | } 74 | 75 | /** 76 | * 当前是否已经登录 77 | * 78 | * @return 79 | */ 80 | public boolean isLogin() { 81 | return getCurrentUser() != null; 82 | } 83 | 84 | /** 85 | * 获取当前用户信息 86 | * @return 87 | */ 88 | public User getCurrentUser() { 89 | if (currentUser == null) { 90 | DaoManager daoManager = DaoManager.getInstance(); 91 | UserDao userDao = daoManager.getUserDao(); 92 | List users = userDao.loadAll(); 93 | if (users != null && users.size() > 0) { 94 | currentUser = users.get(0); 95 | } 96 | } 97 | 98 | return currentUser; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/base/BaseActivity.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.base; 2 | 3 | import android.app.ProgressDialog; 4 | import android.content.Context; 5 | import android.content.DialogInterface; 6 | import android.content.Intent; 7 | import android.os.Build; 8 | import android.os.Bundle; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | import android.view.Window; 12 | import android.view.WindowManager; 13 | import android.widget.Toast; 14 | 15 | import com.hunter.fastandroid.R; 16 | import com.hunter.fastandroid.app.ActivityManager; 17 | import com.hunter.fastandroid.app.UserManager; 18 | import com.hunter.fastandroid.ui.activity.LoginActivity; 19 | import com.hunter.fastandroid.ui.activity.MainActivity; 20 | import com.hunter.fastandroid.ui.widget.CustomProgress; 21 | import com.hunter.fastandroid.utils.CommonUtils; 22 | import com.readystatesoftware.systembartint.SystemBarTintManager; 23 | import com.trello.rxlifecycle2.LifecycleTransformer; 24 | import com.trello.rxlifecycle2.components.support.RxAppCompatActivity; 25 | 26 | import java.util.concurrent.TimeUnit; 27 | 28 | import butterknife.ButterKnife; 29 | import io.reactivex.Observable; 30 | import io.reactivex.Observer; 31 | import io.reactivex.android.schedulers.AndroidSchedulers; 32 | import io.reactivex.schedulers.Schedulers; 33 | 34 | /** 35 | * Activity基类 36 | * 37 | * @author Hunter 38 | */ 39 | public abstract class BaseActivity extends RxAppCompatActivity implements IBaseView { 40 | private Toast toast; 41 | private ProgressDialog mProgressDialog; 42 | 43 | /** 44 | * 填充一个后退按钮 45 | * 46 | * @return 47 | */ 48 | public View fillBackButton() { 49 | return fillBackButton(new View.OnClickListener() { 50 | @Override 51 | public void onClick(View v) { 52 | close(); 53 | } 54 | }); 55 | } 56 | 57 | /** 58 | * 填充一个后退按钮 59 | * 60 | * @return 61 | */ 62 | public View fillBackButton(View.OnClickListener onClickListener) { 63 | View backButton = View.inflate(this, R.layout.layout_back, null); 64 | 65 | backButton.setOnClickListener(onClickListener); 66 | 67 | return backButton; 68 | } 69 | 70 | /** 71 | * 初始化控件 72 | */ 73 | public abstract void initView(); 74 | 75 | /** 76 | * 初始化控制中心 77 | */ 78 | public abstract void initPresenter(); 79 | 80 | @Override 81 | protected void onCreate(Bundle savedInstanceState) { 82 | super.onCreate(savedInstanceState); 83 | setContentView(getContentResId()); 84 | initStatusBar(); 85 | // 初始化View注入 86 | ButterKnife.bind(this); 87 | initPresenter(); 88 | initView(); 89 | 90 | ActivityManager.getInstance().pushActivity(this); 91 | } 92 | 93 | public void goHome() { 94 | CommonUtils.hideSoftInput(this); 95 | finish(); 96 | openPage(MainActivity.class); 97 | ActivityManager.getInstance().finishAllActivityExceptOne(MainActivity.class); 98 | } 99 | 100 | public void backHome() { 101 | finish(); 102 | ActivityManager.getInstance().finishAllActivityExceptOne(MainActivity.class); 103 | } 104 | 105 | /** 106 | * 是否启用沉浸式 107 | * 108 | * @return 109 | */ 110 | public boolean isImmersion() { 111 | return true; 112 | } 113 | 114 | /** 115 | * 初始化沉侵式状态栏 116 | */ 117 | public void initStatusBar() { 118 | if (isImmersion()) { 119 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 120 | Window window = getWindow(); 121 | // Translucent status bar 122 | window.setFlags( 123 | WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, 124 | WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 125 | ViewGroup contentLayout = (ViewGroup) findViewById(Window.ID_ANDROID_CONTENT); 126 | View parentView = contentLayout.getChildAt(0); 127 | if (parentView != null) { 128 | parentView.setFitsSystemWindows(true); 129 | } 130 | } 131 | 132 | initStatsBarColor(); 133 | } 134 | } 135 | 136 | /** 137 | * 获取状态栏高度 138 | * 139 | * @return 140 | */ 141 | public int getStatusBarHeight() { 142 | int result = 0; 143 | int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android"); 144 | if (resourceId > 0) { 145 | result = getResources().getDimensionPixelSize(resourceId); 146 | } 147 | return result; 148 | } 149 | 150 | public void initStatsBarColor() { 151 | initStatsBarColor(0); 152 | } 153 | 154 | public void initStatsBarColor(int color) { 155 | SystemBarTintManager systemBarTintManager = new SystemBarTintManager(this); 156 | systemBarTintManager.setStatusBarTintEnabled(true); 157 | if (color == 0) { 158 | systemBarTintManager.setStatusBarTintResource(R.color.colorPrimary); 159 | } else { 160 | systemBarTintManager.setStatusBarTintResource(color); 161 | } 162 | } 163 | 164 | protected abstract int getContentResId(); 165 | 166 | @Override 167 | public Context getContext() { 168 | return this; 169 | } 170 | 171 | @Override 172 | public void finish() { 173 | super.finish(); 174 | ActivityManager.getInstance().popActivity(this); 175 | } 176 | 177 | @Override 178 | public void showProgress(final boolean flag, final String message) { 179 | showLoading(flag, message); 180 | } 181 | 182 | private void showLoading(boolean flag, String message) { 183 | if (mProgressDialog == null) { 184 | mProgressDialog = new CustomProgress(this, R.style.CustomDialog); 185 | mProgressDialog.setCanceledOnTouchOutside(false); 186 | } 187 | mProgressDialog.setCancelable(flag); 188 | mProgressDialog.setMessage(message); 189 | 190 | if(!mProgressDialog.isShowing()){ 191 | mProgressDialog.show(); 192 | } 193 | } 194 | 195 | @Override 196 | public void showProgress(String message) { 197 | showProgress(true, message); 198 | } 199 | 200 | @Override 201 | public void showProgress(int strRes) { 202 | showProgress(getString(strRes)); 203 | } 204 | 205 | @Override 206 | public void hideProgress() { 207 | if (mProgressDialog == null) 208 | return; 209 | 210 | if (mProgressDialog.isShowing()) { 211 | mProgressDialog.dismiss(); 212 | } 213 | } 214 | 215 | @Override 216 | public void setProgressCancelListener(DialogInterface.OnCancelListener onCancelListener) { 217 | if (mProgressDialog != null) { 218 | mProgressDialog.setOnCancelListener(onCancelListener); 219 | } 220 | } 221 | 222 | @Override 223 | public void showToast(String msg) { 224 | if (!isFinishing()) { 225 | if (toast == null) { 226 | toast = Toast.makeText(this, msg, Toast.LENGTH_SHORT); 227 | } else { 228 | toast.setText(msg); 229 | } 230 | 231 | toast.show(); 232 | } 233 | } 234 | 235 | @Override 236 | public void showToast(int res) { 237 | showToast(getString(res)); 238 | } 239 | 240 | @Override 241 | public void openPage(Class clazz) { 242 | openPage(new Intent(this, clazz)); 243 | } 244 | 245 | public void finishAndOpenPage(Class clazz){ 246 | finish(); 247 | openPage(clazz); 248 | } 249 | 250 | @Override 251 | public void openPage(Intent intent) { 252 | startActivity(intent); 253 | overridePendingTransition(R.anim.push_left_in, R.anim.push_left_out); 254 | } 255 | 256 | @Override 257 | public void openPageForResult(Intent intent, int requestCode) { 258 | startActivityForResult(intent, requestCode); 259 | overridePendingTransition(R.anim.push_left_in, R.anim.push_left_out); 260 | } 261 | 262 | @Override 263 | public void close() { 264 | finish(); 265 | overridePendingTransition(R.anim.push_right_in, R.anim.push_right_out); 266 | } 267 | 268 | /** 269 | * 开始执行一个延时任务 270 | * @param delay 271 | * @param unit 272 | * @param observer 273 | */ 274 | @Override 275 | public void startDelayAsync(long delay, TimeUnit unit, Observer observer) { 276 | startAsync(Observable.timer(delay, unit), observer); 277 | } 278 | 279 | /** 280 | * 开始执行一个定时任务 281 | * @param period 282 | * @param unit 283 | * @param observer 284 | */ 285 | @Override 286 | public void startIntervalAsync(long period, TimeUnit unit, Observer observer) { 287 | startAsync(Observable.interval(period, unit), observer); 288 | } 289 | 290 | /** 291 | * 开始执行一个异步任务 292 | * 293 | * @param observable 294 | * @param observer 295 | * @param 296 | */ 297 | @Override 298 | public void startAsync(Observable observable, Observer observer) { 299 | observable 300 | .subscribeOn(Schedulers.io()) 301 | .unsubscribeOn(Schedulers.io()) 302 | .observeOn(AndroidSchedulers.mainThread()) 303 | .compose(this.bind()) 304 | .subscribe(observer); 305 | } 306 | 307 | @Override 308 | public void clearUser() { 309 | UserManager.getInstance().clearUserInfo(); 310 | openPage(LoginActivity.class); 311 | ActivityManager.getInstance().finishAllActivityExceptOne(LoginActivity.class); 312 | } 313 | 314 | @Override 315 | public LifecycleTransformer bind() { 316 | return bindToLifecycle(); 317 | } 318 | } 319 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/base/BaseFragment.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.base; 2 | 3 | import android.content.Context; 4 | import android.content.DialogInterface; 5 | import android.content.Intent; 6 | import android.os.Bundle; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | 11 | import com.hunter.fastandroid.R; 12 | import com.trello.rxlifecycle2.LifecycleTransformer; 13 | import com.trello.rxlifecycle2.components.support.RxFragment; 14 | 15 | import java.util.concurrent.TimeUnit; 16 | 17 | import butterknife.ButterKnife; 18 | import io.reactivex.Observable; 19 | import io.reactivex.Observer; 20 | import io.reactivex.android.schedulers.AndroidSchedulers; 21 | import io.reactivex.schedulers.Schedulers; 22 | 23 | /** 24 | * Fragment基类 25 | * 26 | * @author Hunter 27 | */ 28 | public abstract class BaseFragment extends RxFragment implements IBaseView { 29 | private View mLayoutView; 30 | 31 | /** 32 | * 初始化布局 33 | */ 34 | public abstract int getLayoutRes(); 35 | 36 | /** 37 | * 初始化视图 38 | */ 39 | public abstract void initView(); 40 | 41 | @Override 42 | public Context getContext() { 43 | return getBaseActivity().getContext(); 44 | } 45 | 46 | @Override 47 | public void onCreate(Bundle savedInstanceState) { 48 | super.onCreate(savedInstanceState); 49 | } 50 | 51 | @Override 52 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 53 | if (mLayoutView != null) { 54 | ViewGroup parent = (ViewGroup) mLayoutView.getParent(); 55 | if (parent != null) { 56 | parent.removeView(mLayoutView); 57 | } 58 | } else { 59 | mLayoutView = getCreateView(inflater, container); 60 | ButterKnife.bind(this, mLayoutView); 61 | initView(); //初始化布局 62 | } 63 | 64 | return mLayoutView; 65 | } 66 | 67 | /** 68 | * 获取Fragment布局文件的View 69 | * 70 | * @param inflater 71 | * @param container 72 | * @return 73 | */ 74 | private View getCreateView(LayoutInflater inflater, ViewGroup container) { 75 | return inflater.inflate(getLayoutRes(), container, false); 76 | } 77 | 78 | /** 79 | * 获取当前Fragment状态 80 | * 81 | * @return true为正常 false为未加载或正在删除 82 | */ 83 | private boolean getStatus() { 84 | return (isAdded() && !isRemoving()); 85 | } 86 | 87 | /** 88 | * 获取Activity 89 | * 90 | * @return 91 | */ 92 | public BaseActivity getBaseActivity() { 93 | return (BaseActivity) getActivity(); 94 | } 95 | 96 | @Override 97 | public void showProgress(boolean flag, String message) { 98 | if (getStatus()) { 99 | getBaseActivity().showProgress(flag, message); 100 | } 101 | } 102 | 103 | @Override 104 | public void showProgress(String message) { 105 | showProgress(true, message); 106 | } 107 | 108 | @Override 109 | public void showProgress(int strRes) { 110 | showProgress(getString(strRes)); 111 | } 112 | 113 | @Override 114 | public void hideProgress() { 115 | if (getStatus()) { 116 | getBaseActivity().hideProgress(); 117 | } 118 | } 119 | 120 | @Override 121 | public void setProgressCancelListener(DialogInterface.OnCancelListener onCancelListener) { 122 | getBaseActivity().setProgressCancelListener(onCancelListener); 123 | } 124 | 125 | @Override 126 | public void showToast(String msg) { 127 | if (getStatus()) { 128 | getBaseActivity().showToast(msg); 129 | } 130 | } 131 | 132 | @Override 133 | public void showToast(int res) { 134 | showToast(getString(res)); 135 | } 136 | 137 | @Override 138 | public void openPage(Class clazz) { 139 | getBaseActivity().openPage(clazz); 140 | } 141 | 142 | @Override 143 | public void openPage(Intent intent) { 144 | getBaseActivity().openPage(intent); 145 | } 146 | 147 | @Override 148 | public void openPageForResult(Intent intent, int requestCode) { 149 | startActivityForResult(intent, requestCode); 150 | getBaseActivity().overridePendingTransition(R.anim.push_left_in, R.anim.push_left_out); 151 | } 152 | 153 | @Override 154 | public void close() { 155 | getBaseActivity().close(); 156 | } 157 | 158 | @Override 159 | public void startAsync(Observable observable, Observer observer) { 160 | observable 161 | .subscribeOn(Schedulers.io()) 162 | .unsubscribeOn(Schedulers.io()) 163 | .observeOn(AndroidSchedulers.mainThread()) 164 | .compose(this.bind()) 165 | .subscribe(observer); 166 | } 167 | 168 | @Override 169 | public void clearUser() { 170 | getBaseActivity().clearUser(); 171 | } 172 | 173 | @Override 174 | public LifecycleTransformer bind() { 175 | return bindToLifecycle(); 176 | } 177 | 178 | @Override 179 | public void startDelayAsync(long delay, TimeUnit unit, Observer observer) { 180 | startAsync(Observable.timer(delay, unit), observer); 181 | } 182 | 183 | @Override 184 | public void startIntervalAsync(long period, TimeUnit unit, Observer observer) { 185 | startAsync(Observable.interval(period, unit), observer); 186 | } 187 | } 188 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/base/BasePresenter.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.base; 2 | 3 | import android.text.TextUtils; 4 | 5 | import com.hunter.fastandroid.R; 6 | import com.hunter.fastandroid.app.ServiceManager; 7 | import com.hunter.fastandroid.rx.JsonResponseFunc; 8 | import com.hunter.fastandroid.utils.MyStringUtils; 9 | import com.hunter.fastandroid.vo.JsonResponse; 10 | 11 | import org.reactivestreams.Subscriber; 12 | 13 | import java.lang.reflect.Field; 14 | import java.util.Collections; 15 | import java.util.HashMap; 16 | import java.util.Map; 17 | 18 | import io.reactivex.Flowable; 19 | import io.reactivex.Observable; 20 | import io.reactivex.Observer; 21 | import io.reactivex.android.schedulers.AndroidSchedulers; 22 | import io.reactivex.schedulers.Schedulers; 23 | 24 | 25 | /** 26 | * Presenter基类 27 | * 28 | * @author Hunter 29 | */ 30 | public abstract class BasePresenter { 31 | 32 | public BasePresenter() { 33 | initService(); 34 | } 35 | 36 | protected abstract void initService(); 37 | 38 | public T getService(Class clazz) { 39 | ServiceManager serviceManager = ServiceManager.getInstance(); 40 | return serviceManager.getService(clazz); 41 | } 42 | 43 | /** 44 | * 普通简单订阅 45 | * @param view 46 | * @param observable 47 | * @param observer 48 | * @param 49 | */ 50 | public void subscribe(IBaseView view, Observable observable, Observer observer) { 51 | observable 52 | .subscribeOn(Schedulers.io()) 53 | .unsubscribeOn(Schedulers.io()) 54 | .observeOn(AndroidSchedulers.mainThread()) 55 | .compose(view.bind()) 56 | .subscribe(observer); 57 | } 58 | 59 | /** 60 | * 转换响应实体的类型 61 | * 62 | * @param observable 63 | * @param 64 | * @return 65 | */ 66 | public Observable convertResponse(Observable> observable) { 67 | return observable.map(new JsonResponseFunc()); 68 | } 69 | 70 | /** 71 | * 转换请求实体类 72 | * 73 | * @param object 74 | * @return 75 | */ 76 | public Map converParams(Object object) { 77 | if (object == null) return Collections.emptyMap(); 78 | 79 | Class clazz = object.getClass(); 80 | Class superclass = clazz.getSuperclass(); 81 | 82 | Field[] fields = clazz.getDeclaredFields(); 83 | Field[] superFields = superclass.getDeclaredFields(); 84 | 85 | if (fields == null || fields.length == 0) { 86 | return Collections.emptyMap(); 87 | } 88 | 89 | Map params = new HashMap(); 90 | try { 91 | for (Field field : fields) { 92 | field.setAccessible(true); 93 | if(field.get(object) != null){ 94 | params.put(field.getName(), String.valueOf(field.get(object))); 95 | } 96 | } 97 | 98 | for (Field superField : superFields) { 99 | superField.setAccessible(true); 100 | if(superField.get(object) != null) { 101 | params.put(superField.getName(), String.valueOf(superField.get(object))); 102 | } 103 | } 104 | 105 | } catch (IllegalAccessException e) { 106 | e.printStackTrace(); 107 | } catch (IllegalArgumentException e) { 108 | e.printStackTrace(); 109 | } 110 | 111 | return params; 112 | } 113 | 114 | /** 115 | * 校验字符串是否为空 116 | * @param baseView 117 | * @param content 需要校验的内容 118 | * @param strRes 为空时的提示语 119 | * @return 120 | */ 121 | public boolean isEmpty(IBaseView baseView, String content, int strRes) { 122 | if (TextUtils.isEmpty(content)) { 123 | baseView.showToast(strRes); 124 | return true; 125 | } 126 | 127 | return false; 128 | } 129 | 130 | /** 131 | * 校验字符串是否为空 132 | * @param baseView 133 | * @param content 需要校验的内容 134 | * @param str 为空时的提示语 135 | * @return 136 | */ 137 | public boolean isEmpty(IBaseView baseView, String content, String str) { 138 | if (TextUtils.isEmpty(content)) { 139 | baseView.showToast(str); 140 | return true; 141 | } 142 | 143 | return false; 144 | } 145 | 146 | /** 147 | * 校验手机号是否有效 148 | * @param baseview 149 | * @param mobile 150 | * @return 151 | */ 152 | public boolean isMobile(IBaseView baseview, String mobile){ 153 | if(!MyStringUtils.checkCellphone(mobile)){ 154 | baseview.showToast(R.string.mobile_valid); 155 | return false; 156 | } 157 | 158 | return true; 159 | } 160 | 161 | 162 | } 163 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/base/BaseRecyclerAdapter.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.base; 2 | 3 | import android.content.Context; 4 | import android.support.annotation.LayoutRes; 5 | import android.support.v7.widget.RecyclerView; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | 10 | import java.util.List; 11 | 12 | /** 13 | * Created by Administrator on 2017/1/16. 14 | */ 15 | public abstract class BaseRecyclerAdapter extends RecyclerView.Adapter { 16 | private List mDatas; 17 | private Context mContext; 18 | private LayoutInflater mInflater; 19 | private OnItemClickListener mOnItemClickListener; 20 | 21 | public BaseRecyclerAdapter(Context context) { 22 | this.mContext = context; 23 | mInflater = (LayoutInflater) mContext 24 | .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 25 | } 26 | 27 | @Override 28 | public RecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 29 | View view = mInflater.inflate(getLayoutId(), parent, false); 30 | return new RecyclerViewHolder(view); 31 | } 32 | 33 | @Override 34 | public void onBindViewHolder(RecyclerViewHolder holder, final int position) { 35 | holder.itemView.setOnClickListener(new View.OnClickListener() { 36 | @Override 37 | public void onClick(View v) { 38 | if (mOnItemClickListener != null) mOnItemClickListener.onItemClick(position); 39 | } 40 | }); 41 | 42 | bindView(holder, position); 43 | } 44 | 45 | abstract public void bindView(RecyclerViewHolder holder, final int position); 46 | 47 | public void setOnItemClickListener(OnItemClickListener onItemClickListener) { 48 | mOnItemClickListener = onItemClickListener; 49 | } 50 | 51 | @LayoutRes 52 | abstract public int getLayoutId(); 53 | 54 | /** 55 | * 获取上下文对象 56 | * 57 | * @return 58 | */ 59 | public Context getContext() { 60 | return mContext; 61 | } 62 | 63 | @Override 64 | public int getItemCount() { 65 | return mDatas == null ? 0 : mDatas.size(); 66 | } 67 | 68 | /** 69 | * 获取指定item数据 70 | * 71 | * @param position 72 | * @return 73 | */ 74 | public T getItemData(int position) { 75 | return mDatas == null ? null : mDatas.get(position); 76 | } 77 | 78 | /** 79 | * 获取数据集合 80 | * 81 | * @return 82 | */ 83 | public List getData() { 84 | return mDatas; 85 | } 86 | 87 | /** 88 | * 设置数据集合 89 | * 90 | * @param datas 91 | */ 92 | public void setData(List datas) { 93 | this.mDatas = datas; 94 | } 95 | 96 | /** 97 | * 移除指定item的数据 98 | * 99 | * @param position 100 | */ 101 | public void removeData(int position) { 102 | this.mDatas.remove(position); 103 | } 104 | 105 | public interface OnItemClickListener { 106 | void onItemClick(int position); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/base/CustomBaseAdapter.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.base; 2 | 3 | import android.content.Context; 4 | import android.view.LayoutInflater; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | import android.widget.BaseAdapter; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * 自定义适配器 13 | * 14 | * @param 数据集合类型 15 | * @author Hunter 16 | */ 17 | public abstract class CustomBaseAdapter extends BaseAdapter { 18 | private LayoutInflater mInflater; 19 | private List mDatas; 20 | private Context mContext; 21 | 22 | public CustomBaseAdapter(Context context) { 23 | mContext = context; 24 | mInflater = (LayoutInflater) mContext 25 | .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 26 | } 27 | 28 | /** 29 | * 获取上下文对象 30 | * 31 | * @return 32 | */ 33 | public Context getContext() { 34 | return mContext; 35 | } 36 | 37 | /** 38 | * 获取item布局 39 | * 40 | * @return 41 | */ 42 | public View getItemView(int resource, ViewGroup parent) { 43 | return mInflater.inflate(resource, parent, false); 44 | } 45 | 46 | /** 47 | * 获取指定item数据 48 | * 49 | * @param position 50 | * @return 51 | */ 52 | public T getItemData(int position) { 53 | return mDatas == null ? null : mDatas.get(position); 54 | } 55 | 56 | /** 57 | * 获取数据集合 58 | * 59 | * @return 60 | */ 61 | public List getData() { 62 | return mDatas; 63 | } 64 | 65 | /** 66 | * 设置数据集合 67 | * 68 | * @param datas 69 | */ 70 | public void setData(List datas) { 71 | this.mDatas = datas; 72 | } 73 | 74 | /** 75 | * 移除指定item的数据 76 | * 77 | * @param position 78 | */ 79 | public void removeData(int position) { 80 | this.mDatas.remove(position); 81 | } 82 | 83 | @Override 84 | public int getCount() { 85 | return mDatas == null ? 0 : mDatas.size(); 86 | } 87 | 88 | @Override 89 | public Object getItem(int position) { 90 | return mDatas == null ? null : mDatas.get(position); 91 | } 92 | 93 | @Override 94 | public long getItemId(int position) { 95 | return 0; 96 | } 97 | 98 | @Override 99 | public abstract View getView(int position, View convertView, ViewGroup parent); 100 | } 101 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/base/CustomFragmentPagerAdapter.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.base; 2 | 3 | import android.support.v4.app.Fragment; 4 | import android.support.v4.app.FragmentManager; 5 | import android.support.v4.app.FragmentPagerAdapter; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | /** 11 | * 自定义Fragment页面适配器 12 | * 13 | * @author Hunter 14 | */ 15 | public class CustomFragmentPagerAdapter extends FragmentPagerAdapter { 16 | List mFragments; 17 | List mTitles; 18 | 19 | public CustomFragmentPagerAdapter(FragmentManager fm) { 20 | super(fm); 21 | } 22 | 23 | /** 24 | * 设置当前adapter的页面集合 25 | * 26 | * @param fragments 27 | */ 28 | public void setPagers(List fragments) { 29 | mFragments = fragments; 30 | } 31 | 32 | /** 33 | * 添加一个页面 34 | * 35 | * @param fragment 36 | */ 37 | public void addPager(Fragment fragment) { 38 | if (mFragments == null) { 39 | ArrayList fragments = new ArrayList(); 40 | fragments.add(fragment); 41 | setPagers(fragments); 42 | } else { 43 | mFragments.add(fragment); 44 | } 45 | } 46 | 47 | /** 48 | * 添加一组页面 49 | * 50 | * @param fragments 51 | */ 52 | public void addPagers(List fragments) { 53 | if (mFragments == null) { 54 | setPagers(fragments); 55 | } else { 56 | mFragments.addAll(fragments); 57 | } 58 | } 59 | 60 | /** 61 | * 设置页面的标题 62 | * 63 | * @param titles 64 | */ 65 | public void setTitles(List titles) { 66 | mTitles = titles; 67 | } 68 | 69 | /** 70 | * 添加一个页面的标题 71 | * 72 | * @param title 73 | */ 74 | public void addTitle(String title) { 75 | if (mTitles == null) { 76 | ArrayList titles = new ArrayList(); 77 | titles.add(title); 78 | setTitles(titles); 79 | } else { 80 | mTitles.add(title); 81 | } 82 | } 83 | 84 | /** 85 | * 添加一组页面的标题 86 | * 87 | * @param titles 88 | */ 89 | public void addTitles(List titles) { 90 | if (mTitles == null) { 91 | setTitles(titles); 92 | } else { 93 | mTitles.addAll(titles); 94 | } 95 | } 96 | 97 | @Override 98 | public CharSequence getPageTitle(int position) { 99 | return mTitles == null ? null : mTitles.get(position); 100 | } 101 | 102 | @Override 103 | public Fragment getItem(int position) { 104 | return mFragments == null ? null : mFragments.get(position); 105 | } 106 | 107 | @Override 108 | public int getCount() { 109 | return mFragments == null ? 0 : mFragments.size(); 110 | } 111 | 112 | } 113 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/base/CustomPagerAdapter.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.base; 2 | 3 | import android.support.v4.app.Fragment; 4 | import android.support.v4.app.FragmentManager; 5 | import android.support.v4.app.FragmentPagerAdapter; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | /** 11 | * 自定义Fragment页面适配器 12 | * 13 | * @author Hunter 14 | */ 15 | public class CustomPagerAdapter extends FragmentPagerAdapter { 16 | List mFragments; 17 | List mTitles; 18 | 19 | public CustomPagerAdapter(FragmentManager fm) { 20 | super(fm); 21 | } 22 | 23 | /** 24 | * 设置当前adapter的页面集合 25 | * 26 | * @param fragments 27 | */ 28 | public void setPagers(List fragments) { 29 | mFragments = fragments; 30 | } 31 | 32 | /** 33 | * 添加一个页面 34 | * 35 | * @param fragment 36 | */ 37 | public void addPager(Fragment fragment) { 38 | if (mFragments == null) { 39 | ArrayList fragments = new ArrayList(); 40 | fragments.add(fragment); 41 | setPagers(fragments); 42 | } else { 43 | mFragments.add(fragment); 44 | } 45 | } 46 | 47 | /** 48 | * 添加一组页面 49 | * 50 | * @param fragments 51 | */ 52 | public void addPagers(List fragments) { 53 | if (mFragments == null) { 54 | setPagers(fragments); 55 | } else { 56 | mFragments.addAll(fragments); 57 | } 58 | } 59 | 60 | /** 61 | * 设置页面的标题 62 | * 63 | * @param titles 64 | */ 65 | public void setTitles(List titles) { 66 | mTitles = titles; 67 | } 68 | 69 | /** 70 | * 添加一个页面的标题 71 | * 72 | * @param title 73 | */ 74 | public void addTitle(String title) { 75 | if (mTitles == null) { 76 | ArrayList titles = new ArrayList(); 77 | titles.add(title); 78 | setTitles(titles); 79 | } else { 80 | mTitles.add(title); 81 | } 82 | } 83 | 84 | /** 85 | * 添加一组页面的标题 86 | * 87 | * @param titles 88 | */ 89 | public void addTitles(List titles) { 90 | if (mTitles == null) { 91 | setTitles(titles); 92 | } else { 93 | mTitles.addAll(titles); 94 | } 95 | } 96 | 97 | @Override 98 | public CharSequence getPageTitle(int position) { 99 | return mTitles == null ? null : mTitles.get(position); 100 | } 101 | 102 | @Override 103 | public Fragment getItem(int position) { 104 | return mFragments == null ? null : mFragments.get(position); 105 | } 106 | 107 | @Override 108 | public int getCount() { 109 | return mFragments == null ? 0 : mFragments.size(); 110 | } 111 | 112 | } 113 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/base/IBaseView.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.base; 2 | 3 | import android.content.Context; 4 | import android.content.DialogInterface; 5 | import android.content.Intent; 6 | 7 | import com.trello.rxlifecycle2.LifecycleTransformer; 8 | 9 | import java.util.concurrent.TimeUnit; 10 | 11 | import io.reactivex.Observable; 12 | import io.reactivex.Observer; 13 | 14 | 15 | /** 16 | * View层接口基类 17 | * 18 | * @author Hunter 19 | */ 20 | public interface IBaseView { 21 | 22 | /** 23 | * 获取上下文对象 24 | * @return 25 | */ 26 | Context getContext(); 27 | 28 | /** 29 | * 显示进度条 30 | * 31 | * @param flag 是否可取消 32 | * @param message 要显示的信息 33 | */ 34 | void showProgress(boolean flag, String message); 35 | 36 | /** 37 | * 显示可取消的进度条 38 | * 39 | * @param message 要显示的信息 40 | */ 41 | void showProgress(String message); 42 | 43 | /** 44 | * 显示可取消的进度条 45 | * @param strRes 46 | */ 47 | void showProgress(int strRes); 48 | 49 | /** 50 | * 隐藏进度条 51 | */ 52 | void hideProgress(); 53 | 54 | /** 55 | * 设置取消进度条监听 56 | * 57 | * @param onCancelListener 58 | */ 59 | void setProgressCancelListener(DialogInterface.OnCancelListener onCancelListener); 60 | 61 | /** 62 | * 根据字符串弹出toast 63 | * 64 | * @param msg 提示内容 65 | */ 66 | void showToast(String msg); 67 | 68 | /** 69 | * 根据字符串资源弹出toast 70 | * @param res 71 | */ 72 | void showToast(int res); 73 | 74 | /** 75 | * 打开指定页面 76 | * @param clazz 77 | */ 78 | void openPage(Class clazz); 79 | 80 | /** 81 | * 根据意图打开页面 82 | * @param intent 83 | */ 84 | void openPage(Intent intent); 85 | 86 | /** 87 | * 带请求的打开页面 88 | * @param intent 89 | * @param requestCode 90 | */ 91 | void openPageForResult(Intent intent, int requestCode); 92 | 93 | /** 94 | * 关闭当前页面 95 | */ 96 | void close(); 97 | 98 | /** 99 | * 开始执行一个延时任务 100 | * @param delay 101 | * @param unit 102 | * @param observer 103 | */ 104 | void startDelayAsync(long delay, TimeUnit unit, Observer observer); 105 | 106 | /** 107 | * 开始执行一个定时任务 108 | * @param period 109 | * @param unit 110 | * @param observer 111 | */ 112 | void startIntervalAsync(long period, TimeUnit unit, Observer observer); 113 | 114 | /** 115 | * 执行一个基于rxjava的异步任务 116 | * @param observable 117 | */ 118 | void startAsync(Observable observable, Observer observer); 119 | 120 | /** 121 | * 清除当前登录用户,并跳转到登录界面 122 | */ 123 | void clearUser(); 124 | 125 | /** 126 | * 关联RxLifecycle 127 | * 128 | * @param 129 | * @return 130 | */ 131 | LifecycleTransformer bind(); 132 | } 133 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/base/RecyclerViewHolder.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.base; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | import android.util.SparseArray; 5 | import android.view.View; 6 | 7 | /** 8 | * Created by Administrator on 2017/1/16. 9 | */ 10 | public class RecyclerViewHolder extends RecyclerView.ViewHolder { 11 | private SparseArray arrayView; 12 | 13 | public RecyclerViewHolder(View itemView) { 14 | super(itemView); 15 | arrayView = new SparseArray<>(); 16 | } 17 | 18 | /** 19 | * 通过填写的itemId来获取具体的View的对象 20 | * @param itemId R.id.*** 21 | * @param 必须是View的子类 22 | * @return 23 | */ 24 | public T getView(int itemId){ 25 | //arrayVie类似于Map容器,get(key)取出的是value值 26 | View mView = arrayView.get(itemId); 27 | if(mView == null){ 28 | //实例化具体的View类型 29 | mView = itemView.findViewById(itemId); 30 | arrayView.put(itemId,mView); 31 | } 32 | return (T) mView; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/exception/ApiException.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.exception; 2 | 3 | 4 | import com.hunter.fastandroid.vo.JsonResponse; 5 | 6 | /** 7 | * 自定义异常 8 | * 9 | * @author Hunter 10 | */ 11 | public class ApiException extends RuntimeException { 12 | private JsonResponse tJsonResponse; 13 | 14 | public ApiException(JsonResponse jsonResponse) { 15 | super(jsonResponse.getMessage()); 16 | tJsonResponse = jsonResponse; 17 | } 18 | 19 | public void setJsonResponse(JsonResponse jsonResponse) { 20 | tJsonResponse = jsonResponse; 21 | } 22 | 23 | public JsonResponse getJsonResponse() { 24 | return tJsonResponse; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/exception/CommonException.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.exception; 2 | 3 | /** 4 | * 自定义异常 5 | * 6 | * @author Hunter 7 | */ 8 | public class CommonException extends RuntimeException { 9 | private String mErrorMsg; 10 | 11 | public CommonException(String errorMsg) { 12 | mErrorMsg = errorMsg; 13 | } 14 | 15 | @Override 16 | public String getMessage() { 17 | return mErrorMsg; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/presenter/TestPresenter.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.presenter; 2 | 3 | import com.hunter.fastandroid.base.BasePresenter; 4 | import com.hunter.fastandroid.rx.ResponseObserver; 5 | import com.hunter.fastandroid.service.TestService; 6 | import com.hunter.fastandroid.ui.interfaces.ITestView; 7 | import com.hunter.fastandroid.vo.DoubanResponse; 8 | 9 | 10 | /** 11 | * Created by Administrator on 2017/1/4. 12 | */ 13 | public class TestPresenter extends BasePresenter { 14 | TestService service; 15 | 16 | @Override 17 | protected void initService() { 18 | service = getService(TestService.class); 19 | } 20 | 21 | public void test(String keyword, final ITestView testView) { 22 | 23 | subscribe(testView, service.test(keyword), new ResponseObserver(testView) { 24 | @Override 25 | public void onNext(DoubanResponse response) { 26 | testView.showData(response.getBooks()); 27 | } 28 | }); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/rx/CommonSubscriber.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.rx; 2 | 3 | 4 | import com.hunter.fastandroid.base.IBaseView; 5 | import com.hunter.fastandroid.exception.CommonException; 6 | import com.orhanobut.logger.Logger; 7 | 8 | import io.reactivex.Observer; 9 | import io.reactivex.disposables.Disposable; 10 | 11 | 12 | /** 13 | * RxJava 自定义Subscriber 14 | * 15 | * @param 16 | * @author Hunter 17 | */ 18 | public abstract class CommonSubscriber implements Observer { 19 | private IBaseView mBaseView; 20 | // 是否显示加载进度条 21 | private boolean mIsShowLoading = true; 22 | 23 | public CommonSubscriber(IBaseView baseView) { 24 | mBaseView = baseView; 25 | } 26 | 27 | public CommonSubscriber(IBaseView baseView, boolean isShowLoading) { 28 | mBaseView = baseView; 29 | mIsShowLoading = isShowLoading; 30 | } 31 | 32 | @Override 33 | public void onSubscribe(Disposable d) { 34 | if (mIsShowLoading) mBaseView.showProgress("加载中···"); 35 | } 36 | 37 | @Override 38 | public void onError(Throwable e) { 39 | mBaseView.hideProgress(); 40 | 41 | if (e instanceof CommonException) { 42 | mBaseView.showToast(e.getMessage()); 43 | }else{ 44 | Logger.e(e.getMessage()); 45 | mBaseView.showToast("系统异常,请重试"); 46 | } 47 | } 48 | 49 | @Override 50 | public void onComplete() { 51 | mBaseView.hideProgress(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/rx/JsonResponseFunc.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.rx; 2 | 3 | 4 | import com.hunter.fastandroid.exception.ApiException; 5 | import com.hunter.fastandroid.vo.JsonResponse; 6 | 7 | import io.reactivex.functions.Function; 8 | 9 | 10 | /** 11 | * RxJava map转换 12 | * 13 | * @param 14 | * @author Hunter 15 | */ 16 | public class JsonResponseFunc implements Function, T> { 17 | @Override 18 | public T apply(JsonResponse tJsonResponse) throws Exception { 19 | if (tJsonResponse == null) return null; 20 | 21 | if (!tJsonResponse.isSuccess()) { 22 | throw new ApiException(tJsonResponse); 23 | } 24 | 25 | return tJsonResponse.getData(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/rx/JsonResponseObserver.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.rx; 2 | 3 | 4 | import com.hunter.fastandroid.base.IBaseView; 5 | import com.hunter.fastandroid.exception.ApiException; 6 | import com.hunter.fastandroid.vo.JsonResponse; 7 | 8 | public abstract class JsonResponseObserver extends ResponseObserver { 9 | public JsonResponseObserver(IBaseView baseView) { 10 | super(baseView); 11 | } 12 | 13 | @Override 14 | public void onNext(T t) { 15 | if (t instanceof JsonResponse) { 16 | JsonResponse response = (JsonResponse) t; 17 | if (!response.isSuccess()) { 18 | onError(new ApiException(response)); 19 | }else{ 20 | onSuccess(t); 21 | } 22 | } 23 | } 24 | 25 | public abstract void onSuccess(T t); 26 | } 27 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/rx/ResponseObserver.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.rx; 2 | 3 | import com.hunter.fastandroid.R; 4 | import com.hunter.fastandroid.base.IBaseView; 5 | import com.hunter.fastandroid.exception.ApiException; 6 | import com.hunter.fastandroid.vo.JsonResponse; 7 | 8 | import io.reactivex.Observer; 9 | import io.reactivex.disposables.Disposable; 10 | 11 | /** 12 | * RxJava 自定义Subscriber 13 | * 14 | * @param 15 | * @author Hunter 16 | */ 17 | public abstract class ResponseObserver implements Observer { 18 | private static final String TAG = "ResponseObserver"; 19 | private IBaseView mBaseView; 20 | private Disposable disposable; 21 | 22 | public ResponseObserver(IBaseView baseView) { 23 | mBaseView = baseView; 24 | } 25 | 26 | @Override 27 | public void onSubscribe(Disposable disposable) { 28 | this.disposable = disposable; 29 | mBaseView.showProgress(R.string.loading); 30 | } 31 | 32 | @Override 33 | public void onError(Throwable e) { 34 | mBaseView.hideProgress(); 35 | mBaseView.showToast(e.getMessage()); 36 | 37 | if (e instanceof ApiException) { 38 | ApiException apiException = (ApiException) e; 39 | 40 | JsonResponse jsonResponse = apiException.getJsonResponse(); 41 | 42 | if(jsonResponse.isTokenValid()){ 43 | mBaseView.showToast(R.string.user_valid); 44 | mBaseView.clearUser(); 45 | }else{ 46 | mBaseView.showToast(jsonResponse.getMessage()); 47 | } 48 | }else{ 49 | mBaseView.showToast(R.string.system_error); 50 | } 51 | } 52 | 53 | @Override 54 | public void onComplete() { 55 | mBaseView.hideProgress(); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/rx/ResponseSubscriber.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.rx; 2 | 3 | import android.content.DialogInterface; 4 | 5 | import com.hunter.fastandroid.base.IBaseView; 6 | import com.orhanobut.logger.Logger; 7 | 8 | import org.reactivestreams.Subscriber; 9 | import org.reactivestreams.Subscription; 10 | 11 | /** 12 | * RxJava 自定义Subscriber (使用背压时使用) 13 | * 14 | * @param 15 | * @author Hunter 16 | */ 17 | public abstract class ResponseSubscriber implements Subscriber { 18 | private static final String TAG = "ResponseObserver"; 19 | private IBaseView mBaseView; 20 | private Subscription subscription; 21 | 22 | public ResponseSubscriber(IBaseView baseView) { 23 | mBaseView = baseView; 24 | mBaseView.setProgressCancelListener(new DialogInterface.OnCancelListener() { 25 | @Override 26 | public void onCancel(DialogInterface dialog) { 27 | if(subscription != null){ 28 | subscription.cancel(); 29 | } 30 | } 31 | }); 32 | } 33 | 34 | @Override 35 | public void onSubscribe(Subscription subscription) { 36 | this.subscription = subscription; 37 | mBaseView.showProgress(""); 38 | } 39 | 40 | @Override 41 | public void onError(Throwable e) { 42 | mBaseView.hideProgress(); 43 | if(null != e){ 44 | mBaseView.showToast(e.getMessage()); 45 | Logger.e(e.getMessage()); 46 | } 47 | } 48 | 49 | @Override 50 | public void onComplete() { 51 | mBaseView.hideProgress(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/service/TestService.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.service; 2 | 3 | import com.hunter.fastandroid.app.URLs; 4 | import com.hunter.fastandroid.vo.DoubanResponse; 5 | import com.hunter.fastandroid.vo.JsonResponse; 6 | 7 | import io.reactivex.Flowable; 8 | import io.reactivex.Observable; 9 | import retrofit2.http.GET; 10 | import retrofit2.http.POST; 11 | import retrofit2.http.Query; 12 | 13 | /** 14 | * Created by Administrator on 2017/1/4. 15 | */ 16 | public interface TestService { 17 | @GET(URLs.MODUEL_BOOK + URLs.SEARCH) 18 | Observable test(@Query("q") String keyword); 19 | } 20 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/ui/activity/LoginActivity.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.ui.activity; 2 | 3 | import com.hunter.fastandroid.base.BaseActivity; 4 | 5 | public abstract class LoginActivity extends BaseActivity { 6 | } 7 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/ui/activity/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.ui.activity; 2 | 3 | import android.support.v7.widget.LinearLayoutManager; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.text.TextUtils; 6 | import android.view.View; 7 | import android.widget.Button; 8 | import android.widget.EditText; 9 | 10 | import com.hunter.fastandroid.R; 11 | import com.hunter.fastandroid.base.BaseActivity; 12 | import com.hunter.fastandroid.presenter.TestPresenter; 13 | import com.hunter.fastandroid.ui.adapter.BookAdapter; 14 | import com.hunter.fastandroid.ui.interfaces.ITestView; 15 | import com.hunter.fastandroid.ui.widget.TitleBar; 16 | import com.hunter.fastandroid.vo.Book; 17 | 18 | import java.util.List; 19 | 20 | import butterknife.BindView; 21 | 22 | public class MainActivity extends BaseActivity implements ITestView { 23 | @BindView(R.id.title_bar) 24 | TitleBar titleBar; 25 | @BindView(R.id.et_input) 26 | EditText etInput; 27 | @BindView(R.id.btn_search) 28 | Button btnSearch; 29 | @BindView(R.id.rv_book) 30 | RecyclerView rvBook; 31 | 32 | private BookAdapter bookAdapter; 33 | 34 | TestPresenter testPresenter; 35 | 36 | @Override 37 | protected int getContentResId() { 38 | return R.layout.activity_main; 39 | } 40 | 41 | @Override 42 | public void initView() { 43 | titleBar.setTitle("测试页面"); 44 | 45 | bookAdapter = new BookAdapter(this); 46 | rvBook.setLayoutManager(new LinearLayoutManager(this)); 47 | rvBook.setAdapter(bookAdapter); 48 | 49 | btnSearch.setOnClickListener(new View.OnClickListener() { 50 | @Override 51 | public void onClick(View view) { 52 | String keyword = etInput.getText().toString(); 53 | if(TextUtils.isEmpty(keyword)){ 54 | showToast("请先输入书名关键字"); 55 | }else{ 56 | searchBook(keyword); 57 | } 58 | } 59 | }); 60 | } 61 | 62 | private void searchBook(String keyword) { 63 | testPresenter.test(keyword,this); 64 | } 65 | 66 | @Override 67 | public void initPresenter() { 68 | testPresenter = new TestPresenter(); 69 | } 70 | 71 | @Override 72 | public void showData(List datas) { 73 | bookAdapter.setData(datas); 74 | bookAdapter.notifyDataSetChanged(); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/ui/adapter/BookAdapter.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.ui.adapter; 2 | 3 | import android.content.Context; 4 | import android.widget.ImageView; 5 | import android.widget.TextView; 6 | 7 | import com.hunter.fastandroid.R; 8 | import com.hunter.fastandroid.base.BaseRecyclerAdapter; 9 | import com.hunter.fastandroid.base.RecyclerViewHolder; 10 | import com.hunter.fastandroid.utils.ImageLoadUtils; 11 | import com.hunter.fastandroid.vo.Book; 12 | 13 | public class BookAdapter extends BaseRecyclerAdapter { 14 | 15 | public BookAdapter(Context context) { 16 | super(context); 17 | } 18 | 19 | @Override 20 | public void bindView(RecyclerViewHolder holder, int position) { 21 | TextView tvName = holder.getView(R.id.tv_name); 22 | TextView tvPub = holder.getView(R.id.tv_publisher); 23 | TextView tvPrice = holder.getView(R.id.tv_price); 24 | ImageView ivImage = holder.getView(R.id.iv_image); 25 | 26 | tvName.setText(getItemData(position).getTitle()); 27 | tvPub.setText(getItemData(position).getPublisher()); 28 | tvPrice.setText(getItemData(position).getPrice()); 29 | ImageLoadUtils.loadImage(getContext(), getItemData(position).getImage(), ivImage); 30 | } 31 | 32 | @Override 33 | public int getLayoutId() { 34 | return R.layout.item_book; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/ui/interfaces/ITestView.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.ui.interfaces; 2 | 3 | import com.hunter.fastandroid.base.IBaseView; 4 | import com.hunter.fastandroid.vo.Book; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * Created by Administrator on 2017/1/4. 10 | */ 11 | public interface ITestView extends IBaseView { 12 | void showData(List datas); 13 | } 14 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/ui/widget/CountDownButton.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.ui.widget; 2 | 3 | import android.content.Context; 4 | import android.os.CountDownTimer; 5 | import android.support.v7.widget.AppCompatTextView; 6 | import android.util.AttributeSet; 7 | 8 | import com.hunter.fastandroid.R; 9 | 10 | 11 | /** 12 | * Created by Administrator on 2017/5/5. 13 | */ 14 | 15 | public class CountDownButton extends AppCompatTextView { 16 | private String oldText = ""; 17 | static final int MAX_COUNT_DOWN = 60000; 18 | static final int COUNT_DOWN_INTERVAL = 1000; 19 | 20 | private CountDownTimer countDownTimer; 21 | 22 | public CountDownButton(Context context) { 23 | super(context); 24 | } 25 | 26 | public CountDownButton(Context context, AttributeSet attrs) { 27 | super(context, attrs); 28 | } 29 | 30 | public CountDownButton(Context context, AttributeSet attrs, int defStyleAttr) { 31 | super(context, attrs, defStyleAttr); 32 | } 33 | 34 | /** 35 | * 开始进行倒计时 36 | */ 37 | public void startCountDown(){ 38 | oldText = getText().toString(); 39 | setEnabled(false); 40 | countDownTimer = new CountDownTimer(MAX_COUNT_DOWN, COUNT_DOWN_INTERVAL){ 41 | 42 | @Override 43 | public void onTick(long millisUntilFinished) { 44 | setText(getContext().getString(R.string.countdown, millisUntilFinished / COUNT_DOWN_INTERVAL)); 45 | } 46 | 47 | @Override 48 | public void onFinish() { 49 | setText(oldText); 50 | setEnabled(true); 51 | } 52 | }.start(); 53 | } 54 | 55 | /** 56 | * 停止倒计时 57 | */ 58 | public void stopCountDown(){ 59 | countDownTimer.cancel(); 60 | countDownTimer.onFinish(); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/ui/widget/CustomGridView.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.ui.widget; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | import android.widget.GridView; 6 | 7 | /** 8 | * 不带滚动条自适应高度的GridView 9 | * 10 | * @author Hunter 11 | */ 12 | public class CustomGridView extends GridView { 13 | public CustomGridView(Context context) { 14 | super(context); 15 | } 16 | 17 | public CustomGridView(Context context, AttributeSet attrs) { 18 | super(context, attrs); 19 | } 20 | 21 | public CustomGridView(Context context, AttributeSet attrs, int defStyleAttr) { 22 | super(context, attrs, defStyleAttr); 23 | } 24 | 25 | @Override 26 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 27 | int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, 28 | MeasureSpec.AT_MOST); 29 | super.onMeasure(widthMeasureSpec, expandSpec); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/ui/widget/CustomListView.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.ui.widget; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | import android.widget.ListView; 6 | 7 | /** 8 | * 不带滚动条自适应高度的ListView 9 | * 10 | * @author Hunter 11 | */ 12 | public class CustomListView extends ListView { 13 | public CustomListView(Context context) { 14 | super(context); 15 | } 16 | 17 | public CustomListView(Context context, AttributeSet attrs) { 18 | super(context, attrs); 19 | } 20 | 21 | public CustomListView(Context context, AttributeSet attrs, int defStyleAttr) { 22 | super(context, attrs, defStyleAttr); 23 | } 24 | 25 | @Override 26 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 27 | int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, 28 | MeasureSpec.AT_MOST); 29 | super.onMeasure(widthMeasureSpec, expandSpec); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/ui/widget/CustomProgress.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.ui.widget; 2 | 3 | import android.app.ProgressDialog; 4 | import android.content.Context; 5 | import android.os.Bundle; 6 | import android.view.WindowManager; 7 | import android.widget.TextView; 8 | 9 | import com.hunter.fastandroid.R; 10 | import com.wang.avi.AVLoadingIndicatorView; 11 | 12 | 13 | /** 14 | * Created by Administrator on 2017/5/25. 15 | */ 16 | 17 | public class CustomProgress extends ProgressDialog { 18 | private AVLoadingIndicatorView loading; 19 | private TextView tvMessage; 20 | private CharSequence mMessage; 21 | 22 | public CustomProgress(Context context) { 23 | super(context); 24 | } 25 | 26 | public CustomProgress(Context context, int theme) { 27 | super(context, theme); 28 | } 29 | 30 | @Override 31 | protected void onCreate(Bundle savedInstanceState) { 32 | super.onCreate(savedInstanceState); 33 | init(getContext()); 34 | } 35 | 36 | private void init(Context context) { 37 | setContentView(R.layout.progress); 38 | 39 | tvMessage = (TextView) findViewById(R.id.tv_message); 40 | if(mMessage != null){ 41 | tvMessage.setText(mMessage); 42 | } 43 | 44 | loading = (AVLoadingIndicatorView) findViewById(R.id.avi); 45 | loading.smoothToShow(); 46 | 47 | WindowManager.LayoutParams params = getWindow().getAttributes(); 48 | params.width = WindowManager.LayoutParams.WRAP_CONTENT; 49 | params.height = WindowManager.LayoutParams.WRAP_CONTENT; 50 | getWindow().setAttributes(params); 51 | } 52 | 53 | @Override 54 | public void setMessage(CharSequence message) { 55 | if(tvMessage != null){ 56 | tvMessage.setText(message); 57 | }else{ 58 | mMessage = message; 59 | } 60 | } 61 | 62 | @Override 63 | public void show() { 64 | super.show(); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/ui/widget/NoZoomControllWebView.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.ui.widget; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.content.Context; 5 | import android.util.AttributeSet; 6 | import android.view.MotionEvent; 7 | import android.webkit.WebView; 8 | import android.widget.ZoomButtonsController; 9 | 10 | /** 11 | * 不可缩放的WebView 12 | * 13 | * @author Hunter 14 | */ 15 | public class NoZoomControllWebView extends WebView { 16 | 17 | private ZoomButtonsController mZoomButtonsController = null; 18 | 19 | public NoZoomControllWebView(Context context) { 20 | super(context); 21 | disableControls(); 22 | } 23 | 24 | public NoZoomControllWebView(Context context, AttributeSet attrs, int defStyle) { 25 | super(context, attrs, defStyle); 26 | disableControls(); 27 | } 28 | 29 | public NoZoomControllWebView(Context context, AttributeSet attrs) { 30 | super(context, attrs); 31 | disableControls(); 32 | } 33 | 34 | /** 35 | * Disable the controls 36 | */ 37 | @SuppressLint("NewApi") 38 | private void disableControls() { 39 | this.getSettings().setBuiltInZoomControls(true); 40 | this.getSettings().setDisplayZoomControls(false); 41 | } 42 | 43 | @Override 44 | public boolean onTouchEvent(MotionEvent ev) { 45 | super.onTouchEvent(ev); 46 | if (mZoomButtonsController != null) { 47 | // Hide the controlls AFTER they where made visible by the default implementation. 48 | mZoomButtonsController.setVisible(false); 49 | } 50 | return true; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/ui/widget/TitleBar.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.ui.widget; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.widget.ImageButton; 8 | import android.widget.LinearLayout; 9 | import android.widget.TextView; 10 | 11 | import com.hunter.fastandroid.R; 12 | 13 | /** 14 | * 自定义标题栏 15 | * 16 | * @author Hunter 17 | */ 18 | public class TitleBar extends LinearLayout { 19 | private LayoutInflater mInflater; 20 | private View mHeader; 21 | private LinearLayout mLayoutLeftContainer; 22 | private LinearLayout mLayoutRightContainer; 23 | private LinearLayout mLayoutCenterContainer; 24 | private LinearLayout mHeaderTitle; 25 | private TextView mTvTitle; 26 | private ImageButton mLeftImageButton; 27 | private ImageButton mRightImageButton; 28 | 29 | public TitleBar(Context context) { 30 | super(context); 31 | init(context); 32 | } 33 | 34 | public TitleBar(Context context, AttributeSet attrs) { 35 | super(context, attrs); 36 | init(context); 37 | } 38 | 39 | private void init(Context context) { 40 | mInflater = LayoutInflater.from(context); 41 | mHeader = mInflater.inflate(R.layout.common_header, null); 42 | addView(mHeader); 43 | initViews(); 44 | } 45 | 46 | /** 47 | * 初始化布局 48 | */ 49 | private void initViews() { 50 | mLayoutLeftContainer = (LinearLayout) findViewByHeaderId(R.id.header_layout_leftview_container); 51 | mLayoutRightContainer = (LinearLayout) findViewByHeaderId(R.id.header_layout_rightview_container); 52 | 53 | mHeaderTitle = (LinearLayout) findViewByHeaderId(R.id.header_title); 54 | mTvTitle = (TextView) findViewByHeaderId(R.id.header_htv_subtitle); 55 | 56 | mLayoutCenterContainer = (LinearLayout) findViewByHeaderId(R.id.header_layout_middleview_container); 57 | 58 | initLeftView(); 59 | initRightView(); 60 | 61 | mLayoutLeftContainer.setVisibility(View.INVISIBLE); 62 | mLayoutRightContainer.setVisibility(View.INVISIBLE); 63 | 64 | mHeaderTitle.setVisibility(View.VISIBLE); 65 | mTvTitle.setVisibility(View.VISIBLE); 66 | 67 | mLayoutCenterContainer.setVisibility(View.GONE); 68 | } 69 | 70 | /** 71 | * 初始化左侧按钮 72 | */ 73 | private void initLeftView() { 74 | View mleftImageButtonView = mInflater.inflate( 75 | R.layout.common_header_leftbutton, null); 76 | mLayoutLeftContainer.addView(mleftImageButtonView); 77 | mLeftImageButton = (ImageButton) mleftImageButtonView 78 | .findViewById(R.id.ib_titlebar_left); 79 | } 80 | 81 | /** 82 | * 初始化右侧按钮 83 | */ 84 | private void initRightView() { 85 | View mRightImageButtonView = mInflater.inflate( 86 | R.layout.common_header_rightbutton, null); 87 | mLayoutRightContainer.addView(mRightImageButtonView); 88 | mRightImageButton = (ImageButton) mRightImageButtonView 89 | .findViewById(R.id.ib_titlebar_right); 90 | } 91 | 92 | /** 93 | * 在TitleBar中查找指定控件 94 | */ 95 | public View findViewByHeaderId(int id) { 96 | return mHeader.findViewById(id); 97 | } 98 | 99 | /** 100 | * 设置TitleBar的标题 101 | */ 102 | public void setTitle(CharSequence title) { 103 | mTvTitle.setText(title); 104 | mHeaderTitle.setVisibility(View.VISIBLE); 105 | mLayoutCenterContainer.setVisibility(View.GONE); 106 | } 107 | 108 | /** 109 | * 设置TitleBar的标题 110 | * 111 | * @param res 112 | */ 113 | public void setTitle(int res) { 114 | mTvTitle.setText(res); 115 | mHeaderTitle.setVisibility(View.VISIBLE); 116 | mLayoutCenterContainer.setVisibility(View.GONE); 117 | } 118 | 119 | /** 120 | * 自定义左侧视图 121 | */ 122 | public void setLeftView(View view) { 123 | mLayoutLeftContainer.removeAllViews(); 124 | mLayoutLeftContainer.addView(view); 125 | mLayoutLeftContainer.setVisibility(View.VISIBLE); 126 | } 127 | 128 | /** 129 | * 自定义居中视图 130 | */ 131 | public void setCenterView(View view) { 132 | mHeaderTitle.setVisibility(View.GONE); 133 | mLayoutCenterContainer.removeAllViews(); 134 | mLayoutCenterContainer.addView(view); 135 | mLayoutCenterContainer.setVisibility(View.VISIBLE); 136 | } 137 | 138 | /** 139 | * 自定义右侧视图 140 | */ 141 | public void setRightView(View view) { 142 | mLayoutRightContainer.removeAllViews(); 143 | mLayoutRightContainer.addView(view); 144 | mLayoutRightContainer.setVisibility(View.VISIBLE); 145 | } 146 | 147 | /** 148 | * 设置文字标题以及左右的View 149 | * 150 | * @param title 151 | * @param leftView 152 | * @param rightView 153 | */ 154 | public void setTitleBar(CharSequence title, View leftView, View rightView) { 155 | setTitle(title); 156 | setLeftView(leftView); 157 | setRightView(rightView); 158 | } 159 | 160 | /** 161 | * 设置文字标题以及左右的View 162 | * 163 | * @param title 164 | * @param leftView 165 | * @param rightView 166 | */ 167 | public void setTitleBar(int title, View leftView, View rightView) { 168 | setTitle(title); 169 | setLeftView(leftView); 170 | setRightView(rightView); 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/utils/CommonUtils.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.utils; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.content.pm.PackageInfo; 6 | import android.content.pm.PackageManager; 7 | import android.os.IBinder; 8 | import android.view.View; 9 | import android.view.inputmethod.InputMethodManager; 10 | 11 | import com.google.gson.Gson; 12 | import com.google.gson.GsonBuilder; 13 | import com.google.gson.JsonParseException; 14 | import com.google.gson.JsonParser; 15 | import com.hunter.fastandroid.app.BaseApplication; 16 | 17 | import java.security.MessageDigest; 18 | import java.util.Locale; 19 | import java.util.regex.Matcher; 20 | import java.util.regex.Pattern; 21 | 22 | /** 23 | * 通用工具类 24 | * 25 | * @author Hunter 26 | */ 27 | public class CommonUtils { 28 | private static final String GSON_FORMAT = "yyyy-MM-dd HH:mm:ss"; 29 | private static Gson mGson; 30 | 31 | /** 32 | * 验证json合法性 33 | * 34 | * @param jsonContent 35 | * @return 36 | */ 37 | public static boolean isJsonFormat(String jsonContent) { 38 | try { 39 | new JsonParser().parse(jsonContent); 40 | return true; 41 | } catch (JsonParseException e) { 42 | return false; 43 | } 44 | } 45 | 46 | 47 | /** 48 | * 对指定字符串进行md5加密 49 | * 50 | * @param s 51 | * @return 加密后的数据 52 | */ 53 | public static String EncryptMD5(String s) { 54 | char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 55 | 'a', 'b', 'c', 'd', 'e', 'f'}; 56 | try { 57 | byte[] btInput = s.getBytes(); 58 | // 获得MD5摘要算法的 MessageDigest 对象 59 | MessageDigest mdInst = MessageDigest.getInstance("MD5"); 60 | // 使用指定的字节更新摘要 61 | mdInst.update(btInput); 62 | // 获得密文 63 | byte[] md = mdInst.digest(); 64 | // 把密文转换成十六进制的字符串形式 65 | int j = md.length; 66 | char str[] = new char[j * 2]; 67 | int k = 0; 68 | for (int i = 0; i < j; i++) { 69 | byte byte0 = md[i]; 70 | str[k++] = hexDigits[byte0 >>> 4 & 0xf]; 71 | str[k++] = hexDigits[byte0 & 0xf]; 72 | } 73 | return new String(str); 74 | } catch (Exception e) { 75 | e.printStackTrace(); 76 | return null; 77 | } 78 | } 79 | 80 | /** 81 | * 判断email格式是否正确 82 | * 83 | * @param email 84 | * @return 85 | */ 86 | public static boolean isEmail(String email) { 87 | String str = "^([a-zA-Z0-9_\\-\\.]+)@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.)|(([a-zA-Z0-9\\-]+\\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\\]?)$"; 88 | Pattern p = Pattern.compile(str); 89 | Matcher m = p.matcher(email); 90 | return m.matches(); 91 | } 92 | 93 | /** 94 | * 根据系统语言判断是否为中国 95 | * 96 | * @return 97 | */ 98 | public static boolean isZh() { 99 | Locale locale = BaseApplication.getInstance().getResources().getConfiguration().locale; 100 | String language = locale.getLanguage(); 101 | if (language.startsWith("zh")) { 102 | return true; 103 | } else { 104 | return false; 105 | } 106 | } 107 | 108 | /** 109 | * 获取gson对象 110 | * 111 | * @return 112 | */ 113 | public static Gson getGson() { 114 | if (mGson == null) { 115 | mGson = new GsonBuilder().setDateFormat(GSON_FORMAT).create(); // 创建gson对象,并设置日期格式 116 | } 117 | 118 | return mGson; 119 | } 120 | 121 | /** 122 | * 获取版本号 123 | * 124 | * @return 当前应用的版本号 125 | */ 126 | public static String getVersion() { 127 | try { 128 | PackageManager manager = BaseApplication.getInstance().getPackageManager(); 129 | PackageInfo info = manager.getPackageInfo(BaseApplication.getInstance().getPackageName(), 0); 130 | return info.versionName; 131 | } catch (Exception e) { 132 | e.printStackTrace(); 133 | return ""; 134 | } 135 | } 136 | 137 | /** 138 | * @param context 139 | */ 140 | public static void hideSoftInput(Activity context) { 141 | 142 | try{ 143 | InputMethodManager imm = (InputMethodManager) context 144 | .getSystemService(Context.INPUT_METHOD_SERVICE); 145 | IBinder ibinder = context.getCurrentFocus().getWindowToken(); 146 | if((imm != null) && (ibinder != null)){ 147 | imm.hideSoftInputFromWindow(ibinder, 0); 148 | } 149 | }catch (Exception e){ 150 | 151 | } 152 | } 153 | 154 | 155 | public static void showSoftInput(Context context, View v) { 156 | InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); 157 | if (!imm.isActive()) { 158 | imm.showSoftInput(v, 0); 159 | } 160 | } 161 | 162 | } 163 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/utils/DateUtils.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.utils; 2 | 3 | import java.text.ParseException; 4 | import java.text.SimpleDateFormat; 5 | import java.util.Calendar; 6 | import java.util.Date; 7 | import java.util.Locale; 8 | 9 | /** 10 | * 日期工具类 11 | * 12 | * @author Hunter 13 | */ 14 | public class DateUtils { 15 | 16 | public static SimpleDateFormat formatDate = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()); 17 | public static SimpleDateFormat formatDay = new SimpleDateFormat("d", Locale.getDefault()); 18 | public static SimpleDateFormat formatMonthDay = new SimpleDateFormat("M-d", Locale.getDefault()); 19 | public static SimpleDateFormat formatDateTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()); 20 | 21 | /** 22 | * 格式化日期 23 | * 24 | * @param date 25 | * @return 年月日 26 | */ 27 | public static String formatDate(Date date) { 28 | return formatDate.format(date); 29 | } 30 | 31 | /** 32 | * 格式化日期 33 | * 34 | * @param date 35 | * @return 年月日 时分秒 36 | */ 37 | public static String formatDateTime(Date date) { 38 | return formatDateTime.format(date); 39 | } 40 | 41 | /** 42 | * 将时间戳解析成日期 43 | * 44 | * @param timeInMillis 45 | * @return 年月日 46 | */ 47 | public static String parseDate(long timeInMillis) { 48 | Calendar calendar = Calendar.getInstance(); 49 | calendar.setTimeInMillis(timeInMillis); 50 | Date date = calendar.getTime(); 51 | return formatDate(date); 52 | } 53 | 54 | /** 55 | * 将时间戳解析成日期 56 | * 57 | * @param timeInMillis 58 | * @return 年月日 时分秒 59 | */ 60 | public static String parseDateTime(long timeInMillis) { 61 | Calendar calendar = Calendar.getInstance(); 62 | calendar.setTimeInMillis(timeInMillis); 63 | Date date = calendar.getTime(); 64 | return formatDateTime(date); 65 | } 66 | 67 | /** 68 | * 解析日期 69 | * 70 | * @param date 71 | * @return 72 | */ 73 | public static Date parseDate(String date) { 74 | Date mDate = null; 75 | try { 76 | mDate = formatDate.parse(date); 77 | } catch (ParseException e) { 78 | e.printStackTrace(); 79 | } 80 | 81 | return mDate; 82 | } 83 | 84 | /** 85 | * 解析日期 86 | * 87 | * @param datetime 88 | * @return 89 | */ 90 | public static Date parseDateTime(String datetime) { 91 | Date mDate = null; 92 | try { 93 | mDate = formatDateTime.parse(datetime); 94 | } catch (ParseException e) { 95 | e.printStackTrace(); 96 | } 97 | 98 | return mDate; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/utils/DialogUtils.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.utils; 2 | 3 | import android.app.AlertDialog; 4 | import android.content.Context; 5 | import android.content.DialogInterface; 6 | 7 | import com.hunter.fastandroid.R; 8 | 9 | 10 | /** 11 | * Created by Administrator on 2017/6/8. 12 | */ 13 | 14 | public class DialogUtils { 15 | public static void showConfirmDialog(Context context, String message, DialogInterface.OnClickListener onClickListener) { 16 | showConfirmDialog(context, message, true, onClickListener); 17 | } 18 | 19 | public static void showConfirmDialog(Context context, int messageRes, DialogInterface.OnClickListener onClickListener) { 20 | showConfirmDialog(context, context.getString(messageRes), onClickListener); 21 | } 22 | 23 | /** 24 | * 显示一个确认对话框 25 | * @param context 26 | * @param message 27 | * @param onClickListener 28 | */ 29 | public static void showConfirmDialog(Context context, String message, boolean cancelable, DialogInterface.OnClickListener onClickListener) { 30 | new AlertDialog 31 | .Builder(context) 32 | .setMessage(message) 33 | .setCancelable(cancelable) 34 | .setPositiveButton(R.string.confirm, onClickListener) 35 | .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { 36 | @Override 37 | public void onClick(DialogInterface dialog, int which) { 38 | dialog.dismiss(); 39 | } 40 | }) 41 | .show(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/utils/FileInfoUtils.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.utils; 2 | 3 | import java.io.File; 4 | import java.io.FileInputStream; 5 | import java.text.DecimalFormat; 6 | 7 | /** 8 | * 文件或文件夹操作工具类 9 | * 10 | * @author Hunter 11 | */ 12 | public class FileInfoUtils { 13 | /** 14 | * 返回自定文件或文件夹的大小 15 | * 16 | * @param f 17 | * @return 18 | * @throws Exception 19 | */ 20 | public static long getFileSizes(File f) throws Exception {// 取得文件大小 21 | long s = 0; 22 | if (f.exists()) { 23 | FileInputStream fis = new FileInputStream(f); 24 | s = fis.available(); 25 | fis.close(); 26 | } else { 27 | f.createNewFile(); 28 | System.out.println("文件不存在"); 29 | } 30 | return s; 31 | } 32 | 33 | // 递归 34 | public static long getFileSize(File f) throws Exception// 取得文件夹大小 35 | { 36 | long size = 0; 37 | File flist[] = f.listFiles(); 38 | for (int i = 0; i < flist.length; i++) { 39 | if (flist[i].isDirectory()) { 40 | size = size + getFileSize(flist[i]); 41 | } else { 42 | size = size + flist[i].length(); 43 | } 44 | } 45 | return size; 46 | } 47 | 48 | public static String FormetFileSize(long fileS) {// 转换文件大小 49 | DecimalFormat df = new DecimalFormat("#0.00"); 50 | String fileSizeString = ""; 51 | if (fileS < 1024) { 52 | fileSizeString = df.format((double) fileS) + "B"; 53 | } else if (fileS < 1048576) { 54 | fileSizeString = df.format((double) fileS / 1024) + "K"; 55 | } else if (fileS < 1073741824) { 56 | fileSizeString = df.format((double) fileS / 1048576) + "M"; 57 | } else { 58 | fileSizeString = df.format((double) fileS / 1073741824) + "G"; 59 | } 60 | return fileSizeString; 61 | } 62 | 63 | public static long getlist(File f) {// 递归求取目录文件个数 64 | long size = 0; 65 | File flist[] = f.listFiles(); 66 | size = flist.length; 67 | for (int i = 0; i < flist.length; i++) { 68 | if (flist[i].isDirectory()) { 69 | size = size + getlist(flist[i]); 70 | size--; 71 | } 72 | } 73 | return size; 74 | 75 | } 76 | } -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/utils/ImageLoadUtils.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.utils; 2 | 3 | import android.content.Context; 4 | import android.widget.ImageView; 5 | 6 | import com.bumptech.glide.Glide; 7 | import com.bumptech.glide.request.RequestOptions; 8 | import com.hunter.fastandroid.R; 9 | 10 | /** 11 | * 图片加载工具类 12 | * 为方便以后随时更换图片加载库 13 | * 并且统一配置图片加载方式 14 | * 15 | * @author Hunter 16 | */ 17 | public class ImageLoadUtils { 18 | 19 | public static final int DEFAULT_PLACEHOLDER_RESID = R.mipmap.ic_launcher; 20 | 21 | public static void loadImage(Context context, String imageUrl, int resId, ImageView imageView) { 22 | RequestOptions options = new RequestOptions() 23 | .placeholder(resId); 24 | 25 | Glide 26 | .with(context) 27 | .load(imageUrl) 28 | .apply(options) 29 | .into(imageView); 30 | } 31 | 32 | public static void loadImage(Context context, String imageUrl, ImageView imageView) { 33 | loadImage(context, imageUrl, DEFAULT_PLACEHOLDER_RESID, imageView); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/utils/MyStringUtils.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.utils; 2 | 3 | import android.util.Log; 4 | 5 | import java.security.MessageDigest; 6 | import java.security.NoSuchAlgorithmException; 7 | import java.text.ParseException; 8 | import java.text.SimpleDateFormat; 9 | import java.util.ArrayList; 10 | import java.util.Calendar; 11 | import java.util.Date; 12 | import java.util.regex.Matcher; 13 | import java.util.regex.Pattern; 14 | 15 | /** 16 | * 字符串操作工具类 17 | * 18 | * @author Hunter 19 | */ 20 | public class MyStringUtils { 21 | private final static Pattern EMAILER = Pattern 22 | .compile("\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*"); 23 | private final static ThreadLocal DATE_FORMATER = new ThreadLocal() { 24 | @Override 25 | protected SimpleDateFormat initialValue() { 26 | return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 27 | } 28 | }; 29 | private static final String _BR = "
"; 30 | private final static ThreadLocal dateFormater2 = new ThreadLocal() { 31 | @Override 32 | protected SimpleDateFormat initialValue() { 33 | return new SimpleDateFormat("yyyy-MM-dd"); 34 | } 35 | }; 36 | 37 | /** 38 | * 字符串截取 39 | * 40 | * @param str 41 | * @param length 42 | * @return 43 | * @throws Exception 44 | */ 45 | public static String subString(String str, int length) throws Exception { 46 | 47 | byte[] bytes = str.getBytes("Unicode"); 48 | int n = 0; // 表示当前的字节数 49 | int i = 2; // 要截取的字节数,从第3个字节开始 50 | for (; i < bytes.length && n < length; i++) { 51 | // 奇数位置,如3、5、7等,为UCS2编码中两个字节的第二个字节 52 | if (i % 2 == 1) { 53 | n++; // 在UCS2第二个字节时n加1 54 | } else { 55 | // 当UCS2编码的第一个字节不等于0时,该UCS2字符为汉字,一个汉字算两个字节 56 | if (bytes[i] != 0) { 57 | n++; 58 | } 59 | } 60 | } 61 | // 如果i为奇数时,处理成偶数 62 | if (i % 2 == 1) { 63 | // 该UCS2字符是汉字时,去掉这个截一半的汉字 64 | if (bytes[i - 1] != 0) 65 | i = i - 1; 66 | // 该UCS2字符是字母或数字,则保留该字符 67 | else 68 | i = i + 1; 69 | } 70 | return new String(bytes, 0, i, "Unicode"); 71 | } 72 | 73 | /** 74 | * @param input 75 | * @return 76 | */ 77 | public static String toDBC(String input) { 78 | char[] c = input.toCharArray(); 79 | for (int i = 0; i < c.length; i++) { 80 | if (c[i] == 12288) { 81 | c[i] = (char) 32; 82 | continue; 83 | } 84 | if (c[i] > 65280 && c[i] < 65375) 85 | c[i] = (char) (c[i] - 65248); 86 | } 87 | return new String(c); 88 | } 89 | 90 | /** 91 | * 计算微博内容的长度 1个汉字 == 两个英文字母所占的长度 标点符号区分英文和中文 92 | * 93 | * @param c 所要统计的字符序列 94 | * @return 返回字符序列计算的长度 95 | */ 96 | public static long calculateWeiboLength(CharSequence c) { 97 | 98 | double len = 0; 99 | for (int i = 0; i < c.length(); i++) { 100 | int temp = (int) c.charAt(i); 101 | if (temp > 0 && temp < 127) { 102 | len += 0.5; 103 | } else { 104 | len++; 105 | } 106 | } 107 | return Math.round(len); 108 | } 109 | 110 | /** 111 | * 分割字符串 112 | * 113 | * @param str String 原始字符串 114 | * @param splitsign String 分隔符 115 | * @return String[] 分割后的字符串数组 116 | */ 117 | public static String[] split(String str, String splitsign) { 118 | int index; 119 | if (str == null || splitsign == null) 120 | return null; 121 | ArrayList al = new ArrayList(); 122 | while ((index = str.indexOf(splitsign)) != -1) { 123 | al.add(str.substring(0, index)); 124 | str = str.substring(index + splitsign.length()); 125 | } 126 | al.add(str); 127 | return (String[]) al.toArray(new String[0]); 128 | } 129 | 130 | /** 131 | * 替换字符串 132 | * 133 | * @param from String 原始字符串 134 | * @param to String 目标字符串 135 | * @param source String 母字符串 136 | * @return String 替换后的字符串 137 | */ 138 | public static String replace(String from, String to, String source) { 139 | if (source == null || from == null || to == null) 140 | return null; 141 | StringBuffer bf = new StringBuffer(""); 142 | int index = -1; 143 | while ((index = source.indexOf(from)) != -1) { 144 | bf.append(source.substring(0, index) + to); 145 | source = source.substring(index + from.length()); 146 | index = source.indexOf(from); 147 | } 148 | bf.append(source); 149 | return bf.toString(); 150 | } 151 | 152 | /** 153 | * 替换字符串,能能够在HTML页面上直接显示(替换双引号和小于号) 154 | * 155 | * @param str String 原始字符串 156 | * @return String 替换后的字符串 157 | */ 158 | public static String htmlencode(String str) { 159 | if (str == null) { 160 | return null; 161 | } 162 | 163 | return replace("\"", """, replace("<", "<", str)); 164 | } 165 | 166 | /** 167 | * 替换字符串,将被编码的转换成原始码(替换成双引号和小于号) 168 | * 169 | * @param str String 170 | * @return String 171 | */ 172 | public static String htmldecode(String str) { 173 | if (str == null) { 174 | return null; 175 | } 176 | 177 | return replace(""", "\"", replace("<", "<", str)); 178 | } 179 | 180 | /** 181 | * 在页面上直接显示文本内容,替换小于号,空格,回车,TAB 182 | * 183 | * @param str String 原始字符串 184 | * @return String 替换后的字符串 185 | */ 186 | public static String htmlshow(String str) { 187 | if (str == null) { 188 | return null; 189 | } 190 | 191 | str = replace("<", "<", str); 192 | str = replace(" ", " ", str); 193 | str = replace("\r\n", _BR, str); 194 | str = replace("\n", _BR, str); 195 | str = replace("\t", "    ", str); 196 | return str; 197 | } 198 | 199 | /** 200 | * 返回指定字节长度的字符串 201 | * 202 | * @param str String 字符串 203 | * @param length int 指定长度 204 | * @return String 返回的字符串 205 | */ 206 | public static String toLength(String str, int length) { 207 | if (str == null) { 208 | return null; 209 | } 210 | if (length <= 0) { 211 | return ""; 212 | } 213 | try { 214 | if (str.getBytes("GBK").length <= length) { 215 | return str; 216 | } 217 | } catch (Exception ex) { 218 | } 219 | StringBuffer buff = new StringBuffer(); 220 | 221 | int index = 0; 222 | char c; 223 | length -= 3; 224 | while (length > 0) { 225 | c = str.charAt(index); 226 | if (c < 128) { 227 | length--; 228 | } else { 229 | length--; 230 | length--; 231 | } 232 | buff.append(c); 233 | index++; 234 | } 235 | buff.append("..."); 236 | return buff.toString(); 237 | } 238 | 239 | /** 240 | * 获取url的后缀名 241 | * 242 | * @param urlString 243 | * @return 244 | */ 245 | public static String getUrlFileName(String urlString) { 246 | String fileName = urlString.substring(urlString.lastIndexOf("/")); 247 | fileName = fileName.substring(1, fileName.length()); 248 | if (fileName.equalsIgnoreCase("")) { 249 | Calendar c = Calendar.getInstance(); 250 | fileName = c.get(Calendar.YEAR) + "" + c.get(Calendar.MONTH) + "" 251 | + c.get(Calendar.DAY_OF_MONTH) + "" 252 | + c.get(Calendar.MINUTE); 253 | 254 | } 255 | return fileName; 256 | } 257 | 258 | public static String replaceSomeString(String str) { 259 | String dest = ""; 260 | try { 261 | if (str != null) { 262 | str = str.replaceAll("\r", ""); 263 | str = str.replaceAll(">", ">"); 264 | str = str.replaceAll("“", "“"); 265 | str = str.replaceAll("”", "”"); 266 | str = str.replaceAll("'", "'"); 267 | str = str.replaceAll(" ", ""); 268 | str = str.replaceAll("", "\n"); 269 | str = str.replaceAll(""", "\""); 270 | str = str.replaceAll("<", "<"); 271 | str = str.replaceAll("‘", "《"); 272 | str = str.replaceAll("’", "》"); 273 | str = str.replaceAll("·", "·"); 274 | str = str.replace("—", "—"); 275 | str = str.replace("…", "…"); 276 | str = str.replace("&", "×"); 277 | str = str.replaceAll("\\s*", ""); 278 | str = str.trim(); 279 | str = str.replaceAll("

", "\n "); 280 | str = str.replaceAll("

", ""); 281 | str = str.replaceAll("", "\n "); 282 | str = str.replaceAll("", ""); 283 | dest = str; 284 | } 285 | } catch (Exception e) { 286 | // TODO: handle exception 287 | } 288 | 289 | return dest; 290 | } 291 | 292 | /** 293 | * 清除文本里面的HTML标签 294 | * 295 | * @param htmlStr 296 | * @return 297 | */ 298 | public static String delHTMLTag(String htmlStr) { 299 | String regEx_script = "]*?>[\\s\\S]*?<\\/script>"; // 定义script的正则表达式 300 | String regEx_style = "]*?>[\\s\\S]*?<\\/style>"; // 定义style的正则表达式 301 | String regEx_html = "<[^>]+>"; // 定义HTML标签的正则表达式 302 | Log.v("htmlStr", htmlStr); 303 | try { 304 | Pattern p_script = Pattern.compile(regEx_script, 305 | Pattern.CASE_INSENSITIVE); 306 | Matcher m_script = p_script.matcher(htmlStr); 307 | htmlStr = m_script.replaceAll(""); // 过滤script标签 308 | 309 | Pattern p_style = Pattern.compile(regEx_style, 310 | Pattern.CASE_INSENSITIVE); 311 | Matcher m_style = p_style.matcher(htmlStr); 312 | htmlStr = m_style.replaceAll(""); // 过滤style标签 313 | 314 | Pattern p_html = Pattern.compile(regEx_html, 315 | Pattern.CASE_INSENSITIVE); 316 | Matcher m_html = p_html.matcher(htmlStr); 317 | htmlStr = m_html.replaceAll(""); // 过滤html标签 318 | } catch (Exception e) { 319 | // TODO: handle exception 320 | } 321 | 322 | return htmlStr; // 返回文本字符串 323 | } 324 | 325 | public static String delSpace(String str) { 326 | if (str != null) { 327 | str = str.replaceAll("\r", ""); 328 | str = str.replaceAll("\n", ""); 329 | str = str.replace(" ", ""); 330 | } 331 | return str; 332 | } 333 | 334 | /** 335 | * 检查字符串是否存在值,如果为true, 336 | * 337 | * @param str 待检验的字符串 338 | * @return 当 str 不为 null 或 "" 就返回 true 339 | */ 340 | public static boolean isNotNull(String str) { 341 | return (str != null && !"".equalsIgnoreCase(str.trim())); 342 | } 343 | 344 | /** 345 | * 将字符串转位日期类型 346 | * 347 | * @param sdate 348 | * @return 349 | */ 350 | public static Date toDate(String sdate) { 351 | try { 352 | return DATE_FORMATER.get().parse(sdate); 353 | } catch (ParseException e) { 354 | return null; 355 | } 356 | } 357 | 358 | /** 359 | * 以友好的方式显示时间 360 | * 361 | * @param sdate 362 | * @return 363 | */ 364 | public static String friendly_time(String sdate) { 365 | Date time = toDate(sdate); 366 | if (time == null) { 367 | return "Unknown"; 368 | } 369 | String ftime = ""; 370 | Calendar cal = Calendar.getInstance(); 371 | 372 | // 判断是否是同一天 373 | String curDate = dateFormater2.get().format(cal.getTime()); 374 | String paramDate = dateFormater2.get().format(time); 375 | if (curDate.equals(paramDate)) { 376 | int hour = (int) ((cal.getTimeInMillis() - time.getTime()) / 3600000); 377 | if (hour == 0) 378 | ftime = Math.max( 379 | (cal.getTimeInMillis() - time.getTime()) / 60000, 1) 380 | + "分钟前"; 381 | else 382 | ftime = hour + "小时前"; 383 | return ftime; 384 | } 385 | 386 | long lt = time.getTime() / 86400000; 387 | long ct = cal.getTimeInMillis() / 86400000; 388 | int days = (int) (ct - lt); 389 | if (days == 0) { 390 | int hour = (int) ((cal.getTimeInMillis() - time.getTime()) / 3600000); 391 | if (hour == 0) 392 | ftime = Math.max( 393 | (cal.getTimeInMillis() - time.getTime()) / 60000, 1) 394 | + "分钟前"; 395 | else 396 | ftime = hour + "小时前"; 397 | } else if (days == 1) { 398 | ftime = "昨天"; 399 | } else if (days == 2) { 400 | ftime = "前天"; 401 | } else if (days > 2 && days <= 10) { 402 | ftime = days + "天前"; 403 | } else if (days > 10) { 404 | ftime = dateFormater2.get().format(time); 405 | } 406 | return ftime; 407 | } 408 | 409 | public static String trimmy(String str) { 410 | String dest = ""; 411 | if (str != null) { 412 | str = str.replaceAll("-", ""); 413 | str = str.replaceAll("\\+", ""); 414 | dest = str; 415 | } 416 | return dest; 417 | } 418 | 419 | public static String replaceBlank(String str) { 420 | 421 | String dest = ""; 422 | if (str != null) { 423 | Pattern p = Pattern.compile("\r"); 424 | Matcher m = p.matcher(str); 425 | dest = m.replaceAll(""); 426 | } 427 | return dest; 428 | } 429 | 430 | /** 431 | * 判断给定字符串时间是否为今日 432 | * 433 | * @param sdate 434 | * @return boolean 435 | */ 436 | public static boolean isToday(String sdate) { 437 | boolean b = false; 438 | Date time = toDate(sdate); 439 | Date today = new Date(0); 440 | if (time != null) { 441 | String nowDate = dateFormater2.get().format(today); 442 | String timeDate = dateFormater2.get().format(time); 443 | if (nowDate.equals(timeDate)) { 444 | b = true; 445 | } 446 | } 447 | return b; 448 | } 449 | 450 | /** 451 | * 判断给定字符串是否空白串。 空白串是指由空格、制表符、回车符、换行符组成的字符串 若输入字符串为null或空字符串,返回true 452 | * 453 | * @param input 454 | * @return boolean 若输入字符串为null或空字符串,返回true 455 | */ 456 | public static boolean isEmpty(String input) { 457 | if (input == null || "".equals(input)) 458 | return true; 459 | 460 | for (int i = 0; i < input.length(); i++) { 461 | char c = input.charAt(i); 462 | if (c != ' ' && c != '\t' && c != '\r' && c != '\n') { 463 | return false; 464 | } 465 | } 466 | return true; 467 | } 468 | 469 | /** 470 | * 判断是不是一个合法的电子邮件地址 471 | * 472 | * @param email 473 | * @return 474 | */ 475 | public static boolean isEmail(String email) { 476 | if (email == null || email.trim().length() == 0) 477 | return false; 478 | return EMAILER.matcher(email).matches(); 479 | } 480 | 481 | /** 482 | * 字符串转整数 483 | * 484 | * @param str 485 | * @param defValue 486 | * @return 487 | */ 488 | public static int toInt(String str, int defValue) { 489 | try { 490 | return Integer.parseInt(str); 491 | } catch (Exception e) { 492 | } 493 | return defValue; 494 | } 495 | 496 | /** 497 | * 对象转整数 498 | * 499 | * @param obj 500 | * @return 转换异常返回 0 501 | */ 502 | public static int toInt(Object obj) { 503 | if (obj == null) 504 | return 0; 505 | return toInt(obj.toString(), 0); 506 | } 507 | 508 | /** 509 | * 对象转整数 510 | * 511 | * @param obj 512 | * @return 转换异常返回 0 513 | */ 514 | public static long toLong(String obj) { 515 | try { 516 | return Long.parseLong(obj); 517 | } catch (Exception e) { 518 | } 519 | return 0; 520 | } 521 | 522 | /** 523 | * 字符串转布尔值 524 | * 525 | * @param b 526 | * @return 转换异常返回 false 527 | */ 528 | public static boolean toBool(String b) { 529 | try { 530 | return Boolean.parseBoolean(b); 531 | } catch (Exception e) { 532 | } 533 | return false; 534 | } 535 | 536 | /** 537 | * 判断是不是合法手机 handset 手机号码 538 | */ 539 | public static boolean isHandset(String handset) { 540 | try { 541 | if (!handset.substring(0, 1).equals("1")) { 542 | return false; 543 | } 544 | if (handset == null || handset.length() != 11) { 545 | return false; 546 | } 547 | String check = "^[0123456789]+$"; 548 | Pattern regex = Pattern.compile(check); 549 | Matcher matcher = regex.matcher(handset); 550 | boolean isMatched = matcher.matches(); 551 | if (isMatched) { 552 | return true; 553 | } else { 554 | return false; 555 | } 556 | } catch (RuntimeException e) { 557 | return false; 558 | } 559 | } 560 | 561 | /** 562 | * 判断输入的字符串是否为纯汉字 563 | * 564 | * @param str 传入的字符窜 565 | * @return 如果是纯汉字返回true, 否则返回false 566 | */ 567 | public static boolean isChinese(String str) { 568 | Pattern pattern = Pattern.compile("[\u0391-\uFFE5]+$"); 569 | return pattern.matcher(str).matches(); 570 | } 571 | 572 | /** 573 | * 判断是否为数字 574 | * 575 | * @param str 576 | * @return 577 | */ 578 | public static boolean isNumeric(String str) { 579 | Pattern pattern = Pattern.compile("[0-9]*"); 580 | Matcher isNum = pattern.matcher(str); 581 | if (!isNum.matches()) { 582 | return false; 583 | } 584 | return true; 585 | } 586 | 587 | /** 588 | * 判断是否为整数 589 | * 590 | * @param str 传入的字符串 591 | * @return 是整数返回true, 否则返回false 592 | */ 593 | public static boolean isInteger(String str) { 594 | Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$"); 595 | return pattern.matcher(str).matches(); 596 | } 597 | 598 | /** 599 | * 判断是否为浮点数,包括double和float 600 | * 601 | * @param str 传入的字符串 602 | * @return 是浮点数返回true, 否则返回false 603 | */ 604 | public static boolean isDouble(String str) { 605 | Pattern pattern = Pattern.compile("^[-\\+]?[.\\d]*$"); 606 | return pattern.matcher(str).matches(); 607 | } 608 | 609 | /** 610 | * 是否为空白,包括null和"" 611 | * 612 | * @param str 613 | * @return 614 | */ 615 | public static boolean isBlank(String str) { 616 | return str == null || str.trim().length() == 0; 617 | } 618 | 619 | /** 620 | * 判断是否是指定长度的字符串 621 | * 622 | * @param text 字符串 623 | * @param lenght 自定的长度 624 | * @return 625 | */ 626 | public static boolean isLenghtStrLentht(String text, int lenght) { 627 | if (text.length() <= lenght) 628 | return true; 629 | else 630 | return false; 631 | } 632 | 633 | /** 634 | * 是否是短信的长度 635 | * 636 | * @param text 637 | * @return 638 | */ 639 | public static boolean isSMSStrLentht(String text) { 640 | if (text.length() <= 70) 641 | return true; 642 | else 643 | return false; 644 | } 645 | 646 | /** 647 | * 判断手机号码是否正确 648 | * 649 | * @param phoneNumber 650 | * @return 651 | */ 652 | public static boolean isPhoneNumberValid(String phoneNumber) { 653 | phoneNumber = trimmy(phoneNumber); 654 | NumberUtils mobile = new NumberUtils(phoneNumber); 655 | return mobile.isLawful(); 656 | } 657 | 658 | /** 659 | * 验证手机号码 660 | * 661 | * 移动号码段:139、138、137、136、135、134、150、151、152、157、158、159、182、183、187、188、147、182 662 | * 联通号码段:130、131、132、136、185、186、145 663 | * 电信号码段:133、153、180、189、177 664 | * 665 | * @param cellphone 666 | * @return 667 | */ 668 | public static boolean checkCellphone(String cellphone) { 669 | String regex = "^(13|14|15|17|18)\\d{9}$"; 670 | Pattern pattern=Pattern.compile(regex); 671 | Matcher matcher=pattern.matcher(cellphone); 672 | return matcher.matches(); 673 | } 674 | 675 | // 判断是否为url 676 | public static boolean checkEmail(String email) { 677 | 678 | Pattern pattern = Pattern 679 | .compile("^\\w+([-.]\\w+)*@\\w+([-]\\w+)*\\.(\\w+([-]\\w+)*\\.)*[a-z]{2,3}$"); 680 | Matcher matcher = pattern.matcher(email); 681 | if (matcher.matches()) { 682 | return true; 683 | } 684 | return false; 685 | } 686 | 687 | // 判断微博分享是否为是否为120个 688 | public static boolean isShareStrLentht(String text, int lenght) { 689 | if (text.length() <= 120) 690 | return true; 691 | else 692 | return false; 693 | } 694 | 695 | public static String getFileNameFromUrl(String url) { 696 | 697 | // 名字不能只用这个 698 | // 通过 ‘?’ 和 ‘/’ 判断文件名 699 | String extName = ""; 700 | String filename; 701 | int index = url.lastIndexOf('?'); 702 | if (index > 1) { 703 | extName = url.substring(url.lastIndexOf('.') + 1, index); 704 | } else { 705 | extName = url.substring(url.lastIndexOf('.') + 1); 706 | } 707 | filename = hashKeyForDisk(url) + "." + extName; 708 | return filename; 709 | /* 710 | * int index = url.lastIndexOf('?'); String filename; if (index > 1) { 711 | * filename = url.substring(url.lastIndexOf('/') + 1, index); } else { 712 | * filename = url.substring(url.lastIndexOf('/') + 1); } 713 | * 714 | * if (filename == null || "".equals(filename.trim())) {// 如果获取不到文件名称 715 | * filename = UUID.randomUUID() + ".apk";// 默认取一个文件名 } return filename; 716 | */ 717 | } 718 | 719 | /** 720 | * 一个散列方法,改变一个字符串(如URL)到一个散列适合使用作为一个磁盘文件名。 721 | */ 722 | public static String hashKeyForDisk(String key) { 723 | String cacheKey; 724 | try { 725 | final MessageDigest mDigest = MessageDigest.getInstance("MD5"); 726 | mDigest.update(key.getBytes()); 727 | cacheKey = bytesToHexString(mDigest.digest()); 728 | } catch (NoSuchAlgorithmException e) { 729 | cacheKey = String.valueOf(key.hashCode()); 730 | } 731 | return cacheKey; 732 | } 733 | 734 | private static String bytesToHexString(byte[] bytes) { 735 | StringBuilder sb = new StringBuilder(); 736 | for (int i = 0; i < bytes.length; i++) { 737 | String hex = Integer.toHexString(0xFF & bytes[i]); 738 | if (hex.length() == 1) { 739 | sb.append('0'); 740 | } 741 | sb.append(hex); 742 | } 743 | return sb.toString(); 744 | } 745 | 746 | /** 747 | * 获取去除了url参数的简单url 748 | * 749 | * @param url 750 | * @return 751 | */ 752 | public static String getSimpleUrl(String url) { 753 | String simpleUrl = url.replaceAll("\\?.*", ""); 754 | return simpleUrl; 755 | } 756 | 757 | } 758 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/utils/NetUtils.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.utils; 2 | 3 | import android.content.Context; 4 | import android.net.ConnectivityManager; 5 | import android.net.NetworkInfo; 6 | 7 | /** 8 | * 网络相关工具类 9 | * 10 | * @author Hunter 11 | */ 12 | public class NetUtils { 13 | 14 | /** 15 | * 判断当前网络是否可用 16 | * 17 | * @return 18 | */ 19 | public static boolean isNetworkConnected(Context context) { 20 | if (context != null) { 21 | ConnectivityManager mConnectivityManager = (ConnectivityManager) context 22 | .getSystemService(Context.CONNECTIVITY_SERVICE); 23 | if (mConnectivityManager == null) { 24 | return false; 25 | } 26 | NetworkInfo[] infos = mConnectivityManager.getAllNetworkInfo(); 27 | if (infos != null) { 28 | for (NetworkInfo info : infos) { 29 | if (info.getState() == NetworkInfo.State.CONNECTED) { 30 | return true; 31 | } 32 | } 33 | } 34 | } 35 | 36 | return false; 37 | } 38 | 39 | /** 40 | * 判断当前wifi是否可用 41 | * 42 | * @return 43 | */ 44 | public static boolean isWifiConnected(Context context) { 45 | if (context != null) { 46 | ConnectivityManager mConnectivityManager = (ConnectivityManager) context 47 | .getSystemService(Context.CONNECTIVITY_SERVICE); 48 | NetworkInfo mWiFiNetworkInfo = mConnectivityManager 49 | .getNetworkInfo(ConnectivityManager.TYPE_WIFI); 50 | if (mWiFiNetworkInfo != null) { 51 | return mWiFiNetworkInfo.isAvailable(); 52 | } 53 | } 54 | return false; 55 | } 56 | 57 | /** 58 | * 判断MOBILE网络是否可用 59 | * 60 | * @return 61 | */ 62 | public boolean isMobileConnected(Context context) { 63 | if (context != null) { 64 | ConnectivityManager mConnectivityManager = (ConnectivityManager) context 65 | .getSystemService(Context.CONNECTIVITY_SERVICE); 66 | NetworkInfo mMobileNetworkInfo = mConnectivityManager 67 | .getNetworkInfo(ConnectivityManager.TYPE_MOBILE); 68 | if (mMobileNetworkInfo != null) { 69 | return mMobileNetworkInfo.isAvailable(); 70 | } 71 | } 72 | return false; 73 | } 74 | 75 | /** 76 | * 获取当前网络连接的类型信息 1 wifi 2 移动网络 -1 无网络 77 | * 78 | * @return 79 | */ 80 | public int getConnectedType(Context context) { 81 | if (context != null) { 82 | ConnectivityManager mConnectivityManager = (ConnectivityManager) context 83 | .getSystemService(Context.CONNECTIVITY_SERVICE); 84 | NetworkInfo mNetworkInfo = mConnectivityManager 85 | .getActiveNetworkInfo(); 86 | if (mNetworkInfo != null && mNetworkInfo.isAvailable()) { 87 | return mNetworkInfo.getType() == ConnectivityManager.TYPE_WIFI ? 1 88 | : 2; 89 | } 90 | } 91 | return -1; 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/utils/NumberUtils.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.utils; 2 | 3 | /** 4 | * 号码验证工具类 5 | * 6 | * @author Hunter 7 | */ 8 | public class NumberUtils { 9 | /** 10 | * 中国移动拥有号码段为:139,138,137,136,135,134,159,158,157(3G),151,150,188(3G),187(3G 11 | * );13个号段 中国联通拥有号码段为:130,131,132,156(3G),186(3G),185(3G);6个号段 12 | * 中国电信拥有号码段为:133,153,189(3G),180(3G);4个号码段 13 | */ 14 | private static String mRegMobileStr = "^1(([3][456789])|([5][01789])|([8][78]))[0-9]{8}$"; 15 | private static String mRegMobile3GStr = "^((157)|(18[78]))[0-9]{8}$"; 16 | private static String mRegUnicomStr = "^1(([3][012])|([5][6])|([8][56]))[0-9]{8}$"; 17 | private static String mRegUnicom3GStr = "^((156)|(18[56]))[0-9]{8}$"; 18 | private static String mRegTelecomStr = "^1(([3][3])|([5][3])|([8][09]))[0-9]{8}$"; 19 | private static String mRegTelocom3GStr = "^(18[09])[0-9]{8}$"; 20 | private static String mRegPhoneString = "^(?:13\\d|15\\d)\\d{5}(\\d{3}|\\*{3})$"; 21 | 22 | private String mobile = ""; 23 | private int facilitatorType = 0; 24 | private boolean isLawful = false; 25 | private boolean is3G = false; 26 | 27 | public NumberUtils(String mobile) { 28 | this.setMobile(mobile); 29 | } 30 | 31 | public String getMobile() { 32 | return mobile; 33 | } 34 | 35 | public void setMobile(String mobile) { 36 | if (mobile == null) { 37 | return; 38 | } 39 | /** */ 40 | /** 第一步判断中国移动 */ 41 | if (mobile.matches(NumberUtils.mRegMobileStr)) { 42 | this.mobile = mobile; 43 | this.setFacilitatorType(0); 44 | this.setLawful(true); 45 | if (mobile.matches(NumberUtils.mRegMobile3GStr)) { 46 | this.setIs3G(true); 47 | } 48 | } 49 | /** */ 50 | /** 第二步判断中国联通 */ 51 | else if (mobile.matches(NumberUtils.mRegUnicomStr)) { 52 | this.mobile = mobile; 53 | this.setFacilitatorType(1); 54 | this.setLawful(true); 55 | if (mobile.matches(NumberUtils.mRegUnicom3GStr)) { 56 | this.setIs3G(true); 57 | } 58 | } 59 | /** */ 60 | /** 第三步判断中国电信 */ 61 | else if (mobile.matches(NumberUtils.mRegTelecomStr)) { 62 | this.mobile = mobile; 63 | this.setFacilitatorType(2); 64 | this.setLawful(true); 65 | if (mobile.matches(NumberUtils.mRegTelocom3GStr)) { 66 | this.setIs3G(true); 67 | } 68 | } 69 | /** */ 70 | /** 第四步判断座机 */ 71 | if (mobile.matches(NumberUtils.mRegPhoneString)) { 72 | this.mobile = mobile; 73 | this.setFacilitatorType(0); 74 | this.setLawful(true); 75 | if (mobile.matches(NumberUtils.mRegMobile3GStr)) { 76 | this.setIs3G(true); 77 | } 78 | } 79 | } 80 | 81 | public int getFacilitatorType() { 82 | return facilitatorType; 83 | } 84 | 85 | private void setFacilitatorType(int facilitatorType) { 86 | this.facilitatorType = facilitatorType; 87 | } 88 | 89 | public boolean isLawful() { 90 | return isLawful; 91 | } 92 | 93 | private void setLawful(boolean isLawful) { 94 | this.isLawful = isLawful; 95 | } 96 | 97 | public boolean isIs3G() { 98 | return is3G; 99 | } 100 | 101 | private void setIs3G(boolean is3G) { 102 | this.is3G = is3G; 103 | } 104 | 105 | } 106 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/utils/PixelUtils.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.utils; 2 | 3 | import android.content.Context; 4 | import android.content.res.Resources; 5 | import android.view.WindowManager; 6 | 7 | import com.hunter.fastandroid.app.BaseApplication; 8 | 9 | /** 10 | * 像素转换工具 11 | * 12 | * @author Hunter 13 | */ 14 | public class PixelUtils { 15 | 16 | /** 17 | * The context. 18 | */ 19 | private static Context mContext = BaseApplication.getInstance(); 20 | 21 | /** 22 | * 获取屏幕宽度 23 | * 24 | * @return 25 | */ 26 | public static int getWindowWidth() { 27 | WindowManager wm = (WindowManager) mContext.getSystemService( 28 | Context.WINDOW_SERVICE); 29 | int width = wm.getDefaultDisplay().getWidth(); 30 | 31 | return width; 32 | } 33 | 34 | /** 35 | * 获取屏幕高度 36 | * 37 | * @return 38 | */ 39 | public static int getWindowHeight() { 40 | WindowManager wm = (WindowManager) mContext.getSystemService( 41 | Context.WINDOW_SERVICE); 42 | int height = wm.getDefaultDisplay().getHeight(); 43 | 44 | return height; 45 | } 46 | 47 | /** 48 | * dp转 px. 49 | * 50 | * @param value the value 51 | * @return the int 52 | */ 53 | public static int dp2px(float value) { 54 | final float scale = mContext.getResources().getDisplayMetrics().densityDpi; 55 | return (int) (value * (scale / 160) + 0.5f); 56 | } 57 | 58 | /** 59 | * dp转 px. 60 | * 61 | * @param value the value 62 | * @param context the context 63 | * @return the int 64 | */ 65 | public static int dp2px(float value, Context context) { 66 | final float scale = context.getResources().getDisplayMetrics().densityDpi; 67 | return (int) (value * (scale / 160) + 0.5f); 68 | } 69 | 70 | /** 71 | * px转dp. 72 | * 73 | * @param value the value 74 | * @return the int 75 | */ 76 | public static int px2dp(float value) { 77 | final float scale = mContext.getResources().getDisplayMetrics().densityDpi; 78 | return (int) ((value * 160) / scale + 0.5f); 79 | } 80 | 81 | /** 82 | * px转dp. 83 | * 84 | * @param value the value 85 | * @param context the context 86 | * @return the int 87 | */ 88 | public static int px2dp(float value, Context context) { 89 | final float scale = context.getResources().getDisplayMetrics().densityDpi; 90 | return (int) ((value * 160) / scale + 0.5f); 91 | } 92 | 93 | /** 94 | * sp转px. 95 | * 96 | * @param value the value 97 | * @return the int 98 | */ 99 | public static int sp2px(float value) { 100 | Resources r; 101 | if (mContext == null) { 102 | r = Resources.getSystem(); 103 | } else { 104 | r = mContext.getResources(); 105 | } 106 | float spvalue = value * r.getDisplayMetrics().scaledDensity; 107 | return (int) (spvalue + 0.5f); 108 | } 109 | 110 | /** 111 | * sp转px. 112 | * 113 | * @param value the value 114 | * @param context the context 115 | * @return the int 116 | */ 117 | public static int sp2px(float value, Context context) { 118 | Resources r; 119 | if (context == null) { 120 | r = Resources.getSystem(); 121 | } else { 122 | r = context.getResources(); 123 | } 124 | float spvalue = value * r.getDisplayMetrics().scaledDensity; 125 | return (int) (spvalue + 0.5f); 126 | } 127 | 128 | /** 129 | * px转sp. 130 | * 131 | * @param value the value 132 | * @return the int 133 | */ 134 | public static int px2sp(float value) { 135 | final float scale = mContext.getResources().getDisplayMetrics().scaledDensity; 136 | return (int) (value / scale + 0.5f); 137 | } 138 | 139 | /** 140 | * px转sp. 141 | * 142 | * @param value the value 143 | * @param context the context 144 | * @return the int 145 | */ 146 | public static int px2sp(float value, Context context) { 147 | final float scale = context.getResources().getDisplayMetrics().scaledDensity; 148 | return (int) (value / scale + 0.5f); 149 | } 150 | } -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/utils/SdCardUtils.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.utils; 2 | 3 | import android.annotation.TargetApi; 4 | import android.os.Build; 5 | import android.os.Environment; 6 | import android.os.StatFs; 7 | 8 | import java.io.BufferedInputStream; 9 | import java.io.BufferedReader; 10 | import java.io.File; 11 | import java.io.FileNotFoundException; 12 | import java.io.IOException; 13 | import java.io.InputStream; 14 | import java.io.InputStreamReader; 15 | import java.util.ArrayList; 16 | 17 | /** 18 | * SD卡操作工具类 19 | * 20 | * @author Hunter 21 | */ 22 | public class SdCardUtils { 23 | private static final String TAG = SdCardUtils.class.getSimpleName(); 24 | 25 | /** 26 | * Get {@link StatFs}. 27 | */ 28 | public static StatFs getStatFs(String path) { 29 | return new StatFs(path); 30 | } 31 | 32 | /** 33 | * Get phone data path. 34 | */ 35 | public static String getDataPath() { 36 | return Environment.getDataDirectory().getPath(); 37 | } 38 | 39 | /** 40 | * Get SD card path. 41 | */ 42 | public static String getNormalSDCardPath() { 43 | return Environment.getExternalStorageDirectory().getPath(); 44 | } 45 | 46 | /** 47 | * Get SD card path by CMD. 48 | */ 49 | public static String getSDCardPath() { 50 | String cmd = "cat /proc/mounts"; 51 | String sdcard = null; 52 | Runtime run = Runtime.getRuntime();// 返回与当前 Java 应用程序相关的运行时对象 53 | BufferedReader bufferedReader = null; 54 | try { 55 | Process p = run.exec(cmd);// 启动另一个进程来执行命令 56 | bufferedReader = new BufferedReader(new InputStreamReader(new BufferedInputStream(p.getInputStream()))); 57 | String lineStr; 58 | while ((lineStr = bufferedReader.readLine()) != null) { 59 | if (lineStr.contains("sdcard") 60 | && lineStr.contains(".android_secure")) { 61 | String[] strArray = lineStr.split(" "); 62 | if (strArray.length >= 5) { 63 | sdcard = strArray[1].replace("/.android_secure", ""); 64 | return sdcard; 65 | } 66 | } 67 | if (p.waitFor() != 0 && p.exitValue() == 1) { 68 | // p.exitValue()==0表示正常结束,1:非正常结束 69 | } 70 | } 71 | } catch (Exception e) { 72 | e.printStackTrace(); 73 | } finally { 74 | try { 75 | if (bufferedReader != null) { 76 | bufferedReader.close(); 77 | } 78 | } catch (IOException e) { 79 | e.printStackTrace(); 80 | } 81 | } 82 | sdcard = Environment.getExternalStorageDirectory().getPath(); 83 | return sdcard; 84 | } 85 | 86 | /** 87 | * Get SD card path list. 88 | */ 89 | public static ArrayList getSDCardPathEx() { 90 | ArrayList list = new ArrayList(); 91 | try { 92 | Runtime runtime = Runtime.getRuntime(); 93 | Process proc = runtime.exec("mount"); 94 | InputStream is = proc.getInputStream(); 95 | InputStreamReader isr = new InputStreamReader(is); 96 | String line; 97 | BufferedReader br = new BufferedReader(isr); 98 | while ((line = br.readLine()) != null) { 99 | if (line.contains("secure")) { 100 | continue; 101 | } 102 | if (line.contains("asec")) { 103 | continue; 104 | } 105 | 106 | if (line.contains("fat")) { 107 | String columns[] = line.split(" "); 108 | if (columns.length > 1) { 109 | list.add("*" + columns[1]); 110 | } 111 | } else if (line.contains("fuse")) { 112 | String columns[] = line.split(" "); 113 | if (columns.length > 1) { 114 | list.add(columns[1]); 115 | } 116 | } 117 | } 118 | } catch (FileNotFoundException e) { 119 | e.printStackTrace(); 120 | } catch (IOException e) { 121 | e.printStackTrace(); 122 | } 123 | return list; 124 | } 125 | 126 | /** 127 | * Get available size of SD card. 128 | */ 129 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) 130 | public static long getAvailableSize(String path) { 131 | try { 132 | File base = new File(path); 133 | StatFs stat = new StatFs(base.getPath()); 134 | return stat.getBlockSizeLong() * stat.getAvailableBlocksLong(); 135 | } catch (Exception e) { 136 | e.printStackTrace(); 137 | } 138 | return 0; 139 | } 140 | 141 | /** 142 | * Get SD card info detail. 143 | */ 144 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) 145 | public static SDCardInfo getSDCardInfo() { 146 | SDCardInfo sd = new SDCardInfo(); 147 | String state = Environment.getExternalStorageState(); 148 | if (Environment.MEDIA_MOUNTED.equals(state)) { 149 | sd.isExist = true; 150 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { 151 | File sdcardDir = Environment.getExternalStorageDirectory(); 152 | StatFs sf = new StatFs(sdcardDir.getPath()); 153 | 154 | sd.totalBlocks = sf.getBlockCountLong(); 155 | sd.blockByteSize = sf.getBlockSizeLong(); 156 | 157 | sd.availableBlocks = sf.getAvailableBlocksLong(); 158 | sd.availableBytes = sf.getAvailableBytes(); 159 | 160 | sd.freeBlocks = sf.getFreeBlocksLong(); 161 | sd.freeBytes = sf.getFreeBytes(); 162 | 163 | sd.totalBytes = sf.getTotalBytes(); 164 | } 165 | } 166 | return sd; 167 | } 168 | 169 | 170 | /** 171 | * see more {@link StatFs} 172 | */ 173 | public static class SDCardInfo { 174 | public boolean isExist; 175 | public long totalBlocks; 176 | public long freeBlocks; 177 | public long availableBlocks; 178 | 179 | public long blockByteSize; 180 | 181 | public long totalBytes; 182 | public long freeBytes; 183 | public long availableBytes; 184 | 185 | @Override 186 | public String toString() { 187 | return "SDCardInfo{" + 188 | "isExist=" + isExist + 189 | ", totalBlocks=" + totalBlocks + 190 | ", freeBlocks=" + freeBlocks + 191 | ", availableBlocks=" + availableBlocks + 192 | ", blockByteSize=" + blockByteSize + 193 | ", totalBytes=" + totalBytes + 194 | ", freeBytes=" + freeBytes + 195 | ", availableBytes=" + availableBytes + 196 | '}'; 197 | } 198 | } 199 | } 200 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/utils/SystemUtils.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.utils; 2 | 3 | import android.content.Context; 4 | import android.content.pm.PackageInfo; 5 | import android.content.pm.PackageManager; 6 | import android.net.ConnectivityManager; 7 | import android.net.NetworkInfo; 8 | import android.telephony.TelephonyManager; 9 | import android.text.TextUtils; 10 | 11 | 12 | import com.hunter.fastandroid.app.BaseApplication; 13 | 14 | import static android.content.Context.TELEPHONY_SERVICE; 15 | 16 | public class SystemUtils { 17 | public static String getModel() { 18 | return android.os.Build.MODEL; 19 | } 20 | 21 | 22 | public static String getSysVersion() { 23 | return android.os.Build.VERSION.RELEASE; 24 | } 25 | 26 | public static String getAppVersion() { 27 | return getAppVersionName(BaseApplication.getInstance()); 28 | } 29 | 30 | public static String getOperatorName() { 31 | TelephonyManager telephonyManager = (TelephonyManager) BaseApplication.getInstance().getSystemService(TELEPHONY_SERVICE); 32 | if (telephonyManager == null) { 33 | return "OTHER"; 34 | } 35 | return telephonyManager.getSimOperatorName(); 36 | } 37 | 38 | public static String getNetworkState() { 39 | //获取系统的网络服务 40 | ConnectivityManager connManager = (ConnectivityManager) BaseApplication.getInstance().getSystemService(Context.CONNECTIVITY_SERVICE); 41 | 42 | //如果当前没有网络 43 | if (null == connManager) 44 | return ""; 45 | 46 | //获取当前网络类型,如果为空,返回无网络 47 | NetworkInfo activeNetInfo = connManager.getActiveNetworkInfo(); 48 | if (activeNetInfo == null || !activeNetInfo.isAvailable()) { 49 | return ""; 50 | } 51 | 52 | // 判断是不是连接的是不是wifi 53 | NetworkInfo wifiInfo = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI); 54 | if (null != wifiInfo) { 55 | NetworkInfo.State state = wifiInfo.getState(); 56 | if (null != state) 57 | if (state == NetworkInfo.State.CONNECTED || state == NetworkInfo.State.CONNECTING) { 58 | return "WIFI"; 59 | } 60 | } 61 | 62 | // 如果不是wifi,则判断当前连接的是运营商的哪种网络2g、3g、4g等 63 | NetworkInfo networkInfo = connManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE); 64 | 65 | if (null != networkInfo) { 66 | NetworkInfo.State state = networkInfo.getState(); 67 | String strSubTypeName = networkInfo.getSubtypeName(); 68 | if (null != state) 69 | if (state == NetworkInfo.State.CONNECTED || state == NetworkInfo.State.CONNECTING) { 70 | switch (activeNetInfo.getSubtype()) { 71 | //如果是2g类型 72 | case TelephonyManager.NETWORK_TYPE_GPRS: // 联通2g 73 | case TelephonyManager.NETWORK_TYPE_CDMA: // 电信2g 74 | case TelephonyManager.NETWORK_TYPE_EDGE: // 移动2g 75 | case TelephonyManager.NETWORK_TYPE_1xRTT: 76 | case TelephonyManager.NETWORK_TYPE_IDEN: 77 | return "2G"; 78 | //如果是3g类型 79 | case TelephonyManager.NETWORK_TYPE_EVDO_A: // 电信3g 80 | case TelephonyManager.NETWORK_TYPE_UMTS: 81 | case TelephonyManager.NETWORK_TYPE_EVDO_0: 82 | case TelephonyManager.NETWORK_TYPE_HSDPA: 83 | case TelephonyManager.NETWORK_TYPE_HSUPA: 84 | case TelephonyManager.NETWORK_TYPE_HSPA: 85 | case TelephonyManager.NETWORK_TYPE_EVDO_B: 86 | case TelephonyManager.NETWORK_TYPE_EHRPD: 87 | case TelephonyManager.NETWORK_TYPE_HSPAP: 88 | return "3G"; 89 | //如果是4g类型 90 | case TelephonyManager.NETWORK_TYPE_LTE: 91 | return "4G"; 92 | default: 93 | //中国移动 联通 电信 三种3G制式 94 | if (strSubTypeName.equalsIgnoreCase("TD-SCDMA") || strSubTypeName.equalsIgnoreCase("WCDMA") || strSubTypeName.equalsIgnoreCase("CDMA2000")) { 95 | return "3G"; 96 | } else { 97 | return "OTHER"; 98 | } 99 | } 100 | } 101 | } 102 | return ""; 103 | } 104 | 105 | public static String getIMEI() { 106 | return android.os.Build.SERIAL; 107 | } 108 | 109 | //获取当前版本号 110 | private static String getAppVersionName(Context context) { 111 | String versionName = ""; 112 | try { 113 | PackageManager packageManager = context.getPackageManager(); 114 | PackageInfo packageInfo = packageManager.getPackageInfo(context.getPackageName(), 0); 115 | versionName = packageInfo.versionName; 116 | if (TextUtils.isEmpty(versionName)) { 117 | return ""; 118 | } 119 | } catch (Exception e) { 120 | e.printStackTrace(); 121 | } 122 | return versionName; 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/vo/Book.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.vo; 2 | 3 | public class Book extends Page { 4 | private String title; 5 | private String publisher; 6 | private String price; 7 | private String image; 8 | 9 | public String getTitle() { 10 | return title; 11 | } 12 | 13 | public void setTitle(String title) { 14 | this.title = title; 15 | } 16 | 17 | public String getPublisher() { 18 | return publisher; 19 | } 20 | 21 | public void setPublisher(String publisher) { 22 | this.publisher = publisher; 23 | } 24 | 25 | public String getPrice() { 26 | return price; 27 | } 28 | 29 | public void setPrice(String price) { 30 | this.price = price; 31 | } 32 | 33 | public String getImage() { 34 | return image; 35 | } 36 | 37 | public void setImage(String image) { 38 | this.image = image; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/vo/DoubanResponse.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.vo; 2 | 3 | import java.util.List; 4 | 5 | public class DoubanResponse extends Page{ 6 | private List books; 7 | 8 | public List getBooks() { 9 | return books; 10 | } 11 | 12 | public void setBooks(List books) { 13 | this.books = books; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/vo/JsonResponse.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.vo; 2 | 3 | /** 4 | * 服务器响应实体类 5 | * 6 | * @param 7 | * @author Hunter 8 | */ 9 | public class JsonResponse { 10 | public final static int SUCCESS = 10000; 11 | public final static int TOKEN_EXPIRE = 99997; 12 | 13 | 14 | private int status; 15 | private String message; 16 | private T data; 17 | 18 | 19 | /** 20 | * TOKEN是否过期 21 | * @return true 过期 flase 未过期 22 | */ 23 | public boolean isTokenValid() { 24 | return TOKEN_EXPIRE == status; 25 | } 26 | 27 | public boolean isSuccess() { 28 | return SUCCESS == status; 29 | } 30 | 31 | public int getStatus() { 32 | return status; 33 | } 34 | 35 | public void setStatus(int status) { 36 | this.status = status; 37 | } 38 | 39 | public String getMessage() { 40 | return message; 41 | } 42 | 43 | public void setMessage(String message) { 44 | this.message = message; 45 | } 46 | 47 | public T getData() { 48 | return data; 49 | } 50 | 51 | public void setData(T data) { 52 | this.data = data; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/vo/Page.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.vo; 2 | 3 | public class Page { 4 | private Long start; 5 | private Long count; 6 | private Long total; 7 | 8 | public Long getStart() { 9 | return start; 10 | } 11 | 12 | public void setStart(Long start) { 13 | this.start = start; 14 | } 15 | 16 | public Long getCount() { 17 | return count; 18 | } 19 | 20 | public void setCount(Long count) { 21 | this.count = count; 22 | } 23 | 24 | public Long getTotal() { 25 | return total; 26 | } 27 | 28 | public void setTotal(Long total) { 29 | this.total = total; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /fastandroid/src/main/java/com/hunter/fastandroid/vo/User.java: -------------------------------------------------------------------------------- 1 | package com.hunter.fastandroid.vo; 2 | 3 | import org.greenrobot.greendao.annotation.Entity; 4 | import org.greenrobot.greendao.annotation.Generated; 5 | import org.greenrobot.greendao.annotation.Id; 6 | import org.greenrobot.greendao.annotation.Property; 7 | import org.greenrobot.greendao.annotation.Transient; 8 | 9 | /** 10 | * Created by Administrator on 2017/1/10. 11 | */ 12 | @Entity 13 | public class User { 14 | @Id 15 | private Long id; 16 | private String userToken = ""; 17 | private String userName = ""; 18 | @Property(nameInDb = "sex") 19 | private String userSex = ""; 20 | @Transient 21 | private String userData = ""; 22 | @Generated(hash = 530591236) 23 | public User(Long id, String userToken, String userName, String userSex) { 24 | this.id = id; 25 | this.userToken = userToken; 26 | this.userName = userName; 27 | this.userSex = userSex; 28 | } 29 | @Generated(hash = 586692638) 30 | public User() { 31 | } 32 | public Long getId() { 33 | return this.id; 34 | } 35 | public void setId(Long id) { 36 | this.id = id; 37 | } 38 | public String getUserToken() { 39 | return this.userToken; 40 | } 41 | public void setUserToken(String userToken) { 42 | this.userToken = userToken; 43 | } 44 | public String getUserName() { 45 | return this.userName; 46 | } 47 | public void setUserName(String userName) { 48 | this.userName = userName; 49 | } 50 | public String getUserSex() { 51 | return this.userSex; 52 | } 53 | public void setUserSex(String userSex) { 54 | this.userSex = userSex; 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /fastandroid/src/main/res/anim/push_left_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /fastandroid/src/main/res/anim/push_left_out.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | -------------------------------------------------------------------------------- /fastandroid/src/main/res/anim/push_right_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | -------------------------------------------------------------------------------- /fastandroid/src/main/res/anim/push_right_out.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | -------------------------------------------------------------------------------- /fastandroid/src/main/res/drawable/bg_progress.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /fastandroid/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 10 | 11 | 19 | 20 |