| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 移动开发 -> Android MVP框架 续 -> 正文阅读 |
|
[移动开发]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. RetrofitRetrofit其实是基于 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. EventBusEventBus是一个基于消息事件的异步处理框架。 3.1 引入依赖 ?dependencies { } 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. RxJavaRxJava是一个异步事件处理操作库,相比于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端开发的常规业务功能操作流程问题。后续会再抽空整理下安卓支付对接处理,微信授权分享等以及一些常用的具体组件的用法心得。关注我,持续更新中~ |
|
移动开发 最新文章 |
Vue3装载axios和element-ui |
android adb cmd |
【xcode】Xcode常用快捷键与技巧 |
Android开发中的线程池使用 |
Java 和 Android 的 Base64 |
Android 测试文字编码格式 |
微信小程序支付 |
安卓权限记录 |
知乎之自动养号 |
【Android Jetpack】DataStore |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年3日历 | -2025/3/4 15:15:13- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |