代码强迫症晚期患者,碰到新鲜的,觉得确实比自己写的好的,就会把自己的代码全改了,虽然碰到各种各样的坑,但是过程是很爽很爽的,极大的满足感。同时公开了很多公共依赖库,新开发的项目只需要添加一行依赖就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文件
<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的实现主题的切换是很麻烦的,尤其加上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://sd:dad/aasdfas/") .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可以同时公用所有公共资源类