Giter Site home page Giter Site logo

shouheng88 / arch-android Goto Github PK

View Code? Open in Web Editor NEW
217.0 4.0 36.0 2.38 MB

Type based Jetpack MVVM library.

License: Apache License 2.0

Java 19.47% Kotlin 80.53%
jetpack jetpack-android databinding databinding-android mvvm-architecture mvvm-android mvvm livedata-android-vmlib viewmodel livedata android-jetpack android-vmlib-fragment android androidx kotlin

arch-android's Introduction

Android VMLib: One Quick MVVM Library Based On Jetpack

中文

License Version Code Grade Build Min Sdk Version Author QQ Group

This project is designed for fast development. The library is mainly based on Jetpack LiveData and ViewModel. At the same time, this project can support DataBinding as well as ViewBinding integration. Also, it provided over 20 kinds of utils classes, companied with features of kotlin, make it easier to use. Anyway, this project can accelerate your development and save a lot of code for you.

1. Use the library

1.1 Add jcenter first

The library is published to jcenter. So, you can use jcenter to introduce this library in your project:

repositories { mavenCentral() }

1.2 Add dependecy

implementation "com.github.Shouheng88:vmlib:$latest-version"

If you need the downloader library based on OkHttp, try add the dependency below:

implementation "com.github.Shouheng88:vmlib-network:$latest-version"

1.3 Initialize the library

Call VMLib.onCreate(this) in your custom Application,

class App : Application() {
    override fun onCreate() {
        super.onCreate()
        VMLib.onCreate(this)
    }
}

This option is only used to get a global Context, so we could use it everywhere. And it won't take too much time.

1.4 Add proguard rules

# Add the rule below if you are using one of the EventBus
-keep class org.greenrobot.eventbus.EventBus {*;}
-keep class org.simple.eventbus.EventBus {*;}

# Add the rule if you want to use umeng
-keep class com.umeng.analytics.MobclickAgent {*;}

# Add the rule if you are using Android-UIX
-keep class me.shouheng.uix.common.UIX {*;}

# Add the rule and replace 'package' of your own App package if you are using ViewBinding
-keep class package.databinding.** {
    public static * inflate(android.view.LayoutInflater);
}

2. VMLib best practice

2.1 Embrace new interaction

Normaly, we need to initialize a LiveData instance everywhere if we want to use it in our project. This will lead to too many global variables in your ViewModel. By simply design, we could make it easy and clean. For example. if you want to request one page data from network, your viewmodel might be like this below,

// me.shouheng.eyepetizer.vm.EyepetizerViewModel#requestFirstPage
fun requestFirstPage() {
    // notify data loading state
    setLoading(HomeBean::class.java)
    // do netowrk request
    eyepetizerService.getFirstHomePage(null, object : OnGetHomeBeansListener {
        override fun onError(code: String, msg: String) {
            // notify load failed
            setFailed(HomeBean::class.java, code, msg)
        }

        override fun onGetHomeBean(homeBean: HomeBean) {
            // notify load succeed
            setSuccess(HomeBean::class.java, homeBean)
        }
    })
}

Then, in the activity, observe the data like below,

observe(HomeBean::class.java, {
    // on succeed
    val list = mutableListOf<Item>()
    it.data.issueList.forEach { issue ->
        issue.itemList.forEach { item ->
            if (item.data.cover != null
                && item.data.author != null
            ) list.add(item)
        }
    }
    adapter.addData(list)
}, { /* on failed */ loading = false }, { /* on loading */ })

This makes you logic simplier and more clean.

The magic is that we use the class type to locate a LiveData instance. Whenever we call setXXX in view model or observe in view layer, we use the Class type to get a LiveData instance from the so called LiveData Pool. So, that means, the Class is the unique identifies of LiveData.

Except Class, we can also use a bool variable and a integer to locate the LiveData.

2.2 Use DataBinding and Viewbinding

VMLib allows you use DataBinding, ViewBinding or none of them. When you want to use DataBinding, you need to make a little change on your gradle:

dataBinding {
    enabled true
}

and let your activity extend the CommonActivity.

For larger project, DataBinding might cause too much time for gradle building. So, for large project, you can use ViewBinding instead. At this time, you need to change the gradle as:

viewBinding {
    enabled true
}

and let your activity extend ViewBindingActivity.

Of course, if you want to use neither of them. What you need to do is just let your activity extend BaseActivity to use power provided by VMlib.

For fragment, VMLib provided similer abstract classes.

When let your activity or fragment extend base classes of VMLib, you have to specify a ViewModel type. For some pages, they are so simple that we don't need to define a ViewModel for it. In this case, we can use the empty view model provied by VMLib, EmptyViewModel.

2.3 Utils and utils-ktx

Different from other libraries, utils classes of VMLib was added by dependency of another project, Android-Utils. Android-Utils provided 20+ utils classes, including io, resources, image, animation and runtime permission etc. This is why VMLib is pwoerful. The utils classes of this library can meet almost all requirements of your daily development. You can get more information about Android-Utils by reading its document.

