BaseDemo

introduce

BaseDemo is a standard architecture of Android application development based on Android MVVM + Retrofit + OkHttp + Coroutine + componentized architecture. Through continuous upgrading and iteration, BaseDemo is now mainly divided into two versions. Branch MVVM+Databinding componentized version, branch MVVM+Databinding+Single Single version. It aims to help you quickly build your own APP project architecture, so that you can quickly respond to the use of a large number of tools, in addition to long-term practical experience, mainly put in the project lib_common component, for your reference. The specific use of the developer tools depends on their own project needs to choose how to use.

Making: github.com/zhouhuandev…

Gitee: gitee.com/shandong_zh…

If my efforts can be exchanged for your help, please click start, which will be the motivation for my unremitting renewal. Thank you very much. If you have any problems in use, please leave a message

Function demonstration

Software Architecture Description

  • Pull refresh on the home page, pull down load, Room operation

  • Center to add photos, videos

The main function

The core base library lib_base

MVVM has ten core common base classes and six basic page interfaces

Basic page interface
  • View layer core interface BaseView
interface BaseView : ILoadView.INoDataView.ITransView.INetErrView {
    fun initListener(a)
    fun initData(a)
    fun finishActivity(a)
}
Copy the code
  • Load the initialization popover interface ILoadView
interface ILoadView {
    // Display the initial loaded View, the initial load data needs to display the View
    fun showInitLoadView(a)

    // Hide the initially loaded View
    fun hideInitLoadView(a)
}
Copy the code
  • Shows whether there is a data page interface INoDataView
interface INoDataView {
    // Display no data View
    fun showNoDataView(a)

    // Hide no data View
    fun hideNoDataView(a)

    // Displays a View with no data for the specified resource
    fun showNoDataView(@DrawableRes resid: Int)
}
Copy the code
  • Display ITransView interface for chrysanthemum View
interface ITransView {
    // Display the small chrysanthemum View with transparent background, such as delete operation
    fun showTransLoadingView(a)

    // Hide the background transparent chrysanthemum View
    fun hideTransLoadingView(a)
}
Copy the code
  • View Indicates the INetErrView interface
interface INetErrView {
    // Display network error View
    fun showNetWorkErrView(a)

    // Hide the network error View
    fun hideNetWorkErrView(a)
}
Copy the code
  • Basic refresh interface BaseRefreshView
interface BaseRefreshView {

    /** * Whether to enable pull-down refresh *@param b
     */
    fun enableRefresh(b: Boolean)

    /** * Whether to enable pull-up loading more */
    fun enableLoadMore(b: Boolean)

    /** * Refresh callback * sends refresh request to ViewModel */
    fun onRefreshEvent(a)

    /** * load more callbacks * send more load requests to the ViewModel */
    fun onLoadMoreEvent(a)

    /** * auto-loaded events * send auto-loaded requests to the ViewModel */
    fun onAutoLoadEvent(a)

    /** * stop refresh */
    fun stopRefresh(a)

    /** * stop loading more */
    fun stopLoadMore(a)

    /** * Automatically load data */
    fun autoLoadData(a)
}
Copy the code
BaseActivity
abstract class BaseActivity : RxAppCompatActivity(), BaseView {
    abstract fun onBindLayout(a): Int
    abstract fun initView(a)
    abstract override fun initData(a)
    override fun initListener(a)
}
Copy the code
BaseMvvmActivity
abstract class BaseMvvmActivity<VM : BaseViewModel> : BaseActivity() {
    /** * bind ViewModel */
    abstract fun onBindViewModel(a): Class<VM>

    /** * places the observer object */
    abstract fun initViewObservable(a)
}
Copy the code
BaseMvvmDataBindingActivity
abstract class BaseMvvmDataBindingActivity<V : ViewDataBinding, VM : BaseViewModel> : BaseMvvmActivity<VM>() {
    abstract fun onBindVariableId(a): Int
}
Copy the code
BaseMvvmRefreshActivity
abstract class BaseMvvmRefreshActivity<T, VM : BaseRefreshViewModel<T> > :BaseMvvmActivity<VM>(), BaseRefreshView {
    protected abstract fun onBindRreshLayout(a): Int
    protected abstract fun enableRefresh(a): Boolean
    protected abstract fun enableLoadMore(a): Boolean
}
Copy the code
BaseMvvmRefreshDataBindingActivity
abstract class BaseMvvmRefreshDataBindingActivity<T, V : ViewDataBinding, VM : BaseRefreshViewModel<T> > :BaseMvvmDataBindingActivity<V, VM>(), BaseRefreshView {
    protected abstract fun onBindRreshLayout(a): Int
    protected abstract fun enableRefresh(a): Boolean
    protected abstract fun enableLoadMore(a): Boolean
}
Copy the code
BaseFragment
    abstract fun onBindLayout(a): Int
    abstract fun initView(mView: View)
    abstract override fun initData(a)
