androidMVVMMVVMSmart-kotlinJetpackViewModel+Lifecycles+Navigation+DataBinding+LiveData+Okhttp+Retrofit+RxJava+GlideBindingAdapterMVVMfindViewById()setText()setOnClickListener()...
clone,,kotlin,Android,
View
MVVMModelViewModelViewModelViewViewView
google AAC(Android Architecture Components:): ViewModel:UI, Lifecycles:UI Navigation:googleActivity,Activity,Fragment. DataBinding:ViewModelUI [LiveData]:(https://developer.android.google.cn/jetpack)ViewModelUI retrofit+okhttp rxJava gsonjson glide BaseRecyclerViewAdapterHelperRecyclerView rxpermissionsAndroid 6.0 material-dialogsmaterial design
googledatabindingurlImageViewBindingAdapterGlideViewOnClickBindingAdapterRxViewViewModelxmlViewModel(@kelin)UIUI,,UI,UIviewmodel,viewmodel.
MVVMBaseActivityMVVMBaseFragmentMVVMBaseViewModelMVVMViewViewDataBindingViewModelBaseActivityMVVMBaseFragmentMVVM.navigationFragment,OnCreateView,BaseFragmentMVVM,include, Base initToolbar(),,Fragmentnavigation,manifest,.
MVVMMVVM
appbuild.gradleandroid {}
dataBinding {
enabled true
}
build.gradle
allprojects {
repositories {
...
google()
jcenter()
maven { url 'https://jitpack.io' }
}
}
appbuild.gradle
appbuild.gradlemvvmsmart
dependencies {
...
api project(':mvvmsmart')// ,
}
config.gradlebuild.gradle
apply from: "config.gradle"
**** config.gradle
android = [] compileSdkVersionbuildToolsVersionversionCode
dependencies = [] ,androidx.
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Application
ApplicationmvvmsmartBaseApplicationMVVM
BaseApplication.setApplication(this);
Application
AppApplication
//
KLog.init(true);
//
CaocConfig.Builder.create()
.backgroundMode(CaocConfig.BACKGROUND_MODE_SILENT) //,
.enabled(true) //
.showErrorDetails(true) //
.showRestartButton(true) //
.trackActivities(true) //Activity
.minTimeBetweenCrashesMs(2000) //()
.errorDrawable(R.mipmap.ic_launcher) //
.restartActivity(LoginActivity.class) //activity
//.errorActivity(YourCustomErrorActivity.class) //activity
//.eventListener(new YourCustomEventListener()) //
.apply();
Fragment,google IO ActivitynavigationFargmentsampleActivityFragment,Fargment.Activity,ActivityBase. Recyclerview
fragment_multi_rv.xmlLinearLayoutManagerMyMultiAdapter
<layout>
<data>
<variable
name="layoutManager"
type="androidx.recyclerview.widget.LinearLayoutManager" />
<variable
name="adapter"
type="com.wzq.sample.ui.recycler_multi.MyMultiAdapter" />
</data>
.....
</layout>
variable - type
variable - name
MultiRecycleViewFragmentBaseFragmentMVVM
class MultiRecycleViewFragment : BaseFragment<FragmentMultiRvBinding, MultiRecycleViewModel>() {
private lateinit var mAdapter: MyMultiAdapter
override fun initContentView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): Int {
return R.layout.fragment_multi_rv
}
override fun initVariableId(): Int {
return BR.viewModel
}
override fun initData() {
super.initData()
viewModel.data
initRecyclerView()
}
override fun initViewObservable() {
super.initViewObservable()
viewModel.itemsEntityLiveData.observe(this, Observer { itemsEntities: ArrayList<ItemsEntity>? -> mAdapter.setNewData(itemsEntities) })
}
....
fragment_multi_rv.xmldatabindingFragmentMultiRvBindingBuild->Clean Project
BaseFragmentMVVM(Sample,Base,base,BaseMVVM), baseViewDataBindingBaseViewModelMVVMActivityLoginBindingViewDataBindingMultiRecycleViewModelBaseFragmentMVVM
BaseFragmentMVVM
initContentView() layoutid
initVariableId() viewModelididR.id.xxxBRRBR.xxxViewModelid
initViewModel()LoginViewModel.
@Override
public LoginViewModel initViewModel() {
//ViewViewModel
return ViewModelProviders.of(this).get(LoginViewModel.class);
}
**** initViewModel()MultiRecycleViewFragmentMultiRecycleViewModelBaseViewModelMVVM
MultiRecycleViewModelBaseViewModelMVVM
class MultiRecycleViewModel(application: Application) : BaseViewModel(application) {
//RecyclerViewObservableList
var itemsEntityLiveData: MutableLiveData<ArrayList<ItemsEntity>> = MutableLiveData()
fun getData() {
val datas = ArrayList<ItemsEntity>()
for (i in 0..49) {
val itemBean = ItemsEntity(i, "MVVMSmart", TestUtils.getGirlImgUrl())
if (i % 2 == 0) {
itemBean.itemType = 0
} else {
itemBean.itemType = 1
}
datas.add(itemBean)
}
itemsEntityLiveData.value = datas
}
}
.....
BaseViewModelMVVMBaseFragmentMVVMStateLiveDataUIViewModelshowDialog()startActivity()MultiRecycleViewModel
BaseActivityMVVMBaseFragmentMVVM(BaseFragmentMVVMnavigation)Sample
databindingLiveData,
ViewModel
public String imgUrl = "http://img0.imgtn.bdimg.com/it/u=2183314203,562241301&fm=26&gp=0.jpg";
ImageView
binding:url="@{viewModel.imgUrl}"
urlImageView
binding:placeholderRes="@{R.mipmap.ic_launcher_round}"
Rdata
<import type=com.wzq.mvvmsmart.R" />
BindingAdapter
@BindingAdapter(value = {"url", "placeholderRes"}, requireAll = false)
public static void setImageUri(ImageView imageView, String url, int placeholderRes) {
if (!TextUtils.isEmpty(url)) {
//Glide
Glide.with(imageView.getContext())
.load(url)
.placeholder(placeholderRes)
.into(imageView);
}
}
ImageView
binding
RecyclerViewAdaptermvvmsmartsetAdapter() mvvmsmartrecyclerview,BaseRecyclerViewAdapterHelper,,DatabindingItemViewModel,,,,,. BaseRecyclerViewAdapterHelperRecyclerView
ViewModel
xml
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:adapter="@{adapter}"
app:layoutManager="@{layoutManager}"/>
layoutManager()lineManager
binding:layoutManager="@{LayoutManagers.grid(3)}
binding:layoutManager="@{LayoutManagers.linear(LinearLayoutManager.HORIZONTAL,Boolean.FALSE)}"
Java
<variable name="layoutManager" type="androidx.recyclerview.widget.LinearLayoutManager" />
<variable name="adapter" type="com.wzq.sample.ui.recycler_multi.MyMultiAdapter" />
,recyclerView;
RecyclerViewListViewViewPager https://awesomeopensource.com/project/evant/binding-collection-adapter
squareMVVMSmart
api "com.squareup.okhttp3:okhttp:3.10.0"
api "com.squareup.retrofit2:retrofit:2.4.0"
api "com.squareup.retrofit2:converter-gson:2.4.0"
api "com.squareup.retrofit2:adapter-rxjava2:2.4.0"
Retrofit
retrofit = Retrofit.Builder()
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // Observable:
.baseUrl(url)
.build()
RetrofitClient
LoggingInterceptor RequestResponse
LoggingInterceptor mLoggingInterceptor = new LoggingInterceptor
.Builder()//
.loggable(true) //
.setLevel(Level.BODY) //
.log(Platform.INFO) //
.request("Request") // requestTag
.response("Response")// ResponseTag
.addHeader("version", BuildConfig.VERSION_NAME)//
.build()
okhttp
okHttpClient = OkHttpClient.Builder()
.cookieJar(CookieJarImpl(PersistentCookieStore(mContext))) // .cache(cache)
.addInterceptor(BaseInterceptor(headers)) // header
.addInterceptor(mContext?.let { CacheInterceptor(it) }) //
.sslSocketFactory(sslParams!!.sSLSocketFactory, sslParams.trustManager) // https
.addInterceptor(LoggingInterceptor.Builder() //
.loggable(BuildConfig.DEBUG) //
.setLevel(Level.BASIC) //
.log(Platform.INFO) //
.request("Request") // requestTag
.response("Response") // ResponseTag
.addHeader("log-header", "I am the log request header.") // , key value
.build()
)
.connectTimeout(DEFAULT_TIMEOUT.toLong(), TimeUnit.SECONDS)
.writeTimeout(DEFAULT_TIMEOUT.toLong(), TimeUnit.SECONDS) // 815s
.connectionPool(ConnectionPool(8, 15, TimeUnit.SECONDS))
.build()
CacheInterceptor 3
//
int CACHE_TIMEOUT = 10 * 1024 * 1024
//
File httpCacheDirectory = new File(mContext.getCacheDir(), "wzq_cache");
//
Cache cache = new Cache(httpCacheDirectory, CACHE_TIMEOUT);
okhttp
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.cache(cache)
.addInterceptor(new CacheInterceptor(mContext))
.build();
MVVMSmartCookieStorePersistentCookieStore (SharedPreferences)MemoryCookieStore ()okhttpcookieJar
okHttpClient = OkHttpClient.Builder()
.cookieJar(CookieJarImpl(PersistentCookieStore(mContext))) // .cache(cache)
.addInterceptor(BaseInterceptor(headers)) // header
.build();
ViewModelBaseActivityMVVMBaseFragmentMVVMLifecycleView
RetrofitClient.getInstance().create(DemoApiService.class)
.demoGet()
.compose(RxUtils.bindToLifecycle(getLifecycleProvider())) // View
.compose(RxUtils.schedulersTransformer()) //
.compose(RxUtils.exceptionTransformer()) //
.subscribe(new Consumer<BaseResponse<DemoEntity>>() {
@Override
public void accept(BaseResponse<DemoEntity> response) throws Exception {
}
}, new Consumer<ResponseThrowable>() {
@Override
public void accept(ResponseThrowable throwable) throws Exception {
}
});
.compose(RxUtils.bindToLifecycle(getLifecycleProvider()))
**** BaseActivityMVVM/BaseFragmentMVVMLifecycleProviderViewModelgetLifecycleProvider() mvvmabit BaseActivityMVVMBaseFragmentMVVMBaseActivityRxAppCompatActivityFragmentRxFragmentRxUtils.bindToLifecycle(lifecycle)
(code 500())
Retrofit.compose(RxUtils.exceptionTransformer())
onError(ResponseThrowable)codemessage
mvvmsmartExceptionHandle
**** codecodecode = 404500HttpExceptioncodeRxJavafilter()BaseSubscriber
MVVMSmart
androidIntent
LiveEventBusViewModelViewModelLiveEventBusrViewModelViewModel
,
appmvvmsmartRetrofit+Okhttp+RxJava+RxBus
String loadUrl = "";
String destFileDir = context.getCacheDir().getPath(); //
String destFileName = System.currentTimeMillis() + ".apk";//
DownLoadManager.instance?.load(url, object : ProgressCallBack<ResponseBody?>([email protected], destFileDir, destFileName) {
override fun onStart() {
super.onStart()
KLog.e("--onStart")
}
override fun onSuccess(responseBody: Any?) {
KLog.e("--onSuccess")
ToastUtils.showShort("")
}
override fun progress(progress: Long, total: Long) {
KLog.e("--progress")
progressDialog.max = total.toInt()
progressDialog.progress = progress.toInt()
}
override fun onError(e: Throwable?) {
e?.printStackTrace()
ToastUtils.showShort("")
progressDialog.dismiss()
}
override fun onCompleted() {
progressDialog.dismiss()
KLog.e("--onCompleted")
}
})
ProgressResponseBodyRxBusProgressCallBackProgressCallBackUI
Fragment()ActivityFragmentActivityAndroidManifest
ViewModelBaseViewModelMVVMFragment
startContainerActivity(Fragment.class.getCanonicalName())
ViewModelBaseViewModelMVVMFragment
Bundle mBundle = new Bundle();
mBundle.putParcelable("entity", entity);
startContainerActivity(Fragment.class.getCanonicalName(), mBundle);
Fragment
Bundle mBundle = getArguments();
if (mBundle != null) {
entity = mBundle.getParcelable("entity");
}
RxPermissions
ViewModel
//
RxPermissions rxPermissions = new RxPermissions((Activity) context);
rxPermissions.request(Manifest.permission.CAMERA)
.subscribe(new Consumer<Boolean>() {
@Override
public void accept(Boolean aBoolean) throws Exception {
if (aBoolean) {
ToastUtils.showShort("");
} else {
ToastUtils.showShort("");
}
}
});
RxJava
String filePath = "mnt/sdcard/1.png";
ImageUtils.compressWithRx(filePath, new Consumer<File>() {
@Override
public void accept(File file) throws Exception {
//RequestBody
...
}
});
RxJavaonNext
List<String> filePaths = new ArrayList<>();
filePaths.add("mnt/sdcard/1.png");
filePaths.add("mnt/sdcard/2.png");
ImageUtils.compressWithRx(filePaths, new Subscriber() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(File file) {
}
});
ToastUtils
MaterialDialogUtils Material
SPUtils SharedPreferences
SDCardUtils SD
ConvertUtils
StringUtils
RegexUtils
KLog json
databindingASdatabinding
TextView android:text=""
StringBooleanASMessages.
(BR) xml
**** +13334AS (bug)
xmlViewModelxmlres/layoutxmlXXXUtilsXXXUtilsres/layoutxml
Cannot resolve type for xxx (xxx) (Ctrl+H) xmlxml
module4.1.1
databindingbuild
xmldatabindingBindingactivity_login.xmldatabinding<layout> <variable>
ActivityLoginBinding.javavariableasdatabdingBR.xxx
MVVMSmartMVVMSmartlibraryappMVVMSmartappproguard-rules.pro
wzqjava app,,,,Android(Android,),MVVMSmart,6,MVVMSmart star
QQ531944409
Copyright 2019 ()
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.