Android MVP框架 续

之前的文章有说过 Android MVP框架搭建 以及Dagger, ARouter的基本用法,

下面继续补充说说一些其他框架插件,如:

ButterKnife,Retrofit,EventBus, RxJava

1. ButterKnife

黄油刀,这框架名字听起来挺形象的,用来做什么的呢?它是一个用于Android系统View注入的框架,可以自动生成视图资源索引文件从而绑定视图,替换掉以前总是要写很多繁琐的findViewById来找到View对象。其简单的使用步骤:

1.1 AS开发工具安装插件 Android ButterKnife Zelezny (android studio 4.0后已绑定该插件)

将用户配置文件中的夹包拷到android studio plugin 下

C:\Users\Bruce\AppData\Roaming\Google\AndroidStudio4.1\plugins\Android-ButterKnife-Injections.jar

将以上位置的夹包拷到以下位置:D:\AndroidStudio\plugins, 然后重启android studio

任意找一个layout引用的地方,右键,generate->自动生成代码

1.2 引入依赖

  build.gradle

dependencies {
    api 'com.jakewharton:butterknife:8.5.1' 
    annotationProcessor 'com.jakewharton:butterknife-compiler:8.5.1'
}

1.3 引用插件

  build.gradle

apply plugin: 'com.jakewharton.butterknife'

1.4 Activity中绑定视图

 1.4.1 activity onCreate方法中:

// 绑定视图
ButterKnife.bind(this);

或

// 加载并绑定视图
View contentView = View.inflate(this, R.layout.activity_main, null);
ButterKnife.bind(this, contentView);

 1.4.2 绑定视图中的组件元素

 主模块:

  @BindView(R.id.tv_version)

   public TextView tv_version;

子模块:

  @BindView(R2.id.tv_title)

  public TextView tv_title;

注意:多模块构建时,app project中绑定用R, 其他library module中绑定用R2,即子模块用R2。

这是因为多模块构建时,由于命名可能会重复,导致编译时资源引用有冲突。主模块的R文件中定义的变量都是final修饰的,不会被覆盖,在资源查找时会直接引用。但子模块的R文件中声明的变量都不是final修饰的,即为可覆盖的,直接引用可能会导致资源错乱。为了避免该问题ButterKnife会自动将子模块的R文件中定义的变量拷贝到R2文件中然后加上final修饰,同主模块的R文件一同编译,这时就能保证资源id的唯一性。

 1.4.3 视图事件监听

主模块:

@OnClick({R.id.button_login})
public void onViewClicked(View view) {
    int i = view.getId();
    if (i == R.id.button_login) {
        //
    }
}

子模块(注意绑定注解参数用R2, 监听事件内部处理需用R):

@OnClick({R2.id.tv_cancel, R2.id.tv_confirm, R2.id.tv_button})
public void onViewClicked(View view) {
    int i = view.getId();
    if (i == R.id.tv_cancel) {
        if (onDialogCancelCallback != null) {
            onDialogCancelCallback.onCancel();
        }
        dismiss();
    } else if (i == R.id.tv_confirm || i == R.id.tv_button) {
        if (onDialogConfirmCallback != null) {
            onDialogConfirmCallback.onConfirm();
        }
        dismiss();
    }
}

2. Retrofit

Retrofit其实是基于 okhttp3 封装了一个易用的发起Http请求的框架

2.1 引入依赖

dependencies {
     api 'com.squareup.retrofit2:retrofit:2.4.0'
}

2.2 定义拦截器,调节网络请求延迟

public class RetrofitInterceptor implements Interceptor {

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();

        SystemClock.sleep(100); // 网络延迟时间

        return chain.proceed(request);
    }

}

2.3 构建请求客户端

public class RetrofitClient {

    private static Retrofit.Builder retrofit;

