From 31ad69bad9c5a3009352eb6ffd1e6a1b94c7415a Mon Sep 17 00:00:00 2001 From: jessyan Date: Fri, 16 Dec 2016 19:25:57 +0800 Subject: [PATCH] optimize demo --- .../mvparms/demo/app/utils/FastBlur.java | 291 ++++++++++++++++++ .../mvparms/demo/di/module/ServiceModule.java | 7 + .../mvparms/demo/mvp/model/UserModel.java | 2 +- .../mvparms/demo/mvp/model/api/Api.java | 3 +- .../mvp/model/api/service/CommonService.java | 27 +- .../mvp/model/api/service/ServiceManager.java | 8 +- .../mvp/model/api/service/UserService.java | 25 ++ .../demo/mvp/model/entity/BaseJson.java | 42 +++ .../demo/mvp/presenter/UserPresenter.java | 4 +- .../com/jess/arms/base/BaseApplication.java | 1 - .../java/com/jess/arms/utils/RxUtils.java | 55 ++++ 11 files changed, 433 insertions(+), 32 deletions(-) create mode 100644 app/src/main/java/me/jessyan/mvparms/demo/app/utils/FastBlur.java create mode 100644 app/src/main/java/me/jessyan/mvparms/demo/mvp/model/api/service/UserService.java create mode 100644 app/src/main/java/me/jessyan/mvparms/demo/mvp/model/entity/BaseJson.java create mode 100644 arms/src/main/java/com/jess/arms/utils/RxUtils.java diff --git a/app/src/main/java/me/jessyan/mvparms/demo/app/utils/FastBlur.java b/app/src/main/java/me/jessyan/mvparms/demo/app/utils/FastBlur.java new file mode 100644 index 0000000..f6cdbae --- /dev/null +++ b/app/src/main/java/me/jessyan/mvparms/demo/app/utils/FastBlur.java @@ -0,0 +1,291 @@ +package me.jessyan.mvparms.demo.app.utils; + +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.drawable.BitmapDrawable; +import android.util.Log; +import android.view.View; + +import com.jess.arms.utils.DrawableProvider; +import com.jess.arms.utils.UiUtils; + +/** + * 使图片高斯模糊 + * Created by paveld on 3/6/14. + */ +public class FastBlur { + + public static Bitmap doBlur(Bitmap sentBitmap, int radius, boolean canReuseInBitmap) { + + // Stack Blur v1.0 from + // http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html + // + // Java Author: Mario Klingemann + // http://incubator.quasimondo.com + // created Feburary 29, 2004 + // Android port : Yahel Bouaziz + // http://www.kayenko.com + // ported april 5th, 2012 + + // This is a compromise between Gaussian Blur and Box blur + // It creates much better looking blurs than Box Blur, but is + // 7x faster than my Gaussian Blur implementation. + // + // I called it Stack Blur because this describes best how this + // filter works internally: it creates a kind of moving stack + // of colors whilst scanning through the image. Thereby it + // just has to add one new block of color to the right side + // of the stack and remove the leftmost color. The remaining + // colors on the topmost layer of the stack are either added on + // or reduced by one, depending on if they are on the right or + // on the left side of the stack. + // + // If you are using this algorithm in your code please add + // the following line: + // + // Stack Blur Algorithm by Mario Klingemann + + Bitmap bitmap; + if (canReuseInBitmap) { + bitmap = sentBitmap; + } else { + bitmap = sentBitmap.copy(sentBitmap.getConfig(), true); + } + + if (radius < 1) { + return (null); + } + + int w = bitmap.getWidth(); + int h = bitmap.getHeight(); + + int[] pix = new int[w * h]; + bitmap.getPixels(pix, 0, w, 0, 0, w, h); + + int wm = w - 1; + int hm = h - 1; + int wh = w * h; + int div = radius + radius + 1; + + int r[] = new int[wh]; + int g[] = new int[wh]; + int b[] = new int[wh]; + int rsum, gsum, bsum, x, y, i, p, yp, yi, yw; + int vmin[] = new int[Math.max(w, h)]; + + int divsum = (div + 1) >> 1; + divsum *= divsum; + int dv[] = new int[256 * divsum]; + for (i = 0; i < 256 * divsum; i++) { + dv[i] = (i / divsum); + } + + yw = yi = 0; + + int[][] stack = new int[div][3]; + int stackpointer; + int stackstart; + int[] sir; + int rbs; + int r1 = radius + 1; + int routsum, goutsum, boutsum; + int rinsum, ginsum, binsum; + + for (y = 0; y < h; y++) { + rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0; + for (i = -radius; i <= radius; i++) { + p = pix[yi + Math.min(wm, Math.max(i, 0))]; + sir = stack[i + radius]; + sir[0] = (p & 0xff0000) >> 16; + sir[1] = (p & 0x00ff00) >> 8; + sir[2] = (p & 0x0000ff); + rbs = r1 - Math.abs(i); + rsum += sir[0] * rbs; + gsum += sir[1] * rbs; + bsum += sir[2] * rbs; + if (i > 0) { + rinsum += sir[0]; + ginsum += sir[1]; + binsum += sir[2]; + } else { + routsum += sir[0]; + goutsum += sir[1]; + boutsum += sir[2]; + } + } + stackpointer = radius; + + for (x = 0; x < w; x++) { + + r[yi] = dv[rsum]; + g[yi] = dv[gsum]; + b[yi] = dv[bsum]; + + rsum -= routsum; + gsum -= goutsum; + bsum -= boutsum; + + stackstart = stackpointer - radius + div; + sir = stack[stackstart % div]; + + routsum -= sir[0]; + goutsum -= sir[1]; + boutsum -= sir[2]; + + if (y == 0) { + vmin[x] = Math.min(x + radius + 1, wm); + } + p = pix[yw + vmin[x]]; + + sir[0] = (p & 0xff0000) >> 16; + sir[1] = (p & 0x00ff00) >> 8; + sir[2] = (p & 0x0000ff); + + rinsum += sir[0]; + ginsum += sir[1]; + binsum += sir[2]; + + rsum += rinsum; + gsum += ginsum; + bsum += binsum; + + stackpointer = (stackpointer + 1) % div; + sir = stack[(stackpointer) % div]; + + routsum += sir[0]; + goutsum += sir[1]; + boutsum += sir[2]; + + rinsum -= sir[0]; + ginsum -= sir[1]; + binsum -= sir[2]; + + yi++; + } + yw += w; + } + for (x = 0; x < w; x++) { + rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0; + yp = -radius * w; + for (i = -radius; i <= radius; i++) { + yi = Math.max(0, yp) + x; + + sir = stack[i + radius]; + + sir[0] = r[yi]; + sir[1] = g[yi]; + sir[2] = b[yi]; + + rbs = r1 - Math.abs(i); + + rsum += r[yi] * rbs; + gsum += g[yi] * rbs; + bsum += b[yi] * rbs; + + if (i > 0) { + rinsum += sir[0]; + ginsum += sir[1]; + binsum += sir[2]; + } else { + routsum += sir[0]; + goutsum += sir[1]; + boutsum += sir[2]; + } + + if (i < hm) { + yp += w; + } + } + yi = x; + stackpointer = radius; + for (y = 0; y < h; y++) { + // Preserve alpha channel: ( 0xff000000 & pix[yi] ) + pix[yi] = (0xff000000 & pix[yi]) | (dv[rsum] << 16) | (dv[gsum] << 8) | dv[bsum]; + + rsum -= routsum; + gsum -= goutsum; + bsum -= boutsum; + + stackstart = stackpointer - radius + div; + sir = stack[stackstart % div]; + + routsum -= sir[0]; + goutsum -= sir[1]; + boutsum -= sir[2]; + + if (x == 0) { + vmin[y] = Math.min(y + r1, hm) * w; + } + p = x + vmin[y]; + + sir[0] = r[p]; + sir[1] = g[p]; + sir[2] = b[p]; + + rinsum += sir[0]; + ginsum += sir[1]; + binsum += sir[2]; + + rsum += rinsum; + gsum += ginsum; + bsum += binsum; + + stackpointer = (stackpointer + 1) % div; + sir = stack[stackpointer]; + + routsum += sir[0]; + goutsum += sir[1]; + boutsum += sir[2]; + + rinsum -= sir[0]; + ginsum -= sir[1]; + binsum -= sir[2]; + + yi += w; + } + } + + bitmap.setPixels(pix, 0, w, 0, 0, w, h); + + return (bitmap); + } + + public static void blur(Bitmap bkg, View view) { + long startMs = System.currentTimeMillis(); + float radius = 15; + float scaleFactor = 8; + //放大到整个view的大小 + bkg = DrawableProvider.getReSizeBitmap(bkg, view.getMeasuredWidth(), view.getMeasuredHeight()); + + Bitmap overlay = Bitmap.createBitmap((int) (view.getMeasuredWidth() / scaleFactor) + , (int) (view.getMeasuredHeight() / scaleFactor), Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(overlay); + canvas.translate(-view.getLeft() / scaleFactor, -view.getTop() / scaleFactor); + canvas.scale(1 / scaleFactor, 1 / scaleFactor); + Paint paint = new Paint(); + paint.setFlags(Paint.FILTER_BITMAP_FLAG); + canvas.drawBitmap(bkg, 0, 0, paint); + overlay = FastBlur.doBlur(overlay, (int) radius, true); + view.setBackgroundDrawable(new BitmapDrawable(UiUtils.getResources(), overlay)); + Log.w("test", "cost " + (System.currentTimeMillis() - startMs) + "ms"); + } + + public static Bitmap blurBitmap(Bitmap bkg, int width, int height) { + long startMs = System.currentTimeMillis(); + float radius = 15;//越大模糊效果越大 + float scaleFactor = 8; + //放大到整个view的大小 + bkg = DrawableProvider.getReSizeBitmap(bkg, width, height); + Bitmap overlay = Bitmap.createBitmap((int) (width / scaleFactor) + , (int) (height / scaleFactor), Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(overlay); + canvas.scale(1 / scaleFactor, 1 / scaleFactor); + Paint paint = new Paint(); + paint.setFlags(Paint.FILTER_BITMAP_FLAG); + canvas.drawBitmap(bkg, 0, 0, paint); + overlay = FastBlur.doBlur(overlay, (int) radius, true); + Log.w("test", "cost " + (System.currentTimeMillis() - startMs) + "ms"); + return overlay; + } +} diff --git a/app/src/main/java/me/jessyan/mvparms/demo/di/module/ServiceModule.java b/app/src/main/java/me/jessyan/mvparms/demo/di/module/ServiceModule.java index 275d319..8bd8837 100644 --- a/app/src/main/java/me/jessyan/mvparms/demo/di/module/ServiceModule.java +++ b/app/src/main/java/me/jessyan/mvparms/demo/di/module/ServiceModule.java @@ -6,6 +6,7 @@ import javax.inject.Singleton; import dagger.Module; import dagger.Provides; import me.jessyan.mvparms.demo.mvp.model.api.service.CommonService; +import me.jessyan.mvparms.demo.mvp.model.api.service.UserService; import retrofit2.Retrofit; /** @@ -20,4 +21,10 @@ public class ServiceModule { return retrofit.create(CommonService.class); } + @Singleton + @Provides + UserService provideUserService(Retrofit retrofit) { + return retrofit.create(UserService.class); + } + } diff --git a/app/src/main/java/me/jessyan/mvparms/demo/mvp/model/UserModel.java b/app/src/main/java/me/jessyan/mvparms/demo/mvp/model/UserModel.java index 7d166f1..8c28bef 100644 --- a/app/src/main/java/me/jessyan/mvparms/demo/mvp/model/UserModel.java +++ b/app/src/main/java/me/jessyan/mvparms/demo/mvp/model/UserModel.java @@ -28,7 +28,7 @@ public class UserModel extends BaseModel implement @Override public Observable> getUsers(int lastIdQueried, boolean update) { - Observable> users = mServiceManager.getCommonService() + Observable> users = mServiceManager.getUserService() .getUsers(lastIdQueried, USERS_PER_PAGE); //使用rxcache缓存,上拉刷新则不读取缓存,加载更多读取缓存 return mCacheManager.getCommonCache() diff --git a/app/src/main/java/me/jessyan/mvparms/demo/mvp/model/api/Api.java b/app/src/main/java/me/jessyan/mvparms/demo/mvp/model/api/Api.java index 11c4a24..6f58f3f 100644 --- a/app/src/main/java/me/jessyan/mvparms/demo/mvp/model/api/Api.java +++ b/app/src/main/java/me/jessyan/mvparms/demo/mvp/model/api/Api.java @@ -5,5 +5,6 @@ package me.jessyan.mvparms.demo.mvp.model.api; * contact with jess.yan.effort@gmail.com */ public interface Api { - public static final String APP_DOMAIN = "https://api.github.com"; + String APP_DOMAIN = "https://api.github.com"; + String RequestSuccess = "0"; } diff --git a/app/src/main/java/me/jessyan/mvparms/demo/mvp/model/api/service/CommonService.java b/app/src/main/java/me/jessyan/mvparms/demo/mvp/model/api/service/CommonService.java index 8ba21e3..e50ec35 100644 --- a/app/src/main/java/me/jessyan/mvparms/demo/mvp/model/api/service/CommonService.java +++ b/app/src/main/java/me/jessyan/mvparms/demo/mvp/model/api/service/CommonService.java @@ -1,35 +1,10 @@ package me.jessyan.mvparms.demo.mvp.model.api.service; -import java.util.List; - -import me.jessyan.mvparms.demo.mvp.model.entity.User; -import retrofit2.http.GET; -import retrofit2.http.Headers; -import retrofit2.http.Query; -import rx.Observable; - /** + * 存放通用的一些API * Created by jess on 8/5/16 12:05 * contact with jess.yan.effort@gmail.com */ public interface CommonService { - String HEADER_API_VERSION = "Accept: application/vnd.github.v3+json"; - - @Headers({HEADER_API_VERSION}) - @GET("/users") - Observable> getUsers(@Query("since") int lastIdQueried, @Query("per_page") int perPage); - - -// @GET("/api/v2/feed?num=2&udid=26868b32e808498db32fd51fb422d00175e179df&vc=83") -// Observable getDailyList(); -// -// @GET("/api/v2/categories?udid=26868b32e808498db32fd51fb422d00175e179df&vc=83") -// Observable getFindMore(); -// -// @GET("/api/v3/ranklist?num=10&strategy=%s&udid=26868b32e808498db32fd51fb422d00175e179df&vc=83") -// Observable getHotStrategy(); -// -// @GET("/api/v3/videos?categoryName=%s&strategy=%s&udid=26868b32e808498db32fd51fb422d00175e179df&vc=83") -// Observable getFindDetail(); } diff --git a/app/src/main/java/me/jessyan/mvparms/demo/mvp/model/api/service/ServiceManager.java b/app/src/main/java/me/jessyan/mvparms/demo/mvp/model/api/service/ServiceManager.java index c494aab..efe73f2 100644 --- a/app/src/main/java/me/jessyan/mvparms/demo/mvp/model/api/service/ServiceManager.java +++ b/app/src/main/java/me/jessyan/mvparms/demo/mvp/model/api/service/ServiceManager.java @@ -12,20 +12,26 @@ import javax.inject.Singleton; @Singleton public class ServiceManager implements BaseServiceManager { private CommonService mCommonService; + private UserService mUserService; /** * 如果需要添加service只需在构造方法中添加对应的service,在提供get方法返回出去,只要在ServiceModule提供了该service * Dagger2会自行注入 * @param commonService */ - @Inject public ServiceManager(CommonService commonService){ + @Inject public ServiceManager(CommonService commonService,UserService userService){ this.mCommonService = commonService; + this.mUserService = userService; } public CommonService getCommonService() { return mCommonService; } + public UserService getUserService() { + return mUserService; + } + /** * 这里可以释放一些资源(注意这里是单例,即不需要在activity的生命周期调用) */ diff --git a/app/src/main/java/me/jessyan/mvparms/demo/mvp/model/api/service/UserService.java b/app/src/main/java/me/jessyan/mvparms/demo/mvp/model/api/service/UserService.java new file mode 100644 index 0000000..8539a7c --- /dev/null +++ b/app/src/main/java/me/jessyan/mvparms/demo/mvp/model/api/service/UserService.java @@ -0,0 +1,25 @@ +package me.jessyan.mvparms.demo.mvp.model.api.service; + +import java.util.List; + +import me.jessyan.mvparms.demo.mvp.model.entity.User; +import retrofit2.http.GET; +import retrofit2.http.Headers; +import retrofit2.http.Query; +import rx.Observable; + +/** + * 存放关于用户的一些api + * Created by jess on 8/5/16 12:05 + * contact with jess.yan.effort@gmail.com + */ +public interface UserService { + + String HEADER_API_VERSION = "Accept: application/vnd.github.v3+json"; + + @Headers({HEADER_API_VERSION}) + @GET("/users") + Observable> getUsers(@Query("since") int lastIdQueried, @Query("per_page") int perPage); + + +} diff --git a/app/src/main/java/me/jessyan/mvparms/demo/mvp/model/entity/BaseJson.java b/app/src/main/java/me/jessyan/mvparms/demo/mvp/model/entity/BaseJson.java new file mode 100644 index 0000000..a0f5912 --- /dev/null +++ b/app/src/main/java/me/jessyan/mvparms/demo/mvp/model/entity/BaseJson.java @@ -0,0 +1,42 @@ +package me.jessyan.mvparms.demo.mvp.model.entity; + +import java.io.Serializable; + +import me.jessyan.mvparms.demo.mvp.model.api.Api; + +/** + * 如果你服务器返回的数据固定为这种方式(字段名可根据服务器更改) + * 替换范型即可重用BaseJson + * Created by jess on 26/09/2016 15:19 + * Contact with jess.yan.effort@gmail.com + */ + +public class BaseJson implements Serializable{ + private T data; + private String code; + private String msg; + + public T getData() { + return data; + } + + public String getCode() { + return code; + } + + public String getMsg() { + return msg; + } + + /** + * 请求是否成功 + * @return + */ + public boolean isSuccess() { + if (code.equals(Api.RequestSuccess)) { + return true; + } else { + return false; + } + } +} diff --git a/app/src/main/java/me/jessyan/mvparms/demo/mvp/presenter/UserPresenter.java b/app/src/main/java/me/jessyan/mvparms/demo/mvp/presenter/UserPresenter.java index d9d23d6..a565f1c 100644 --- a/app/src/main/java/me/jessyan/mvparms/demo/mvp/presenter/UserPresenter.java +++ b/app/src/main/java/me/jessyan/mvparms/demo/mvp/presenter/UserPresenter.java @@ -3,11 +3,11 @@ package me.jessyan.mvparms.demo.mvp.presenter; import android.app.Application; import com.jess.arms.base.AppManager; -import com.jess.arms.base.BaseActivity; import com.jess.arms.base.DefaultAdapter; import com.jess.arms.di.scope.ActivityScope; import com.jess.arms.mvp.BasePresenter; import com.jess.arms.utils.PermissionUtil; +import com.jess.arms.utils.RxUtils; import com.tbruyelle.rxpermissions.RxPermissions; import java.util.ArrayList; @@ -86,7 +86,7 @@ public class UserPresenter extends BasePresenter>bindToLifecycle())//使用RXlifecycle,使subscription和activity一起销毁 + .compose(RxUtils.>bindToLifecycle(mRootView))//使用RXlifecycle,使subscription和activity一起销毁 .subscribe(new ErrorHandleSubscriber>(mErrorHandler) { @Override public void onNext(List users) { diff --git a/arms/src/main/java/com/jess/arms/base/BaseApplication.java b/arms/src/main/java/com/jess/arms/base/BaseApplication.java index 551ba67..2c562db 100644 --- a/arms/src/main/java/com/jess/arms/base/BaseApplication.java +++ b/arms/src/main/java/com/jess/arms/base/BaseApplication.java @@ -52,7 +52,6 @@ public abstract class BaseApplication extends Application { .build(); this.mAppModule = new AppModule(this, mAppManager);//提供application this.mImagerModule = new ImageModule();//图片加载框架默认使用glide - } /** diff --git a/arms/src/main/java/com/jess/arms/utils/RxUtils.java b/arms/src/main/java/com/jess/arms/utils/RxUtils.java new file mode 100644 index 0000000..75e5019 --- /dev/null +++ b/arms/src/main/java/com/jess/arms/utils/RxUtils.java @@ -0,0 +1,55 @@ +package com.jess.arms.utils; + +import com.jess.arms.base.BaseActivity; +import com.jess.arms.base.BaseFragment; +import com.jess.arms.mvp.BaseView; +import com.trello.rxlifecycle.LifecycleTransformer; + +import rx.Observable; +import rx.android.schedulers.AndroidSchedulers; +import rx.functions.Action0; +import rx.schedulers.Schedulers; + +/** + * Created by jess on 11/10/2016 16:39 + * Contact with jess.yan.effort@gmail.com + */ + +public class RxUtils { + + public static Observable.Transformer applySchedulers(final BaseView view) { + return new Observable.Transformer() { + @Override + public Observable call(Observable observable) { + return observable.subscribeOn(Schedulers.io()) + .doOnSubscribe(new Action0() { + @Override + public void call() {//显示进度条 + view.showLoading(); + } + }) + .subscribeOn(AndroidSchedulers.mainThread()) + .observeOn(AndroidSchedulers.mainThread()) + .doAfterTerminate(new Action0() { + @Override + public void call() { + view.hideLoading();//隐藏进度条 + } + }).compose(RxUtils.bindToLifecycle(view)); + } + }; + } + + + public static LifecycleTransformer bindToLifecycle(BaseView view) { + if (view instanceof BaseActivity) { + return ((BaseActivity) view).bindToLifecycle(); + } else if (view instanceof BaseFragment) { + return ((BaseFragment) view).bindToLifecycle(); + } else { + throw new IllegalArgumentException("view isn't activity or fragment"); + } + + } + +} -- GitLab