Copy the code
BaseMvvmFragment
abstract class BaseMvvmFragment<VM : BaseViewModel> : BaseFragment() {
    abstract fun onBindViewModel(a): Class<VM>
    abstract fun initViewObservable(a)
}
Copy the code
BaseMvvmDataBindingFragment
abstract class BaseMvvmDataBindingFragment<V : ViewDataBinding, VM : BaseViewModel> :
    BaseMvvmFragment<VM>() {
    abstract fun onBindVariableId(a): Int
}
Copy the code
BaseMvvmRefreshFragment
abstract class BaseMvvmRefreshFragment<T, VM : BaseRefreshViewModel<T>> : BaseMvvmFragment<VM>(),
    BaseRefreshView {
    protected abstract fun onBindRreshLayout(): Int
    protected abstract fun enableRefresh(): Boolean
    protected abstract fun enableLoadMore(): Boolean
}
Copy the code
BaseMvvmRefreshDataBindingFragment
abstract class BaseMvvmRefreshDataBindingFragment<T, V : ViewDataBinding, VM : BaseRefreshViewModel<T> > :BaseMvvmDataBindingFragment<V, VM>(),
    BaseRefreshView {
    protected abstract fun onBindRreshLayout(a): Int
    protected abstract fun enableRefresh(a): Boolean
    protected abstract fun enableLoadMore(a): Boolean
}
Copy the code
  • BaseAdapter
  • BaseDataBindAdapter
  • BaseViewHolder
  • IBaseViewModel
  • BaseViewModel
  • BaseRefreshViewModel

.

features

  • Supported Or notToolBar
    open fun enableToolbar(a): Boolean {
        return true
    }
Copy the code
  • Support customizationToolBar
    open fun onBindToolbarLayout(): Int {
        return R.layout.common_toolbar
    }
