marclee44 / me

1 stars 0 forks source link

第一个应用的初次重构(ViewModel+Data Binding初探) #2

Open marclee44 opened 3 years ago

marclee44 commented 3 years ago

自从完成了第一个应用(从第一个Android应用开始),用惯了WPF的MVVM,没用绑定真的是各种不适应。没说的,学呗,重构呗。

既然要用绑定,第一步当然是要启用这些功能:

build.gradle中,加入

android {
...
    dataBinding {
       enabled true
    }
}

还是在build.gradle中,加入

dependencies {
    def lifecycle_version = "2.3.0"
...
    implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"
}

改造页面

activity_main.xml中,找到androidx.constraintlayout.widget.ConstraintLayout,Alt+Enter,Convert to data binding layout,页面自动转换为了支持Data Binding的样式:

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
...
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

<data>标签中可以加入layout支持的变量,包括Model、ViewModel等等。如:

    <data>
        <variable
            name="viewmodel"
            type="com.example.helloworld.HelloViewModel"/>
    </data>

同时,各控件的相关内容,就可以修改为绑定了。其基础格式为@{ expression },TwoWay‘@={ expression }` 嗯,就好像:

<EditText 
...
            android:text="@={viewmodel.name}" />

...

<Button
...
            android:onClick="@{() -> viewmodel.sendMessage()}" />

...

<TextView
...
            android:text="@{viewmodel.message}" />

接下来是MainActivity.java,需要在这将页面与ViewModel进行绑定

public class MainActivity extends AppCompatActivity {
    private ActivityMainBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
//        setContentView(R.layout.activity_main);

        HelloViewModel model = new ViewModelProvider(this).get(HelloViewModel.class);
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        binding.setViewmodel(model);
    }

可以看到,这里以DataBindingUtil.setContentView()代替了最初的setContentView() 另外,别忘了在销毁Activity时解除绑定,以免发生内存泄漏

    @Override
    protected void onDestroy() {
        super.onDestroy();

        binding.unbind();
    }

最后就是ViewModel本身了

public class HelloViewModel extends ViewModel {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void sendMessage() {
...
    }
}

HelloViewModel继承自ViewModel辅助程序类 name属性可被页面直接绑定 sendMessage()方法可被页面控件事件触发 如果属性较多,建个Model,MVVM的雏形就算完成了

soapgu commented 3 years ago

binding.unbind()是否有必要。 看源码binding用的弱引用,应该不会有拉住引用而内存泄漏的情况 图片