BaseApp
public class BaseApp extends Application {
private static BaseApp sBaseApp;
//默认不是夜间模式
public static int mMode = AppCompatDelegate.MODE_NIGHT_NO;
@Override
public void onCreate() {
super.onCreate();
sBaseApp = this;
}
public static BaseApp getInstance(){
return sBaseApp;
}
}
ToastUtil(Toast 工具类)
public class ToastUtil {
public static void showShort(String msg){
//避免内存泄漏的一个方法,用到上下文的地方,能用application的就application
Toast.makeText(BaseApp.getInstance(),msg,Toast.LENGTH_SHORT).show();
}
public static void showLong(String msg){
//避免内存泄漏的一个方法,用到上下文的地方,能用application的就application
Toast.makeText(BaseApp.getInstance(),msg,Toast.LENGTH_LONG).show();
}
}
MyAppGlideModule(自动缓存图片的工具类,不需要调用,放到项目里就可以)
import android.content.Context;
import com.bumptech.glide.Glide;
import com.bumptech.glide.GlideBuilder;
import com.bumptech.glide.Registry;
import com.bumptech.glide.annotation.GlideModule;
import com.bumptech.glide.load.engine.cache.ExternalPreferredCacheDiskCacheFactory;
import com.bumptech.glide.module.AppGlideModule;
@GlideModule
public class MyAppGlideModule extends AppGlideModule {
// "me" 是应用在内存卡里创建的文件名,自己随便起
@Override
public void applyOptions(Context context, GlideBuilder builder) {
builder.setDiskCache(new ExternalPreferredCacheDiskCacheFactory(
context,"me",1024*1024*500));
}
@Override
public void registerComponents(Context context, Glide glide, Registry registry) {
}
}
HttpUtils、RxUtils、Constants(Retrofit+Rxjava网络请求数据时使用)
1.HttpUtils
import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import okhttp3.Cache;
import okhttp3.CacheControl;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
public class HttpUtils {
private final Retrofit.Builder mRetrofitBuilder;
private HttpUtils(){
OkHttpClient mOkHttpClient = getOkHttpClient();
mRetrofitBuilder = getRetrofit(mOkHttpClient);
}
private static volatile HttpUtils instance;
public static HttpUtils getInstance(){
if(instance == null){
synchronized (HttpUtils.class){
if(instance == null){
instance = new HttpUtils();
}
}
}
return instance;
}
//获取数据加载的Retrofit
private Retrofit.Builder getRetrofit(OkHttpClient okHttpClient){
return new Retrofit.Builder()
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create());
}
/**
* 固定模板
* 创建带缓存的OkhttpClient
* @return
*/
private OkHttpClient getOkHttpClient() {
//设置本地缓存文件
File cacheFile = new File(Constants.PATH_CACHE);
//设置缓存文件大小
Cache cache = new Cache(cacheFile, 1024 * 1024 * 50);
return new OkHttpClient.Builder().
cache(cache)
.addInterceptor(new MyCacheinterceptor())
.addNetworkInterceptor(new MyCacheinterceptor())
//设置缓存时间
.writeTimeout(60, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS)
.connectTimeout(10, TimeUnit.SECONDS)
//设置错误重连
.retryOnConnectionFailure(true).build();
}
/**
* 固定模板
*/
private class MyCacheinterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
//这里就是说判读我们的网络条件,要是有网络的话我么就直接获取网络上
// 面的数据,要是没有网络的话我么就去缓存里面取数据
if (!SystemUtil.isNetworkConnected()) {
request = request
.newBuilder()
.cacheControl(CacheControl.FORCE_CACHE)
.build();
}
Response originalResponse = chain.proceed(request);
if (SystemUtil.isNetworkConnected()) {
int maxAge = 0;
// 有网络时, 不缓存, 最大保存时长为0
return originalResponse.newBuilder()
.removeHeader("Pragma")
.header("Cache-Control", "public ,max-age=" + maxAge)
.build();
} else {
//s秒
int maxStale = 60 * 60 * 24;
return originalResponse.newBuilder()
.removeHeader("Pragma")
//这里的设置的是我们的没有网络的缓存时间,
// 想设置多少就是多少。
.header("Cache-Control", "public, only-if-cached," +
" max-stale=" + maxStale)
.build();
}
}
}
//创建Retrofit请求数据接口
public synchronized T getApiserver(String baseUrl,Class tClass){
return mRetrofitBuilder.baseUrl(baseUrl).build().create(tClass);
}
/* //创建Retrofit请求数据接口
public synchronized T getApiserver(String baseUrl,Class tClass){
return mRetrofit.create(tClass);
}*/
}
2.RxUtils
import io.reactivex.Flowable;
import io.reactivex.FlowableTransformer;
import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.ObservableTransformer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
public class RxUtils {
/**
* 同一线程处理
* @param
* @return
*/
public static FlowableTransformer rxSchedulerHelper(){
//compose简化线程
return new FlowableTransformer() {
@Override
public Flowable apply(Flowable upstream) {
return upstream.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
}
};
}
public static ObservableTransformer rxObservableSchedulerHelper(){
//compose 简化线程
return new ObservableTransformer() {
@Override
public ObservableSource apply(Observable upstream) {
return upstream.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
}
};
}
}
3.Constants
public interface Constants {
boolean isDebug = true;
String PATH_SDCARD = Environment.getExternalStorageDirectory().getAbsolutePath() +
File.separator + "codeest" + File.separator + "GeekNews";
String FILE_PROVIDER_AUTHORITY="com.baidu.geek.fileprovider";
//网络缓存的地址
String PATH_DATA = BaseApp.getInstance().getCacheDir().getAbsolutePath() +
File.separator + "data";
String PATH_CACHE = PATH_DATA + "/NetCache";
String DATA = "data";
//夜间模式
String MODE = "mode";
String NIGHT_CURRENT_FRAG_POS = "fragment_pos";
String DATE="date";
}
用法
// DailyNewsBean 数据的bean类
// CallBack MVP中的callback接口
public void getData(final CallBack callBack) {
HttpService httpService = HttpUtils.getInstance().getApiserver(HttpService.dailyNewsUrl, HttpService.class);
httpService.getDailyNewsData().compose(RxUtils.rxObservableSchedulerHelper())
.subscribe(new Observer() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(DailyNewsBean dailyNewsBean) {
callBack.onSuccess(dailyNewsBean);
}
@Override
public void onError(Throwable e) {
callBack.onFail(e.getMessage());
}
@Override
public void onComplete() {
}
});
接口
public interface HttpService {
String dailyNewsUrl="http://news-at.zhihu.com/api/4/";
@GET("news/latest")
Observable getDailyNewsData();
}
SpUtil(记住密码等可以使用)
//Sharepreference
public class SpUtil {
/**
* 保存在手机里面的文件名
*/
private static final String FILE_NAME = "share_date";
/**
* 保存数据的方法,我们需要拿到保存数据的具体类型,然后根据类型调用不同的保存方法
* @param key
* @param object
*/
public static void setParam( String key, Object object){
String type = object.getClass().getSimpleName();
SharedPreferences sp = BaseApp.getInstance().getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
if("String".equals(type)){
editor.putString(key, (String)object);
}
else if("Integer".equals(type)){
editor.putInt(key, (Integer)object);
}
else if("Boolean".equals(type)){
editor.putBoolean(key, (Boolean)object);
}
else if("Float".equals(type)){
editor.putFloat(key, (Float)object);
}
else if("Long".equals(type)){
editor.putLong(key, (Long)object);
}
editor.commit();
}
/**
* 得到保存数据的方法,我们根据默认值得到保存的数据的具体类型,然后调用相对于的方法获取值
* @param key
* @param defaultObject
* @return
*/
public static Object getParam(String key, Object defaultObject){
String type = defaultObject.getClass().getSimpleName();
SharedPreferences sp = BaseApp.getInstance().getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);
if("String".equals(type)){
return sp.getString(key, (String)defaultObject);
}
else if("Integer".equals(type)){
return sp.getInt(key, (Integer)defaultObject);
}
else if("Boolean".equals(type)){
return sp.getBoolean(key, (Boolean)defaultObject);
}
else if("Float".equals(type)){
return sp.getFloat(key, (Float)defaultObject);
}
else if("Long".equals(type)){
return sp.getLong(key, (Long)defaultObject);
}
return null;
}
}
用法
// Constants.NIGHT_CURRENT_FRAG_POS 存储或获取数据的标记
// 保存
// 0 要保存的数据
SpUtil.setParam(Constants.NIGHT_CURRENT_FRAG_POS, 0);
// 获取
// 0 获取数据的默认值,可以随便输入,类型和要获取到的数据的类型一样就可以
int type = (int) SpUtil.getParam(Constants.NIGHT_CURRENT_FRAG_POS, 0);
SystemUtil
里面有方法可以实现根据手机的分辨率从 dp 的单位 转成为 px(像素),从 px(像素) 的单位 转成为 dp
public class SystemUtil {
/**
* 检查WIFI是否连接
*/
public static boolean isWifiConnected() {
ConnectivityManager connectivityManager = (ConnectivityManager) BaseApp.getInstance().getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo wifiInfo = connectivityManager
.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
return wifiInfo != null;
}
/**
* 检查手机网络(4G/3G/2G)是否连接
*/
public static boolean isMobileNetworkConnected() {
ConnectivityManager connectivityManager = (ConnectivityManager) BaseApp.getInstance().getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo mobileNetworkInfo = connectivityManager
.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
return mobileNetworkInfo != null;
}
/**
* 检查是否有可用网络
*/
public static boolean isNetworkConnected() {
ConnectivityManager connectivityManager = (ConnectivityManager) BaseApp.getInstance().getSystemService(Context.CONNECTIVITY_SERVICE);
return connectivityManager.getActiveNetworkInfo() != null;
}
/**
* 保存文字到剪贴板
* @param context
* @param text
*/
public static void copyToClipBoard(Context context, String text) {
ClipData clipData = ClipData.newPlainText("url", text);
ClipboardManager manager = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
manager.setPrimaryClip(clipData);
Toast.makeText(context,"已复制到剪贴板",Toast.LENGTH_SHORT).show();
}
/**
* 保存图片到本地
* @param context
* @param url
* @param bitmap
*/
public static Uri saveBitmapToFile(Context context, String url, Bitmap bitmap,
View container, boolean isShare){
String fileName = url.substring(url.lastIndexOf("/"),url.lastIndexOf(".")) + ".png";
File fileDir = new File(Constants.PATH_SDCARD);
if (!fileDir.exists()){
fileDir.mkdirs();
}
File imageFile = new File(fileDir,fileName);
Uri uri = Uri.fromFile(imageFile);
if (isShare && imageFile.exists()) {
if (Build.VERSION.SDK_INT >= 24) {
uri = FileProvider.getUriForFile(context.getApplicationContext(),
Constants.FILE_PROVIDER_AUTHORITY, imageFile);
}
return uri;
}
try {
FileOutputStream fos = new FileOutputStream(imageFile);
boolean isCompress = bitmap.compress(Bitmap.CompressFormat.PNG, 90, fos);
if (isCompress) {
ToastUtil.showShort("保存妹纸成功n(*≧▽≦*)n");
} else {
ToastUtil.showShort("保存妹纸失败ヽ(≧Д≦)ノ");
}
fos.flush();
fos.close();
} catch (IOException e) {
e.printStackTrace();
ToastUtil.showShort("保存妹纸失败ヽ(≧Д≦)ノ");
}
try {
MediaStore.Images.Media.insertImage(context.getContentResolver(), imageFile.getAbsolutePath(), fileName, null);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,uri));
if (Build.VERSION.SDK_INT >= 24) {
uri = FileProvider.getUriForFile(context.getApplicationContext(),
Constants.FILE_PROVIDER_AUTHORITY, imageFile);
}
return uri;
}
/**
* 根据手机的分辨率从 dp 的单位 转成为 px(像素)
*/
public static int dp2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
public static int dp2px(float dpValue) {
final float scale = BaseApp.getInstance().getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
/**
* 根据手机的分辨率从 px(像素) 的单位 转成为 dp
*/
public static int px2dp(Context context, float pxValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}
public static int px2dp(float pxValue) {
final float scale = BaseApp.getInstance().getResources().getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}
/**
* 获取进程号对应的进程名
*
* @param pid 进程号
* @return 进程名
*/
public static String getProcessName(int pid) {
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader("/proc/" + pid + "/cmdline"));
String processName = reader.readLine();
if (!TextUtils.isEmpty(processName)) {
processName = processName.trim();
}
return processName;
} catch (Throwable throwable) {
throwable.printStackTrace();
} finally {
try {
if (reader != null) {
reader.close();
}
} catch (IOException exception) {
exception.printStackTrace();
}
}
return null;
}
}
UIModeUtil(应用切换日夜间模式时使用)
里面使用到的BaseApp和Constants上面有
/**
* 使用这个类需要把style设置成日夜间的样式:Theme.AppCompat.DayNight.NoActionBar
*/
public class UIModeUtil {
/**
* 夜间模式切换
*/
public static void changeModeUI(AppCompatActivity activity){
int currentNightMode = activity.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
if(currentNightMode == Configuration.UI_MODE_NIGHT_NO){
//日间模式,切成夜间模式
activity.getDelegate().setLocalNightMode(AppCompatDelegate.MODE_NIGHT_YES);
SpUtil.setParam(Constants.MODE,AppCompatDelegate.MODE_NIGHT_YES);
BaseApp.mMode = AppCompatDelegate.MODE_NIGHT_YES;
}else{
activity.getDelegate().setLocalNightMode(AppCompatDelegate.MODE_NIGHT_NO);
SpUtil.setParam(Constants.MODE,AppCompatDelegate.MODE_NIGHT_NO);
BaseApp.mMode = AppCompatDelegate.MODE_NIGHT_NO;
}
}
/**
* 设置当前的模式
* @param activity
*/
public static void setActModeFromSp(AppCompatActivity activity){
int mode = (int) SpUtil.getParam(Constants.MODE, AppCompatDelegate.MODE_NIGHT_NO);
activity.getDelegate().setLocalNightMode(mode);
}
/**
* 设置当前的模式
* @param activity
*/
public static void setActModeUseMode(AppCompatActivity activity,int mode){
activity.getDelegate().setLocalNightMode(mode);
}
public static void setAppMode(int mode){
AppCompatDelegate.setDefaultNightMode(mode);
}
}