Jetpack Compse combat - a new development experience

No reply to the public Composeto obtain the installation package

Project Address: Wanandroid-Compose

After some time ago of the Android Dev Summit, I believe you have an idea of the Jetpack Compose . If you have not heard, you can read this article Jetpack latest developments Compose . All in all, Compose is a subversive of declarative UI framework , and its motto is to destroy the xml file!

Although Jetpack Compose is only a preview version, API may change, the lack of adequate controls support, or even not so stable, but that can not stop me Fengyun curious mind. I started the first time on the line and a Compose version Wanandroid application, function is relatively simple, including only home, advertising and the latest project, similar to the native Android page Viewpager + TabLayout. Gif below shows the basic pages in the application:

Page can be seen not so smooth, View reuse should be a problem, even I did not find how to do pull-down refresh. So, Compose brought us anything at all? Before answer this question, I would like to say for the Android application architecture problems.

Barren years - MVC

When I joined the line, can be said that the golden age of Android development, it can be said that the era of barren developers. On the one hand, it is no exaggeration to say that the basic write xml able to get a job. On the other hand, for developers, not far from the current development architecture specification. Remember correctly, I was the main development framework that year xUtils 2, a library round contract, binding from the layout and ID, network requests to the Photo Gallery, ORM operations, everything. The layout and then ID binding or runtime reflection, rather than compile notes. For a long time, Android even an official network libraries are not.

In architecture, a lot of people are Activity line and to die, I have met thousands of lines zouguolai of MainActivity. And I think this is the MVC architecture, Entity Entity class that Modellayer, Activity/Fragmentthat is, Controllerlayers, layout files that Viewlayer.

But this really is MVCit? Not really. Whether it is MVC, MVPor MVVM, should follow the principle of a minimum, the presentation layer and the service layer separation , which is given in the official website of Android Application Architecture Guide emphasizes the separation of concerns . Activity/FragmentIt is necessary to assume the task of the view layer, display and update the UI, but also to deal with the business logic layer, to obtain data. This is not consistent with the basic principles of architectural design.

Correct MVC model, Model layer only contains the entity classes Entity, more important role is business logic. View layer handles logical view. The Controller is a bridge between the Model and the View. How the bridge was built, and in fact there is no standard, according to your own needs it.

Ruan Yifeng quoted a teacher of drawing, generally such a meaning, but not necessarily completely one-way dependence.

From the barren era to come, MVC finally taste a little layering in it, the separation of view and business layers. However, dependency Model View layer and the layer, the code causing the coupling, will eventually lead to increasingly Activity bloated. Is there a way to View complete separation layer and the Model layer, so that the view layer and model layer is completely separated from it? MVP came into being.

Bronze years - MVP

Ruan Yifeng teacher still picture:

Compared to MVC, MVP used Presenter 层instead Controller 层, and View 层and Model 层completely separated, relying Presenter communication.

Imagine a scene to obtain user information. IViewA series of views defined in the interface layer interface, View layer (the Activity) implement IViewthe interface logic in the corresponding view. Presenter View layer held by business logic, i.e., the user information request. In general, not directly with the business logic Presenter, Model layer but by, for example, the Repository data warehouse, data acquired, to avoid making the same mistakes Presenter, has fat. Meanwhile, Presenter layer also holds VIew, and forwarded to View after obtaining user information.

To summarize, MVP of the View and Model completely decoupled, Presenter communication. View Presenter and co-processing view layer logic, Model layer is responsible for business logic.

On Github Android official architecture example architecture-samples in the MVP as the main branch of the firm for a long time. My first example is based on the official transformation of his MVP architecture, and use for a long time. But the MVP architecture as an interface-oriented programming, with the increasing complexity of the business, a kind of everywhere déjà vu interface, it seemed a bit cumbersome.

Another point, duties boundary Presenter is not clear enough, it calls the Model layer in addition to bear to obtain business logic, but also control the View layer processing UI. Say something with the following piece of code:

class LoginPresenter(private val mView: LoginContract.View) : LoginContract.Presenter {

    ......

    override fun login(userName: String, passWord: String) {
        CoroutineScope(Dispatchers.Main).launch {
            val result = WanRetrofitClient.service.login(userName, passWord).await()
            with(result) {
                if (errorCode == -1)  mView.loginError(errorMsg) else mView.login(data)
            }
        }
    }
}

Upon the occurrence of any change in the View layer, Presenter layer should make the appropriate changes. While decoupling between View and Model, View, and Presenter but it couples. Ideally, Presenter layer should be responsible only access to data, change the View layer automatic observation data. So, MVVM here.

Golden Age - MVVM

Google's official view of the town house.

MVP scenery has long since disappeared, Android official architecture example architecture-samples of the main branch has switched to MVVM. In the Android MVVM architecture, the ViewModel is the most important, it is an aspect Repository acquired through the data warehouse, on the other hand update Activity / Fragment View layer from the acquired data. And so on, listen to how this sentence so familiar, Presenter also did not do these things? Indeed, they are doing things that are similar, but the realization is completely different.

In my open source project Wanandroid is LoginViewModelan example:

class LoginViewModel(val repository: LoginRepository) : BaseViewModel() {

    private val _uiState = MutableLiveData<LoginUiModel>()
    val uiState: LiveData<LoginUiModel>
        get() = _uiState


    fun loginDataChanged(userName: String, passWord: String) {
        emitUiState(enableLoginButton = isInputValid(userName, passWord))
    }