Except utils classes, VMLib also provided a utils kotlin extension based on Android-Utils. If you want to use the ktx library, you need to add the below dependency on your project,

implementation "me.shouheng.utils:utils-ktx:$latest-version"

By configing above, you can save a lot code. For example, if you want to get a drawable, tint it and then display it in ImageView. One line is enough:

iv.icon = drawableOf(R.drawable.ic_add_circle).tint(Color.WHITE)

If you want to request runtime permission in Activity, what you need to do is only writing one line below,

checkStoragePermission {  /* got permission */ }

As for avoding continous click, you only need one line,

btnRateIntro.onDebouncedClick { /* do something */ }

All in all, by VMLib you can significantly lower the difficulty of development.

2.4 Get result responsively

In VMLib, we refined logic of getting result from another Activity. In VMLib, you don't need to override onActivityResult method any more. You can use the onResult method and a integer for request code to get result:

onResult(0) { code, data ->
    if (code == Activity.RESULT_OK) {
        val ret = data?.getStringExtra("__result")
        L.d("Got result: $ret")
    }
}

This is in fact implemented by dispatching result and calling callback methods in BaseActivity. The goodness is that you don't need to override onActivityResult.

Except calling onResult method, you can also use the start method we provided and a callback to get result:

start(intent, 0) { resultCode, data ->
    if (resultCode == Activity.RESULT_OK) {
        val ret = data?.getStringExtra("__result")
        toast("Got result: $ret")
    }
}

By top level Activity, this is reather easy to achive and it won't cost too much code.

2.5 EventBus

VMLib support EventBus. Generally, for EventBus, you have two choices of EvnetBus and AndroidEventBus. To use EventBus, what you need to do is to use @ActivityConfiguration to decorate your activity and let useEventBus filed of it be true.

@ActivityConfiguration(useEventBus = true)
class DebugActivity : CommonActivity<MainViewModel, ActivityDebugBinding>() {
    // ...
}

Then, you need to use @Subscribe to subscribe:

@Subscribe
fun onGetMessage(simpleEvent: SimpleEvent) {
    // do something ...
}

At last, you can use method of Bus to send a global message anywhere.

VMLib can handle details of EventBus which make your code simpler.

2.6 Wrapper classes: Resources and Status

In VMLib, interaction between ViewModel and View is achived by transfering data wrappered by Resources and Status. The Status is an enum, which have three values, means 'Succeed', 'Failed' and 'Loading' seperatlly. The Resources contains a filed of Status, and a data filed which represent the data. Also the Resources provided 5 additional fileds whose name start with udf. You can use them to carry some extra information.

The wrapper is able to use not only just between view model and view layer but also other circumstances, for example, getting result from kotlin coroutines. The goodness is that you can use one class type transfer three states.

2.7 Container Activity

In order to use Fragment, we provided ContainerActivity, a container for Fragment. It's rather to use. For example, If we want to use SampleFragment in ContainerActivity, set some arguments, animation direction etc. The code below is enough for you:

ContainerActivity.open(SampleFragment::class.java)
    .put(SampleFragment.ARGS_KEY_TEXT, stringOf(R.string.sample_main_argument_to_fragment))
    .put(ContainerActivity.KEY_EXTRA_ACTIVITY_DIRECTION, ActivityDirection.ANIMATE_BACK)
    .withDirection(ActivityDirection.ANIMATE_FORWARD)
    .launch(context!!)

ContainerActivity can get fragment instance from fragment class and then display it in container. The logic is located in ContainerActivity, what you need to do is just implement your owen Fragment logic.

ContainerActivity is rather suitable for cases Fragment is simple. In such cases, you don't need to define Activity yourself, the ContainerActivity is enouth.

2.8 Compressor

So far, Compressor is the last part for VMLib.

This is an advanced and easy to use image compress library for Android, Compressor. It support not only async but also sync API. Also, it support multiple types of input and ouput, which can meet most of your requirements. Get more about it by its document.

3. About

License

Copyright (c) 2019-2020 Jeff Wang.

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.

arch-android's People

Contributors

shouheng88 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

arch-android's Issues

一个小建议

库写的很棒
提一个小建议:
这么大一版方法的重载,看的好累。。
完全可以移出
setFailed(HomeBean::class.java, code = errorCode, message = errorMsg)

TODOs

  • preference 的 f 方法加一层缓存:不做,考虑 preference 被移除等情况,容易出现问题

调整方法顺序

类 BasePreferenceFragment 的方法

 protected abstract fun doCreateView(savedInstanceState: Bundle?)

 @XmlRes protected abstract fun getPreferencesResId(): Int

的顺序,

原因:覆写的时候顺序和声明顺序一致

Components Development Guidelines

  • Should we share resources in a common module?

No! This might lead to too much conflicts when corporation.

  • 组件化协作开发方式,开闭源码

建议增加androidX支持

建议增加androidX支持
目前新建项目使用的都是androidX
默认生成的viewbinding是androidX包下的
与vmlib定义的类型不匹配

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.