[置顶] app框架总结
2018-01-30 17:13
295 查看
代码强迫症晚期患者,碰到新鲜的,觉得确实比自己写的好的,就会把自己的代码全改了,虽然碰到各种各样的坑,但是过程是很爽很爽的,极大的满足感。同时公开了很多公共依赖库,新开发的项目只需要添加一行依赖就ok了,可以快速开发应用
依赖库
一。代码框架mvvm+fragmentation:
1.mvvm的数据绑定各种天马行空的错误,开始的时候真的很头疼,但还是咬牙坚持下来了,mvvm可以通过一行代码控制recylerview填充,刷新
adapter可以这样写,
@BindingAdapter({"app:functionsf", "app:functionsItem"})
public static void scanAdapter(final RecyclerView recyclerView, final FunctionsFVH scanVH, final ArrayList<FunctionBean> arrayList) {
RecyclerView.Adapter adapter = recyclerView.getAdapter();
if (adapter != null) {
adapter.notifyDataSetChanged();
return;
}
if (scanVH != null && arrayList != null) {
recyclerView.setLayoutManager(new GridLayoutManager(recyclerView.getContext(), 3));
recyclerView.setAdapter(new BaseRecyclerAdapterF<FunctionBean>(arrayList) {
@Override
protected RecyclerView.ViewHolder createNewViewHolder(ViewGroup parent, int viewType) {
ViewDataBinding binding = getBinding(parent, R.layout.f_functions_item);
RecyclerView.ViewHolder viewHolder = new FunctionsFItemVH(binding, scanVH.mCtx);
binding.setVariable(cn.com.reformer.brake.BR.FunctionsFItemVH, viewHolder);
return viewHolder;
}
});
}
} xml文件
2.framentation是youkey大神的开源框架,通过这个框架完全可以实现单Activity+多Fragment模式,app整体性能很轻,各种跳转很优美,所有也进行了各种各样的踩坑,再完成门禁大师app的时候,实现了一个Activity+多个fragment的框架,其中很多坑比如
1>activity主题切换:启动主题要更换普通主题的
<!--启动模式-->
<style name="theme_launch" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowFullscreen">true</item>
<item name="android:windowBackground">@drawable/launch_bg</item>
<item name="android:navigationBarColor">@color/colorPrimaryTitle</item>
</style>
<!--主题模式-->
<style name="theme_wangfei" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowBackground">@color/colorPrimary</item>
<item name="android:navigationBarColor">@color/colorPrimaryTitle</item>
</style> 注意单个activity的
4000
实现主题的切换是很麻烦的,尤其加上fragmentation框架
package com.reformer.util.global;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.view.WindowManager;
import com.baidu.mobstat.StatService;
import com.reformer.util.R;
import me.yokeyword.fragmentation.SupportActivity;
import wangfei.util.global.SpUtil;
public abstract class BaseA extends SupportActivity {
public static BaseA mCtx;//上下文
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initTheme(savedInstanceState);
}
@Override
protected void onResume() {
super.onResume();
StatService.onResume(mCtx);
mCtx = this;
}
@Override
protected void onPause() {
super.onPause();
StatService.onPause(mCtx);
mCtx = null;
SpUtil.putString("welcomeTime", String.valueOf(System.currentTimeMillis()));
}
@Override
protected void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putInt("theme", mCurTheme);
}
public int mCurTheme = 0;
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void initTheme(Bundle savedInstanceState) {
if (savedInstanceState != null) {
initBarState();
int[] themeIds = {R.style.theme_launch, R.style.theme_wangfei, R.style.theme_full_screen};
getWindow().setBackgroundDrawable(null);
mCurTheme = themeIds[savedInstanceState.getInt("theme")];
setTheme(mCurTheme);
reCreateView();
} else {
firstCreate();
switchTheme(1);
}
}
protected abstract void firstCreate();
protected abstract void reCreateView();
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
protected void initBarState() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {//透明状态栏
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
}
/**
* @param themeID 0启动模式,1.主题模式 ,2.全屏模式
*/
public void switchTheme(final int themeID) {
mCurTheme = themeID;
recreate();
}
}
实现这个activity要重写两个方法,
}} 在第一个firstCreate()的时候调用app的初始化方法,第二个reCreateView()就可以加载界面了,因为直接加载首界面所以还需要判断用户身份,这个时候如果身份不合法需要跳转登陆界面,这个跳转太快了,需要延时500ms(个人建议),否则背景容易重影;fragment创建启动的时候,不能有太多的Obsevable变量刷新界面,否则界面的跳转可能会有抖动的现象
二。联网框架用的retrofit+rxjava,优点很明显代码逻辑清晰,可异步,快速
public class RetrofitUtils {
// public static final String baseUrl = "http://192111.168111.1111.1111:11111/firmware/";
private static Retrofit retrofit = null;
private static IRetrofitServer iServer;
private static Retrofit retrofit2 = null;
private static IRetrofitServer iServer2;
public static IRetrofitServer getInstance() {
if (retrofit == null) {
synchronized (RetrofitUtils.class) {
if (retrofit == null) {
// OkHttpClient mOkHttpClient=new OkHttpClient.Builder()
// .connectTimeout(HttpConfig.HTTP_TIME, TimeUnit.SECONDS)
// .readTimeout(HttpConfig.HTTP_TIME, TimeUnit.SECONDS)
// .writeTimeout(HttpConfig.HTTP_TIME, TimeUnit.SECONDS)
// .addInterceptor(InterceptorUtil.HeaderInterceptor())
// .addInterceptor(InterceptorUtil.LogInterceptor())//添加日志拦截器
// .build();
retrofit = new Retrofit.Builder()
.baseUrl("http://114.215.171.48:8995/firmware/")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())//添加rxjava转换器
.build();
iServer = retrofit.create(IRetrofitServer.class);
}
}
}
return iServer;
}
public static IRetrofitServer getInstance2(final ProgressListener progressListener) {
if (retrofit2 == null) {
synchronized (RetrofitUtils.class) {
if (retrofit2 == null) {
// OkHttpClient mOkHttpClient=new OkHttpClient.Builder()
// .connectTimeout(HttpConfig.HTTP_TIME, TimeUnit.SECONDS)
// .readTimeout(HttpConfig.HTTP_TIME, TimeUnit.SECONDS)
// .writeTimeout(HttpConfig.HTTP_TIME, TimeUnit.SECONDS)
// .addInterceptor(InterceptorUtil.HeaderInterceptor())
// .addInterceptor(InterceptorUtil.LogInterceptor())//添加日志拦截器
// .build();
OkHttpClient client = new OkHttpClient.Builder().addNetworkInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Response response = chain.proceed(chain.request());
return response.newBuilder().body(new ProgressResponseBody(response.body(), progressListener)).build();
}
}).build();
retrofit2 = new Retrofit.Builder()
.client(client)
.baseUrl("http://114.215.171.48:8995/firmware/")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())//添加rxjava转换器
.build();
iServer2 = retrofit2.create(IRetrofitServer.class);
}
}
}
return iServer2;
}
public interface IRetrofitServer {
//### 1. 获取token
@FormUrlEncoded
@POST("api/emply/Login")
Call<BaseResponse<Token>> getToken(@Field("param") String userPhone);
//### 2. 获取固件设备列表
@FormUrlEncoded
@POST("api/version/date")
Call<BaseResponse<ArrayList<Vertion>>> getDevices(@Field("token") String token, @Field("param") String code);
//### 3.下载固件
@GET
Call<ResponseBody> downFirmware(@Url String fileUrl);
// 如果你下载的文件很大,则使用
@Streaming
@GET
Call<ResponseBody> downloadFileWithDynamicUrlAsync(@Url String fileUrl);
}其实一个实例就行了,有两个是因为有一个是测试下载大文件的,所以分开了
三。整体架构是app module指向多个子module,过个子module共同只想工具类module
除了app module是apply plugin: 'com.android.application'
其他的都是apply plugin: 'com.android.library' module之间是单向继承关系,可以保证各个功能子module互不影响,同时公用一个util module可以同时公用所有公共资源类
依赖库
一。代码框架mvvm+fragmentation:
1.mvvm的数据绑定各种天马行空的错误,开始的时候真的很头疼,但还是咬牙坚持下来了,mvvm可以通过一行代码控制recylerview填充,刷新
adapter可以这样写,
@BindingAdapter({"app:functionsf", "app:functionsItem"})
public static void scanAdapter(final RecyclerView recyclerView, final FunctionsFVH scanVH, final ArrayList<FunctionBean> arrayList) {
RecyclerView.Adapter adapter = recyclerView.getAdapter();
if (adapter != null) {
adapter.notifyDataSetChanged();
return;
}
if (scanVH != null && arrayList != null) {
recyclerView.setLayoutManager(new GridLayoutManager(recyclerView.getContext(), 3));
recyclerView.setAdapter(new BaseRecyclerAdapterF<FunctionBean>(arrayList) {
@Override
protected RecyclerView.ViewHolder createNewViewHolder(ViewGroup parent, int viewType) {
ViewDataBinding binding = getBinding(parent, R.layout.f_functions_item);
RecyclerView.ViewHolder viewHolder = new FunctionsFItemVH(binding, scanVH.mCtx);
binding.setVariable(cn.com.reformer.brake.BR.FunctionsFItemVH, viewHolder);
return viewHolder;
}
});
}
} xml文件
<android.support.v7.widget.RecyclerView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/title_aasdfasf" android:layout_centerInParent="true" android:layout_gravity="center" android:divider="@null" android:dividerHeight="8dp" app:functionsItem="@{FunctionsFVH.itmesVHs}" app:functionsf="@{FunctionsFVH}" />viewhodler中的成员变量
public final ObservableArrayList<FunctionBean> itmesVHs = new ObservableArrayList<>();通过改变这个成员变量就可以实现adapter的填充,刷新,真tmd英明神武啊
2.framentation是youkey大神的开源框架,通过这个框架完全可以实现单Activity+多Fragment模式,app整体性能很轻,各种跳转很优美,所有也进行了各种各样的踩坑,再完成门禁大师app的时候,实现了一个Activity+多个fragment的框架,其中很多坑比如
1>activity主题切换:启动主题要更换普通主题的
<!--启动模式-->
<style name="theme_launch" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowFullscreen">true</item>
<item name="android:windowBackground">@drawable/launch_bg</item>
<item name="android:navigationBarColor">@color/colorPrimaryTitle</item>
</style>
<!--主题模式-->
<style name="theme_wangfei" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowBackground">@color/colorPrimary</item>
<item name="android:navigationBarColor">@color/colorPrimaryTitle</item>
</style> 注意单个activity的
4000
实现主题的切换是很麻烦的,尤其加上fragmentation框架
package com.reformer.util.global;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.view.WindowManager;
import com.baidu.mobstat.StatService;
import com.reformer.util.R;
import me.yokeyword.fragmentation.SupportActivity;
import wangfei.util.global.SpUtil;
public abstract class BaseA extends SupportActivity {
public static BaseA mCtx;//上下文
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initTheme(savedInstanceState);
}
@Override
protected void onResume() {
super.onResume();
StatService.onResume(mCtx);
mCtx = this;
}
@Override
protected void onPause() {
super.onPause();
StatService.onPause(mCtx);
mCtx = null;
SpUtil.putString("welcomeTime", String.valueOf(System.currentTimeMillis()));
}
@Override
protected void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putInt("theme", mCurTheme);
}
public int mCurTheme = 0;
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void initTheme(Bundle savedInstanceState) {
if (savedInstanceState != null) {
initBarState();
int[] themeIds = {R.style.theme_launch, R.style.theme_wangfei, R.style.theme_full_screen};
getWindow().setBackgroundDrawable(null);
mCurTheme = themeIds[savedInstanceState.getInt("theme")];
setTheme(mCurTheme);
reCreateView();
} else {
firstCreate();
switchTheme(1);
}
}
protected abstract void firstCreate();
protected abstract void reCreateView();
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
protected void initBarState() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {//透明状态栏
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
}
/**
* @param themeID 0启动模式,1.主题模式 ,2.全屏模式
*/
public void switchTheme(final int themeID) {
mCurTheme = themeID;
recreate();
}
}
实现这个activity要重写两个方法,
public class AllA extends BaseA { private AllVH allvh; @Override protected void firstCreate() { } @Override protected void reCreateView() {
AAllBinding viewDataBinding = DataBindingUtil.setContentView(this, R.layout.a_all); allvh = new AllVH(this); viewDataBinding.setAllvh(allvh); FunctionsF fragment = findFragment(FunctionsF.class); if (fragment == null) loadRootFragment(viewDataBinding.flContainer.getId(), FunctionsF.newInstance());
}} 在第一个firstCreate()的时候调用app的初始化方法,第二个reCreateView()就可以加载界面了,因为直接加载首界面所以还需要判断用户身份,这个时候如果身份不合法需要跳转登陆界面,这个跳转太快了,需要延时500ms(个人建议),否则背景容易重影;fragment创建启动的时候,不能有太多的Obsevable变量刷新界面,否则界面的跳转可能会有抖动的现象
二。联网框架用的retrofit+rxjava,优点很明显代码逻辑清晰,可异步,快速
public class RetrofitUtils {
// public static final String baseUrl = "http://192111.168111.1111.1111:11111/firmware/";
private static Retrofit retrofit = null;
private static IRetrofitServer iServer;
private static Retrofit retrofit2 = null;
private static IRetrofitServer iServer2;
public static IRetrofitServer getInstance() {
if (retrofit == null) {
synchronized (RetrofitUtils.class) {
if (retrofit == null) {
// OkHttpClient mOkHttpClient=new OkHttpClient.Builder()
// .connectTimeout(HttpConfig.HTTP_TIME, TimeUnit.SECONDS)
// .readTimeout(HttpConfig.HTTP_TIME, TimeUnit.SECONDS)
// .writeTimeout(HttpConfig.HTTP_TIME, TimeUnit.SECONDS)
// .addInterceptor(InterceptorUtil.HeaderInterceptor())
// .addInterceptor(InterceptorUtil.LogInterceptor())//添加日志拦截器
// .build();
retrofit = new Retrofit.Builder()
.baseUrl("http://114.215.171.48:8995/firmware/")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())//添加rxjava转换器
.build();
iServer = retrofit.create(IRetrofitServer.class);
}
}
}
return iServer;
}
public static IRetrofitServer getInstance2(final ProgressListener progressListener) {
if (retrofit2 == null) {
synchronized (RetrofitUtils.class) {
if (retrofit2 == null) {
// OkHttpClient mOkHttpClient=new OkHttpClient.Builder()
// .connectTimeout(HttpConfig.HTTP_TIME, TimeUnit.SECONDS)
// .readTimeout(HttpConfig.HTTP_TIME, TimeUnit.SECONDS)
// .writeTimeout(HttpConfig.HTTP_TIME, TimeUnit.SECONDS)
// .addInterceptor(InterceptorUtil.HeaderInterceptor())
// .addInterceptor(InterceptorUtil.LogInterceptor())//添加日志拦截器
// .build();
OkHttpClient client = new OkHttpClient.Builder().addNetworkInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Response response = chain.proceed(chain.request());
return response.newBuilder().body(new ProgressResponseBody(response.body(), progressListener)).build();
}
}).build();
retrofit2 = new Retrofit.Builder()
.client(client)
.baseUrl("http://114.215.171.48:8995/firmware/")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())//添加rxjava转换器
.build();
iServer2 = retrofit2.create(IRetrofitServer.class);
}
}
}
return iServer2;
}
public interface IRetrofitServer {
//### 1. 获取token
@FormUrlEncoded
@POST("api/emply/Login")
Call<BaseResponse<Token>> getToken(@Field("param") String userPhone);
//### 2. 获取固件设备列表
@FormUrlEncoded
@POST("api/version/date")
Call<BaseResponse<ArrayList<Vertion>>> getDevices(@Field("token") String token, @Field("param") String code);
//### 3.下载固件
@GET
Call<ResponseBody> downFirmware(@Url String fileUrl);
// 如果你下载的文件很大,则使用
@Streaming
@GET
Call<ResponseBody> downloadFileWithDynamicUrlAsync(@Url String fileUrl);
}其实一个实例就行了,有两个是因为有一个是测试下载大文件的,所以分开了
三。整体架构是app module指向多个子module,过个子module共同只想工具类module
除了app module是apply plugin: 'com.android.application'
其他的都是apply plugin: 'com.android.library' module之间是单向继承关系,可以保证各个功能子module互不影响,同时公用一个util module可以同时公用所有公共资源类
相关文章推荐
- [置顶] 【微信平台】艺萌管家APP技术总结(三)——上传和显示图片
- [置顶] Android Multimedia框架总结(八)Stagefright框架之AwesomePlayer及数据解析器
- [置顶] 关于iOS10 - iMessage App的总结
- [置顶] 微信授权登陆接入第三方App(步骤总结)Android。
- [置顶] MUI打开App提示音,安卓手机。mui框架。提示音
- MUI框架原生wepApp启动遇到过的坑与总结
- [置顶] Android Multimedia框架总结(二十)MediaCodec状态周期及Codec与输入/输出Buffer过程(附实例)
- [置顶] Android Multimedia框架总结(三)MediaPlayer中创建到setDataSource过程
- [置顶] Android Multimedia框架总结(二十四)MediaMuxer实现手机屏幕录制成gif图
- [置顶] Android Multimedia框架总结(二)MediaPlayer框架及播放网络视频案例
- [置顶] Android Multimedia框架总结(十)Stagefright框架之音视频输出过程
- [置顶] Android Multimedia框架总结(十九)Camera2框架C/S模型之CameraService启动及与Client连接过程
- [置顶] 【微信平台】艺萌管家APP技术总结(二)——云片网发送短信验证码
- [置顶] Android Multimedia框架总结(一)MediaPlayer介绍之状态图及生命周期
- [置顶] Android Multimedia框架总结(十八)Camera2框架从Java层到C++层类关系
- [置顶] 【微信平台】艺萌管家APP技术总结(一)——动态分页加载图片
- [置顶] VLC框架总结(一)VLC源码及各modules功能介绍
- [置顶] Android图片加载与缓存开源框架总结七部曲:Glide Picasso ImageLoader Fresco ASimpleCache等
- APICloud框架——总结一下最近开发APP遇到的一些问题 (三)
- [置顶] Android Multimedia框架总结(五)多媒体基础概念