目录
- 一、基本使用
- 二、ViewModel + DataBinding + LiveData结合使用
- 1. java版本
- 2. kotlin版本
一、基本使用
MyViewModel.kt
package com.example.myviewmodelimport androidx.lifecycle.ViewModelclass MyViewModel : ViewModel() {// 数据放这 进行横竖屏切换不会丢失var number : Int = 0
}
MainActivity.kt
package com.example.myviewmodelimport androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.lifecycle.ViewModelProvider
// Kotlin的绑定机制
import kotlinx.android.synthetic.main.activity_main.*class MainActivity : AppCompatActivity() {// 数据放这 进行横竖屏切换会丢失// var number : Int = 0private lateinit var myViewModel: MyViewModeloverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)// myViewModel = MyViewModel() // 不能之间实例化,因为这样写系统就不可控了// 旧版本的写法(扩展性不强)// ViewModelProviders.of(this).get(MyViewModel::class.java)// this == ViewModelStoreOwner接口myViewModel = ViewModelProvider(this, ViewModelProvider.NewInstanceFactory()).get(MyViewModel::class.java) // 通过反射来加载Java的class// Kotlin的绑定机制tv_number.text = "${myViewModel.number}"bt.setOnClickListener {tv_number.text = "${++myViewModel.number}"}}
}
数据存放在ViewModelStore类中,该类有一个Map存储<String, ViewModel>,value为ViewModel,该ViewModel存放相关的具体数据,横竖屏切换保证ViewModelStore是同一个对象。
二、ViewModel + DataBinding + LiveData结合使用
1. java版本
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<!-- DataBinding区域 -->
<layout xmlns:android="http://schemas.android.com/apk/res/android"><data><variablename="vm"type="com.example.jetpack_kotlin.MainViewModel" /></data><!-- UI绘制区域 --><LinearLayoutandroid:layout_width="fill_parent"android:layout_height="fill_parent"android:orientation="vertical"android:background="@drawable/phone2_bg"><LinearLayoutandroid:layout_width="fill_parent"android:layout_height="0dip"android:layout_weight="1" /><!-- 电话号码 --><TextViewandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:textSize="@dimen/activity_phone_tv"android:gravity="center"android:text="@{vm.phoneInfo}"android:textStyle="bold" /><!-- 表格布局 --><TableLayoutandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:layout_marginBottom="16dip"><!-- 第一列 --><TableRowandroid:layout_width="fill_parent"android:layout_height="wrap_content"><Buttonandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:layout_weight="1"android:text="@string/phone1"android:onClick="@{()->vm.appendNumber(String.valueOf(1))}"android:textSize="@dimen/activity_phone_bt"android:background="@drawable/phone_selector_number" /><Buttonandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:layout_weight="1"android:text="@string/phone2"android:onClick="@{()->vm.appendNumber(String.valueOf(2))}"android:textSize="@dimen/activity_phone_bt"android:background="@drawable/phone_selector_number" /><Buttonandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:layout_weight="1"android:text="@string/phone3"android:onClick="@{()->vm.appendNumber(String.valueOf(3))}"android:textSize="@dimen/activity_phone_bt"android:background="@drawable/phone_selector_number" /></TableRow><!-- 第二列 --><TableRowandroid:layout_width="fill_parent"android:layout_height="wrap_content"><Buttonandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:layout_weight="1"android:text="@string/phone4"android:onClick="@{()->vm.appendNumber(String.valueOf(4))}"android:textSize="@dimen/activity_phone_bt"android:background="@drawable/phone_selector_number" /><Buttonandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:layout_weight="1"android:text="@string/phone5"android:onClick="@{()->vm.appendNumber(String.valueOf(5))}"android:textSize="@dimen/activity_phone_bt"android:background="@drawable/phone_selector_number" /><Buttonandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:layout_weight="1"android:text="@string/phone6"android:onClick="@{()->vm.appendNumber(String.valueOf(6))}"android:textSize="@dimen/activity_phone_bt"android:background="@drawable/phone_selector_number" /></TableRow><!-- 第3列 --><TableRowandroid:layout_width="fill_parent"android:layout_height="wrap_content"><Buttonandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:layout_weight="1"android:text="@string/phone7"android:onClick="@{()->vm.appendNumber(String.valueOf(7))}"android:textSize="@dimen/activity_phone_bt"android:background="@drawable/phone_selector_number" /><Buttonandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:layout_weight="1"android:text="@string/phone8"android:onClick="@{()->vm.appendNumber(String.valueOf(8))}"android:textSize="@dimen/activity_phone_bt"android:background="@drawable/phone_selector_number" /><Buttonandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:layout_weight="1"android:text="@string/phone9"android:onClick="@{()->vm.appendNumber(String.valueOf(9))}"android:textSize="@dimen/activity_phone_bt"android:background="@drawable/phone_selector_number" /></TableRow><!-- 第4列 --><TableRowandroid:layout_width="fill_parent"android:layout_height="wrap_content"><Buttonandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:layout_weight="1"android:text="@string/phonexin"android:onClick="@{()->vm.appendNumber(@string/phonexin)}"android:textSize="@dimen/activity_phone_bt"android:background="@drawable/phone_selector_number" /><Buttonandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:layout_weight="1"android:text="@string/phone0"android:onClick="@{()->vm.appendNumber(String.valueOf(0))}"android:textSize="@dimen/activity_phone_bt"android:background="@drawable/phone_selector_number" /><Buttonandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:layout_weight="1"android:text="@string/phonejin"android:onClick="@{()->vm.appendNumber(@string/phonejin)}"android:textSize="@dimen/activity_phone_bt"android:background="@drawable/phone_selector_number" /></TableRow><!-- 第5列 --><TableRowandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:layout_marginTop="6dip"><LinearLayoutandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:layout_weight="1"android:orientation="vertical"><!-- 清空 --><Buttonandroid:layout_width="40dp"android:layout_height="40dp"android:textSize="@dimen/activity_phone_bt"android:background="@drawable/phone_selector_min"android:layout_gravity="center"android:onClick="@{()->vm.clear()}"android:layout_margin="6dip" /></LinearLayout><LinearLayoutandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:layout_weight="1"android:orientation="vertical"><!-- 拨打 --><ImageViewandroid:layout_width="46dip"android:layout_height="46dip"android:src="@drawable/phone_selector_call"android:onClick="@{()->vm.callPhone()}"android:layout_gravity="center" /></LinearLayout><LinearLayoutandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:layout_weight="1"android:orientation="vertical"><!-- 删除一个字符 --><Buttonandroid:layout_width="60dp"android:layout_height="wrap_content"android:textSize="@dimen/activity_phone_bt"android:background="@drawable/phone_selector_backspace"android:layout_gravity="center"android:onClick="@{()->vm.backspaceNumber()}"/></LinearLayout></TableRow></TableLayout></LinearLayout>
</layout>
MainViewModel.java
package com.example.jetpack_java2;import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.MutableLiveData;/*** AndroidViewModel 与 ViewModel的区别是 AndroidViewModel自带application环境*/
public class MainViewModel extends AndroidViewModel {// 传统方式的数据// private String phoneInfo = ""; // 目前无法实现感应功能// 实现感应功能 LiveData + DataBindingprivate MutableLiveData<String> phoneInfo;// 环境private Context mContext;public MainViewModel(@NonNull Application application) {super(application);mContext = application;}// 把数据暴露出去 给布局用public MutableLiveData<String> getPhoneInfo() {if (phoneInfo == null) {phoneInfo = new MutableLiveData<>();// 设置默认值phoneInfo.setValue("");}return phoneInfo;}/*** 输入* @param number*/public void appendNumber(String number) {phoneInfo.setValue(phoneInfo.getValue() + number);}/*** 删除*/public void backspaceNumber() {int length = phoneInfo.getValue().length();if (length > 0) {phoneInfo.setValue(phoneInfo.getValue().substring(0, length - 1));}}/*** 清空*/public void clear() {phoneInfo.setValue("");}/*** 拨打*/public void callPhone() {Intent intent = new Intent();intent.setAction(Intent.ACTION_CALL);intent.setData(Uri.parse("tel:" + phoneInfo.getValue()));// 非Activity启动拨号 或者是 非Activity启动任何的 startActivity都会崩溃intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);mContext.startActivity(intent);}
}
MainActivity.java
package com.example.jetpack_java2;import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;
import androidx.lifecycle.ViewModelProvider;
import androidx.lifecycle.ViewModelProviders;import android.os.Bundle;
import android.view.View;import com.example.jetpack_java2.databinding.ActivityMainBinding;public class MainActivity extends AppCompatActivity {private ActivityMainBinding dataBinding; // DataBinding初始化private MainViewModel mainViewModel; // MainViewModel初始化@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// setContentView(R.layout.activity_main);dataBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);// 旧版本的写法// mainViewModel = ViewModelProviders.of(this).get(MainViewModel.class);// 下面是新版本的写法// 如果MainViewModel extends ViewModel// mainViewModel = new ViewModelProvider(this,// new ViewModelProvider.NewInstanceFactory()).get(MainViewModel.class);// 如果MainViewModel extends AndroidViewModelmainViewModel = new ViewModelProvider(getViewModelStore(),new ViewModelProvider.AndroidViewModelFactory(getApplication())).get(MainViewModel.class);dataBinding.setVm(mainViewModel);dataBinding.setLifecycleOwner(this); // DataBinding与LiveData建立感应}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.jetpack_java2"><uses-permission android:name="android.permission.READ_CONTACTS"/><uses-permission android:name="android.permission.WRITE_CONTACTS"/><uses-permission android:name="android.permission.CALL_PHONE"/><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/AppTheme"><activity android:name=".MainActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity></application></manifest>
2. kotlin版本
MainViewModel.kt
package com.example.jetpack_kotlinimport android.app.Application
import android.content.Context
import android.content.Intent
import android.net.Uri
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.MutableLiveDataclass MainViewModel(application : Application) : AndroidViewModel(application) {// LiveData数据(有感应)val phoneInfo by lazy { MutableLiveData<String>() }init {phoneInfo.value = "" // 设置默认值}// 定义一个环境var mContext : Context = application/*** 输入*/fun appendNumber(number : String) {phoneInfo.value = phoneInfo.value + number}/*** 删除*/fun backspaceNumberr() {var length = phoneInfo.value?.length ?: 0if (length > 0) {phoneInfo.value = phoneInfo.value?.substring(0, length - 1)}}/*** 清空*/fun clear() {phoneInfo.value = ""}/*** 拨号*/fun callPhone() {var intent = Intent()intent.action = Intent.ACTION_CALLintent.data = Uri.parse("tel:" + phoneInfo.value)intent.flags = Intent.FLAG_ACTIVITY_NEW_TASKmContext.startActivity(intent)}
}
MainActivity.kt
package com.example.jetpack_kotlinimport androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.ViewModelProvider
import com.example.jetpack_kotlin.databinding.ActivityMainBindingclass MainActivity : AppCompatActivity() {var binding : ActivityMainBinding ?= nullvar viewModel : MainViewModel ?= nulloverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)// setContentView(R.layout.activity_main)binding = DataBindingUtil.setContentView(this, R.layout.activity_main)viewModel = ViewModelProvider(this, ViewModelProvider.AndroidViewModelFactory(application)).get(MainViewModel::class.java)binding?.vm = viewModel// DataBinding 与 LiveData 建立感应binding?.lifecycleOwner = this}
}