    // ViewModel 只处理视图逻辑,数据仓库 Repository 负责业务逻辑
    fun login(userName: String, passWord: String) {
        viewModelScope.launch(Dispatchers.Default) {
            if (userName.isBlank() || passWord.isBlank()) return@launch

            withContext(Dispatchers.Main) { showLoading() }

            val result = repository.login(userName, passWord)

            withContext(Dispatchers.Main) {
                if (result is Result.Success) {
                    emitUiState(showSuccess = result.data,enableLoginButton = true)
                } else if (result is Result.Error) {
                    emitUiState(showError = result.exception.message,enableLoginButton = true)
                }
            }
        }
    }

    private fun showLoading() {
        emitUiState(true)
    }

    private fun emitUiState(
            showProgress: Boolean = false,
            showError: String? = null,
            showSuccess: User? = null,
            enableLoginButton: Boolean = false,
            needLogin: Boolean = false
    ) {
        val uiModel = LoginUiModel(showProgress, showError, showSuccess, enableLoginButton,needLogin)
        _uiState.value = uiModel
    }

    data class LoginUiModel(
            val showProgress: Boolean,
            val showError: String?,
            val showSuccess: User?,
            val enableLoginButton: Boolean,
            val needLogin:Boolean
    )
}

Can be seen, is not ViewModel cited View, View observed data varied by LIveData observable, based observer pattern and do ViewModel completely decoupled.

Data-driven view , this is Jetpack MVVM an important principle respected. The basic data stream as follows:

  • Repository data layer is responsible for obtaining and integrating data from different data sources, is responsible for substantially all the business logic
  • ViewModel holds Repository, the View layer to get data and driver updates
  • View holds ViewModel, observations LiveData carry, data-driven UI

And some developers have talked about such a problem, do not use DataBinding ** fairly MVVM it? ** I think the core of MVVM never lies DataBinding. DataBinding can only help us data-driven view to achieve the ultimate, the way you can two-way binding.

Jetpack MVVM to say for the most satisfied with the piece, and that is none other than non-DataBinding. I think in the narrow DataBinding is a library written against humanity logic code in xml inside, I am firmly opposed to the introduction of it in any project. Opinionated when it is easy to into the errors in reading KunminX of re-learning Android: from being opposed to the real Hong Jetpack DataBinding! After that, as the article name, really fragrant.

Fragrant incense indeed, all make me work early is a good thing. At some times I commit log, I wrote to destroy Adapter words, I was just using DataBinding eliminated Adapter most of RecyclerView. But after submitting my uneasy conscience, I pursue or write logic code in the xml file, this really does humanity do?

The future can be - Jetpack Compose

Now you should be able to understand what I read on the Jetpack Compose of enforcement. Other features shuffled around, in my opinion, it is the perfect solution to data-driven view of the problem, I do not need to use the DataBinding.

Compose show how simple code usage. The following code depicts the list of articles under the Home Tab.

@Composable
fun MainTab(articleUiModel: ArticleViewModel.ArticleUiModel?) {

    VerticalScroller {
        FlexColumn {
            inflexible {
                HeightSpacer(height = 16.dp)
            }
            flexible(1f) {
                articleUiModel?.showSuccess?.datas?.forEach {
                    ArticleItem(article = it)
                }

                articleUiModel?.showError?.let { toast(App.CONTEXT, it) }
wenjian
                articleUiModel?.showLoading?.let { Progress() }
            }
        }
    }
}

The wording is called declarative programming , I will use Flutter students should be very familiar. Method parameter ArticleUiModelis the data entity class, the direct UI constructed in accordance with the data ArticleUiModel. He said the vernacular point is to give you the length and width of the rectangle, so you draw a rectangle out. Finally, add @Composeannotations, is a component of the available UI. A closer look at the code, which also use two UI components, ArticleItemand Progress, the code is not posted. Namely item item list of articles and loading progress bar.

So, how does data updates? The easiest way is to use @Modelannotations.

@Model
data class ArticleUiModel(){
  ......
}

Yes, that simple. @ModelNotes will automatically put your data classes become observable object, as long ArticleUIModel changes, UI will be automatically updated.

But I used in conjunction LiveData in the actual development, the performance seems not so normal. Later on Medium accidentally saw a solution for LiveData do a special deal:

// general purpose observe effect. this will likely be provided by LiveData. effect API for
// compose will also simplify soon.
fun <T> observe(data: LiveData<T>) = effectOf<T?> {
    val result = +state<T?> { data.value }
    val observer = +memo { Observer<T> { result.value = it } }

    +onCommit(data) {
        data.observeForever(observer)
        onDispose { data.removeObserver(observer) }
    }

    result.value
}wenjian

LiveData can be observed in the Activity / Fragment in:

class MainActivity : BaseVMActivity<ArticleViewModel>() {

    override fun initView() {
        setContent {
           +observe(mViewModel.uiState)
            WanandroidApp(mViewModel)
        }
    }

    override fun initData() {
       mViewModel.getHomeArticleList()
    }
}

Observation can be automatically included in such LiveData View layer.

No xml, no DataBinding, everything looks much more desirable. But there is so little Zaoxin UI experience, you can reply back in a number of public Compose installation experience. Because still early preview version, which is understandable. I believe, until the release Release version, must be sufficient to completely replace the soundtrack of View system.

This article does not detail the course and other features detailed Jetpack Compose. For more information I recommend the following two articles:

At last

As Android Jetpack official website introduction page said, Jetpack can help developers more easily write high-quality applications. Indeed, with the specification of the application architecture, we just need to focus on the code needed to accelerate the development, elimination of boilerplate code, reducing crashes and memory leaks, strong build quality applications. I can not think of any reason not to use the Jetpack to build your application. While the Compose will be called an extremely important piece of the puzzle in Jetpack.

Jetpack Compse, the future can be!


Add my micro letter, adding technical exchange group.

No public backstage reply "compose", get the latest installation package.

Guess you like

Origin www.cnblogs.com/bingxinshuo/p/11879246.html