Copy the code
  • You can customize title, text, and icon information
    open fun getTootBarTitle(a): String {
        return ""
    }

    /** * Set the pattern of the return button, which can be Drawable or ResId * note: only valid if enableToolBarLeft returns true **@return* /
    open fun getToolBarLeftIcon(a): Int {
        return R.drawable.ic_white_black_45dp
    }

    /** * whether to open returns **@return* /
    open fun enableToolBarLeft(a): Boolean {
        return false
    }

    /** * sets the text ** to the right of the title@return* /
    open fun getToolBarRightTxt(a): String {
        return ""
    }

    /** * set the display Icon ** to the right of the title@returnInt resId type */
    open fun getToolBarRightImg(a): Int {
        return 0
    }

    /** * listen for a callback@return* /
    open fun getToolBarRightTxtClick(a): View.OnClickListener? {
        return null
    }

    /** * listen for callback *@return* /
    open fun getToolBarRightImgClick(a): View.OnClickListener? {
        return null
    }
Copy the code
  • supportloadingLoad the data
    override fun showInitLoadView(a) {
        showInitLoadView(true)}override fun hideInitLoadView(a) {
        showInitLoadView(false)}Copy the code
  • Support transparentloadingLoad data of
    override fun showTransLoadingView(a) {
        showTransLoadingView(true)}override fun hideTransLoadingView(a) {
        showTransLoadingView(false)}Copy the code
  • Whether to enable full-screen display
    open fun enableAllowFullScreen(a): Boolean {
        return false
    }
Copy the code
  • No data is displayed
    override fun showNoDataView(a) {
        showNoDataView(true)}override fun showNoDataView(resid: Int) {
        showNoDataView(true, resid)
    }

    override fun hideNoDataView(a) {
        showNoDataView(false)}Copy the code
  • Support network network error display
    override fun hideNetWorkErrView(a) {
        showNetWorkErrView(false)}override fun showNetWorkErrView(a) {
        showNetWorkErrView(true)}Copy the code
  • supportFragmentLazy loading
    / * * * lazy loading mechanism When the page is visible when loading data. * if the current FragmentTransaction setMaxLifecycle processing Lifecycle. State. * if failure of RESUMED the lazy loading FragmentTransaction setMaxLifecycle afferent BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT, * Then only the current Fragment is in the Lifecycle.State. The upper limit for all other fragments is Lifecycle.state.started. * If the BEHAVIOR_SET_USER_VISIBLE_HINT is passed, then all fragments are in the Lifecycle.state. RESUMED State, * and there will be fragments. SetUserVisibleHint (Boolean) callback * /
    private fun lazyLoad(a) {
        // The onCreateView is loaded and the page is visible before loading the data
        if (isViewCreated && isViewVisable) {
            Log.d(TAG, "lazyLoad: Successful")
            initData()
            // When the data is loaded, restore the flag to prevent repeated loading
            isViewCreated = false
            isViewVisable = false
        } else {
            Log.d(TAG, "lazyLoad: Fail")}}// Lazy loading is disabled by default
    open fun enableLazyData(a): Boolean {
        return false
    }
Copy the code
  • supportDataBinding
  • encapsulationUIChangeLiveData,UIChangeRefreshLiveData
  • ViewModelLazy loading

.

Pull-up function component lib_refresh_layout

  • Support the most basic pull down refresh, pull up load more
  • Support custom HeadView and FootView
  • Automatic refresh
  • Enable or disable drop-down refresh
  • Support enable, offensive pull-up loading more
  • General small chrysanthemum style DaisyRefreshLayout
  • Common little arrow style ArrowRefreshLayout

The project architecture

  • Integration mode: All business components are dependent on “APP shell project” to form a complete APP;
  • Component mode: Business components can be developed independently, and each business component is an APP;
  • App shell project: responsible for managing various business components and packaging APK, without specific business functions;
  • Business components: projects formed independently according to the company’s specific business;
  • Functional components: Provides some basic functions for APP development, such as log printing, drop-down refresh control, etc.
  • Main component: a service component that specifies the APP startup page and Main interface.
  • Common components: Functional components that support the foundation of business components and provide most of the functions required by business components

The MVVM architecture

BaseMVVM architecture

Official guidelines for MVVM architecture

  • View layer class diagram

  • ViewModel Layer class diagram

Componentized implementation

Based on Ali ARouter as a route, realize communication jump between components

Github.com/alibaba/ARo…

Integration pattern and component pattern transformation

The Module property is configured in the build.gradle file of each component. When we develop in component mode, the business component should be in the Application property. At this time, the business component is an Android App that can be independently developed and debugged. When we switch to integration mode development, the business components should be in the Library property so that they can be relied upon by our “app shell project” to form a fully functional app

Go to the root directory of the BaseDemo Project and find the gradle.properties file. Then change isModule to your desired development mode (true/false) and click Sync Project to synchronize the Project

isModule=false
Copy the code

if (isModule.toBoolean()) {
    apply plugin: 'com.android.application'
} else {
    apply plugin: 'com.android.library'
}
Copy the code

AndroidManifest merge problem between components

We can create an Androidmanifest.xml file for the business component in component development mode and specify the androidmanifest.xml file path according to isModule. Let business components use different Androidmanifest.xml in integration mode and component mode so that form collisions can be avoided for the module_main component as follows:

sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
            if (isModule.toBoolean()) {
                manifest.srcFile 'src/main/module/AndroidManifest.xml'
            } else {
                manifest.srcFile 'src/main/AndroidManifest.xml'
                java {
                    exclude 'debug/**'}}}}Copy the code

Application in component mode

Create an Application in the Debug directory for each component and configure it in the Androidmanifest.xml directory under Module

Application in integrated development mode

Exclude Application under DEBUG /** and use Application under moudLE_APP shell, which must inherit from ModuleApplication

class MyApp : ModuleApplication(a)Copy the code

Build. Gradle management

  • Third-party lib source libraries and all need to be importedlib.build.gradleEach individual moudle needs to be introducedmodule.build.gradle
  • versions.gradleRely on three party library version unified management
  • base.build.gradleUnified management of basic compiled versions

The development environment

  • Android Studio: 3.6, 4.0
  • Gradle version:.6.5
  • Gradle Android Plugin: 4.0.2

Version of the specification

  • MinSdkVersion (Minimum Version) : 21 (Android 5.0)
  • TargetSdkVersion: 30 (Adnroid 10.0)
  • CompileSdkVersion: 30 (Adnroid 10.0)
  • BuildToolsVersion (SDK build) : 30.0.2

The problem of feedback

Welcome to Start, call github.com/zhouhuandev… If you have any questions, please leave a message

gitee.com/shandong_zh…

Email address: [email protected]

About the author

Name : "zhouhuandev",
Blog : "https://blog.csdn.net/youxun1312"
Github:"https://github.com/zhouhuandev/BaseDemo"
Gitee:"https://gitee.com/shandong_zhaotai_network_sd_zhaotai/BaseDemo"
Copy the code

Thanks to third party open source

  • YImagePicker
  • KLog

Note: there is a large part of the project to help the open source masters, not a list, in this heartfelt thanks, if there is insufficient trouble to guide correction.

License

Copyright (C) zhouhuan, BaseDemo Framework Open Source Project 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 Project 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.Copy the code