    public static RetrofitService getService(String baseUrl) {
        if (retrofit == null) {
            OkHttpClient client = new OkHttpClient.Builder()
                    .connectTimeout(ARetrofit.timeout, TimeUnit.SECONDS)
                    .readTimeout(ARetrofit.timeout, TimeUnit.SECONDS)
                    .writeTimeout(ARetrofit.timeout, TimeUnit.SECONDS)
                    .retryOnConnectionFailure(true)
                    .addNetworkInterceptor(new RetrofitInterceptor())
                    .build();
            retrofit = new Retrofit.Builder().client(client);
        }
        if (TextUtils.isEmpty(baseUrl)) {
            return retrofit.build().create(RetrofitService.class);
        }
        return retrofit.baseUrl(baseUrl).build().create(RetrofitService.class);
    }
}

2.4 定义请求响应回调处理

public abstract class BaseCallback<T> implements Callback<ResponseBody> {

    @Override
    public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
        RetrofitResult<T> result = new RetrofitResult<>();

        if (response.code() == 200) {
            try {
                this.onSuccess(response);
            } catch (Exception e) {
                result.status = RetrofitResult.Status.ERROR_CLIENT;
                if (BuildConfig.DEBUG) {
                    result.msg = RetrofitResult.Status.ERROR_CLIENT.getMsg();
                }
                this.onComplete(result);
            }
        } else {
            result.status = RetrofitResult.Status.ERROR_SERVER;
            result.msg = RetrofitResult.Status.ERROR_SERVER.getMsg();
            this.onComplete(result);
        }
    }

    @Override
    public void onFailure(Call<ResponseBody> call, Throwable t) {
        RetrofitResult<T> result = new RetrofitResult<>();

        if (ConnectUtil.isNetworkConnected()) {
            if (t instanceof SocketTimeoutException) {
                result.status = RetrofitResult.Status.ERROR_TIMEOUT;
                result.msg = RetrofitResult.Status.ERROR_TIMEOUT.getMsg();
            } else {
                result.status = RetrofitResult.Status.ERROR_REQUEST;
                result.msg = RetrofitResult.Status.ERROR_REQUEST.getMsg();
            }
        } else {
            result.status = RetrofitResult.Status.ERROR_NETWORK;
            result.msg = RetrofitResult.Status.ERROR_NETWORK.getMsg();
        }
        this.onComplete(result);
    }

    /**
     * 完成请求
     */
    public abstract void onComplete(RetrofitResult<T> result);

    /**
     * 请求成功
     */
    public abstract void onSuccess(Response<ResponseBody> response) throws Exception;
}
public abstract class RetrofitCallback<T> extends BaseCallback<T> {

    private Type type; // 泛型的类型

    public RetrofitCallback() {
        try {
            type = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        } catch (Exception e) {
            LogUtil.e(e.getMessage());
        }
    }

    private ParameterizedType type(final Class raw, final Type... args) {
        return new ParameterizedType() {
            public Type getRawType() {
                return raw;
            }

            public Type[] getActualTypeArguments() {
                return args;
            }

            public Type getOwnerType() {
                return null;
            }
        };
    }

    @Override
    public void onSuccess(Response<ResponseBody> response) throws Exception {
        String json = response.body().string();

        RetrofitResult result;
        if (type != null) {
            result = new Gson().fromJson(json, type(RetrofitResult.class, type));
        } else {
            result = new Gson().fromJson(json, RetrofitResult.class);
        }

        if (result.code == RetrofitResult.RetrofitCode.SUCCESS) { 
            result.status = RetrofitResult.Status.SUCCESS; 
        } else { 
            result.status = RetrofitResult.Status.ERROR_UNKNOWN; 
        } 

        onComplete(result);
    }

}

2.5 定义请求方法

public interface RetrofitService {

    @GET
    Call<ResponseBody> download(@Url String url);

    @GET
    Call<ResponseBody> get(@Url String url, @QueryMap Map<String, Object> map);

    @GET
    Call<ResponseBody> get(@Url String url, @Query("userId") int userId);

    @POST
    Call<ResponseBody> post(@Url String url, @Body RequestBody jsonBody);

    @Multipart
    @POST
    Call<ResponseBody> upload(@Url String url, @Part List<MultipartBody.Part> parts);

    @Multipart
    @POST
    Call<ResponseBody> uploadFile(@Url String url, 
                                  @Part List<MultipartBody.Part> parts,
                                  @PartMap Map<String, RequestBody> params);

}

2.6 封装扩展请求方法

  以post方法为例:

public class RetrofitRequest {
    public static Call post(RetrofitService service, String url, 
                            Object params, Callback callback) { 
           Map<String, Object> paramMap = new HashMap<>(); 
           if(params != null){ 
                paramMap.put("param", params); 
           } 
           Call call = service.post(url, RequestBody.create(MediaType.parse("application/json"),                                                            GsonUtil.objectToJson(paramMap))); 
           call.enqueue(callback); 
           return call; 
    }
} 

2.7 使用示例

RetrofitService userService = RetrofitClient.getService("http://192.168.2.6:8100/");

Map<String, Object> map = new HashMap<>();
map.put("username", "admin");
map.put("pwd", "admin123");

RetrofitRequest.post(userService, "api/login", map, new RetrofitCallback() {
    @Override
    public void onComplete(RetrofitResult result) {
        if (result.status == RetrofitResult.Status.SUCCESS) {
            EventManager.post(new LoginEvent());
        } else {
            ToastManager.toast(result.msg);
        }
    }
});

3. EventBus

EventBus是一个基于消息事件的异步处理框架。

3.1 引入依赖

 dependencies {
     api 'org.greenrobot:eventbus:3.1.1'

}

3.2 定义消息监听管理器

public class EventManager {

    /**
     * 注册
     */
    public static void register(Object view) {
        if (!isRegister(view)){
            EventBus.getDefault().register(view);
        }
    }

    /**
     * 反注册
     */
    public static void unregister(Object view) {
        if (isRegister(view)){
            EventBus.getDefault().unregister(view);
        }
    }

    /**
     * 发送事件
     */
    public static void post(Object data) {
        EventBus.getDefault().post(data);
    }

    /**
     * 是否已注册
     */
    private static boolean isRegister(Object view) {
        return EventBus.getDefault().isRegistered(view);
    }

}

3.3 注册监听

  Activity onCreate方法中:

 EventManager.register(this);

3.4 发送消息

  比如上面Retrofit请求示例中,登录成功回调方法中:

EventManager.post(new LoginEvent());

3.5 监听消息

  在需要监听接收消息的Activity中订阅消息:

@Subscribe
public void onEvent(LoginEvent event) {
   // 调用对应的presenter处理业务逻辑或执行页面路由跳转等
}

4. RxJava

RxJava是一个异步事件处理操作库,相比于AsyncTask,Handler等的异步操作处理更简洁。

RxJava无需层层嵌套,可以直接链式调用,示例(实现一个简单的倒计时):

private Subscription mSubscription;
private final int TIME = 60;    // 开始倒计时时间
private int currentTime = TIME; // 剩余时间
 /**
  * 开始倒计时
  */
 public void countdown() {
    getView().tv_code.setEnabled(false);
    mSubscription = Observable.interval(0, 1, TimeUnit.SECONDS)
        .observeOn(AndroidSchedulers.mainThread()).subscribe(aLong -> {
            if (isNotEmptyView()) {
                if (currentTime > 0) {
                    getView().tv_code.setText(currentTime + "s");
                    getView().tv_code.setTextColor(Color.parseColor("#cccccc"));
                } else {
                    cancelTask();
                    getView().tv_code.setEnabled(true);
                    getView().tv_code.setText("验证码");
                    getView().tv_code.setTextColor(Color.parseColor("#222222"));
                    currentTime = TIME;
                }
                currentTime--;
            }
        });
 }

 /**
  * 取消倒计时
  */
 private void cancelTask() {
    if (mSubscription != null) {
        if (!mSubscription.isUnsubscribed()) {
            mSubscription.unsubscribe();
        }
        mSubscription = null;
    }
 }

5. 写在最后

以上是Android MVP 中常用的一些框架技术,再加上之前说的Dagger, ARouter等,基本上能解决Android端开发的常规业务功能操作流程问题。后续会再抽空整理下安卓支付对接处理,微信授权分享等以及一些常用的具体组件的用法心得。关注我,持续更新中~

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值