├── .gitignore ├── .idea ├── codeStyles │ └── Project.xml ├── gradle.xml ├── misc.xml └── runConfigurations.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── lihang │ │ └── viewmodelstu │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── lihang │ │ │ └── viewmodelstu │ │ │ ├── MainActivity.java │ │ │ ├── MyApplication.java │ │ │ ├── bean │ │ │ └── TestBean.java │ │ │ ├── observer │ │ │ └── MyObserver.java │ │ │ ├── roomabout │ │ │ ├── Address.java │ │ │ ├── AppDataBase.java │ │ │ ├── Clothes.java │ │ │ ├── ClothesDao.java │ │ │ ├── DBInstance.java │ │ │ ├── Person.java │ │ │ ├── PersonDao.java │ │ │ └── withrxjava │ │ │ │ ├── Dog.java │ │ │ │ └── DogDao.java │ │ │ ├── ui │ │ │ ├── activity │ │ │ │ ├── LifecyclesActivity.java │ │ │ │ ├── LiveDataActivity.java │ │ │ │ ├── RoomActivity.java │ │ │ │ ├── ViewModelActivity.java │ │ │ │ └── WithRxJavaActivity.java │ │ │ └── fragment │ │ │ │ └── OneFragment.java │ │ │ ├── utils │ │ │ ├── ActivityUtils.java │ │ │ ├── LogUtils.java │ │ │ └── ToastUtils.java │ │ │ └── viewmodel │ │ │ ├── LiveDataViewModel.java │ │ │ └── MyViewModel.java │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ └── ic_launcher_background.xml │ │ ├── layout │ │ ├── activity_lifecycles.xml │ │ ├── activity_livedata.xml │ │ ├── activity_main.xml │ │ ├── activity_room.xml │ │ ├── activity_viewmodel.xml │ │ ├── activity_with_rxjava.xml │ │ └── fragment_one.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── lihang │ └── viewmodelstu │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | xmlns:android 14 | 15 | ^$ 16 | 17 | 18 | 19 |
20 |
21 | 22 | 23 | 24 | xmlns:.* 25 | 26 | ^$ 27 | 28 | 29 | BY_NAME 30 | 31 |
32 |
33 | 34 | 35 | 36 | .*:id 37 | 38 | http://schemas.android.com/apk/res/android 39 | 40 | 41 | 42 |
43 |
44 | 45 | 46 | 47 | .*:name 48 | 49 | http://schemas.android.com/apk/res/android 50 | 51 | 52 | 53 |
54 |
55 | 56 | 57 | 58 | name 59 | 60 | ^$ 61 | 62 | 63 | 64 |
65 |
66 | 67 | 68 | 69 | style 70 | 71 | ^$ 72 | 73 | 74 | 75 |
76 |
77 | 78 | 79 | 80 | .* 81 | 82 | ^$ 83 | 84 | 85 | BY_NAME 86 | 87 |
88 |
89 | 90 | 91 | 92 | .* 93 | 94 | http://schemas.android.com/apk/res/android 95 | 96 | 97 | ANDROID_ATTRIBUTE_ORDER 98 | 99 |
100 |
101 | 102 | 103 | 104 | .* 105 | 106 | .* 107 | 108 | 109 | BY_NAME 110 | 111 |
112 |
113 |
114 |
115 |
116 |
-------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 15 | 16 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 14 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AACstu 2 | MVVM组件AAC(Android Architecture Components) 学习demo 3 | [Android从零开始搭建MVVM架构(1)————DataBinding](https://juejin.im/post/5d89d9f8f265da03f2340e2b) 4 | [Android从零开始搭建MVVM架构(2)————ViewModel](https://juejin.im/post/5d9c333cf265da5b8a515abb) 5 | [Android从零开始搭建MVVM架构(3)————LiveData](https://juejin.im/post/5d9d8f756fb9a04dd8591b8e) 6 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 29 5 | buildToolsVersion "29.0.2" 6 | defaultConfig { 7 | applicationId "com.lihang.viewmodelstu" 8 | minSdkVersion 22 9 | targetSdkVersion 29 10 | versionCode 1 11 | versionName "1.0" 12 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 13 | } 14 | 15 | dataBinding { 16 | enabled = true 17 | } 18 | buildTypes { 19 | release { 20 | minifyEnabled false 21 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 22 | } 23 | } 24 | } 25 | 26 | dependencies { 27 | implementation fileTree(dir: 'libs', include: ['*.jar']) 28 | implementation 'androidx.appcompat:appcompat:1.0.2' 29 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3' 30 | testImplementation 'junit:junit:4.12' 31 | androidTestImplementation 'androidx.test:runner:1.1.1' 32 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' 33 | implementation 'android.arch.lifecycle:extensions:1.1.1' 34 | 35 | // //Room的依赖引用 36 | implementation 'android.arch.persistence.room:runtime:2.1.4' 37 | annotationProcessor 'android.arch.persistence.room:compiler:2.1.4' 38 | 39 | // //Room配合RxJava使用 40 | implementation 'android.arch.persistence.room:rxjava2:2.1.4' 41 | implementation 'io.reactivex.rxjava2:rxandroid:2.0.2' 42 | 43 | 44 | } 45 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/lihang/viewmodelstu/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.lihang.viewmodelstu; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.test.platform.app.InstrumentationRegistry; 6 | import androidx.test.ext.junit.runners.AndroidJUnit4; 7 | 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | /** 14 | * Instrumented test, which will execute on an Android device. 15 | * 16 | * @see Testing documentation 17 | */ 18 | @RunWith(AndroidJUnit4.class) 19 | public class ExampleInstrumentedTest { 20 | @Test 21 | public void useAppContext() { 22 | // Context of the app under test. 23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 24 | 25 | assertEquals("com.lihang.viewmodelstu", appContext.getPackageName()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /app/src/main/java/com/lihang/viewmodelstu/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.lihang.viewmodelstu; 2 | 3 | import androidx.annotation.NonNull; 4 | import androidx.annotation.Nullable; 5 | import androidx.appcompat.app.AppCompatActivity; 6 | import androidx.databinding.DataBindingUtil; 7 | import androidx.lifecycle.LifecycleObserver; 8 | import androidx.lifecycle.Observer; 9 | 10 | import android.os.Bundle; 11 | import android.view.View; 12 | 13 | import com.lihang.viewmodelstu.databinding.ActivityMainBinding; 14 | import com.lihang.viewmodelstu.roomabout.DBInstance; 15 | import com.lihang.viewmodelstu.roomabout.withrxjava.Dog; 16 | import com.lihang.viewmodelstu.ui.activity.LifecyclesActivity; 17 | import com.lihang.viewmodelstu.ui.activity.LiveDataActivity; 18 | import com.lihang.viewmodelstu.ui.activity.RoomActivity; 19 | import com.lihang.viewmodelstu.ui.activity.ViewModelActivity; 20 | import com.lihang.viewmodelstu.ui.activity.WithRxJavaActivity; 21 | import com.lihang.viewmodelstu.utils.ActivityUtils; 22 | import com.lihang.viewmodelstu.utils.ToastUtils; 23 | 24 | import java.util.List; 25 | 26 | 27 | public class MainActivity extends AppCompatActivity implements View.OnClickListener { 28 | private ActivityMainBinding binding; 29 | 30 | @Override 31 | protected void onCreate(Bundle savedInstanceState) { 32 | super.onCreate(savedInstanceState); 33 | setContentView(R.layout.activity_main); 34 | binding = DataBindingUtil.setContentView(this, R.layout.activity_main); 35 | binding.setOnClickListener(this); 36 | } 37 | 38 | @Override 39 | public void onClick(View v) { 40 | switch (v.getId()) { 41 | case R.id.btn_viewModel: 42 | ActivityUtils.transfer(MainActivity.this, ViewModelActivity.class); 43 | break; 44 | 45 | case R.id.btn_liveData: 46 | ActivityUtils.transfer(MainActivity.this, LiveDataActivity.class); 47 | break; 48 | 49 | case R.id.btn_room: 50 | ActivityUtils.transfer(MainActivity.this, RoomActivity.class); 51 | break; 52 | 53 | case R.id.btn_with_rxjava: 54 | ActivityUtils.transfer(MainActivity.this, WithRxJavaActivity.class); 55 | break; 56 | 57 | case R.id.btn_with_livedata: 58 | DBInstance.getInstance().getDogDao().getToLiveData(2, 12).observe(this, new Observer>() { 59 | @Override 60 | public void onChanged(List dogs) { 61 | ToastUtils.showToast("查出来的当前size长度 ==> " + dogs.size()); 62 | } 63 | }); 64 | break; 65 | 66 | case R.id.btn_with_lifecycles: 67 | ActivityUtils.transfer(MainActivity.this, LifecyclesActivity.class); 68 | break; 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /app/src/main/java/com/lihang/viewmodelstu/MyApplication.java: -------------------------------------------------------------------------------- 1 | package com.lihang.viewmodelstu; 2 | import android.app.Application; 3 | 4 | 5 | /** 6 | * Created by leo 7 | * on 2019/10/8. 8 | */ 9 | public class MyApplication extends Application { 10 | public static MyApplication context; 11 | 12 | @Override 13 | public void onCreate() { 14 | super.onCreate(); 15 | context = this; 16 | } 17 | 18 | public static MyApplication getInstance() { 19 | if (context == null) { 20 | context = new MyApplication(); 21 | } 22 | return context; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/com/lihang/viewmodelstu/bean/TestBean.java: -------------------------------------------------------------------------------- 1 | package com.lihang.viewmodelstu.bean; 2 | 3 | import androidx.databinding.ObservableField; 4 | import androidx.databinding.ObservableInt; 5 | 6 | /** 7 | * Created by leo 8 | * on 2019/10/8. 9 | */ 10 | public class TestBean { 11 | public final ObservableField name = new ObservableField<>(); 12 | 13 | private void setName(String name) { 14 | this.name.set(name); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/lihang/viewmodelstu/observer/MyObserver.java: -------------------------------------------------------------------------------- 1 | package com.lihang.viewmodelstu.observer; 2 | 3 | import com.lihang.viewmodelstu.utils.LogUtils; 4 | 5 | import androidx.lifecycle.Lifecycle; 6 | import androidx.lifecycle.LifecycleObserver; 7 | import androidx.lifecycle.OnLifecycleEvent; 8 | 9 | /** 10 | * Created by leo 11 | * on 2019/10/14. 12 | */ 13 | public class MyObserver implements LifecycleObserver { 14 | @OnLifecycleEvent(Lifecycle.Event.ON_CREATE) 15 | public void onCreate() { 16 | LogUtils.i("MyObserver","onCreate"); 17 | } 18 | 19 | @OnLifecycleEvent(Lifecycle.Event.ON_START) 20 | public void onStart() { 21 | LogUtils.i("MyObserver","onStart"); 22 | } 23 | 24 | @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) 25 | public void onResume() { 26 | LogUtils.i("MyObserver","onResume"); 27 | } 28 | 29 | @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE) 30 | public void onPause() { 31 | LogUtils.i("MyObserver","onPause"); 32 | } 33 | 34 | @OnLifecycleEvent(Lifecycle.Event.ON_STOP) 35 | public void onStop() { 36 | LogUtils.i("MyObserver","onStop"); 37 | } 38 | 39 | @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) 40 | public void onDestory() { 41 | LogUtils.i("MyObserver","onDestory"); 42 | } 43 | 44 | // @OnLifecycleEvent(Lifecycle.Event.ON_ANY) 45 | // public void onAny() { 46 | // LogUtils.i("MyObserver","onAny"); 47 | // } 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/java/com/lihang/viewmodelstu/roomabout/Address.java: -------------------------------------------------------------------------------- 1 | package com.lihang.viewmodelstu.roomabout; 2 | 3 | /** 4 | * Created by leo 5 | * on 2019/10/10. 6 | */ 7 | public class Address { 8 | private String city; 9 | private String street; 10 | 11 | public String getCity() { 12 | return city; 13 | } 14 | 15 | public void setCity(String city) { 16 | this.city = city; 17 | } 18 | 19 | public String getStreet() { 20 | return street; 21 | } 22 | 23 | public void setStreet(String street) { 24 | this.street = street; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/java/com/lihang/viewmodelstu/roomabout/AppDataBase.java: -------------------------------------------------------------------------------- 1 | package com.lihang.viewmodelstu.roomabout; 2 | 3 | import com.lihang.viewmodelstu.roomabout.withrxjava.Dog; 4 | import com.lihang.viewmodelstu.roomabout.withrxjava.DogDao; 5 | 6 | import androidx.room.Database; 7 | import androidx.room.RoomDatabase; 8 | import androidx.room.migration.Migration; 9 | import androidx.sqlite.db.SupportSQLiteDatabase; 10 | 11 | /** 12 | * Created by leo 13 | * on 2019/10/10. 14 | */ 15 | //注解指定了database的表映射实体数据以及版本等信息 16 | @Database(entities = {Person.class, Clothes.class,Dog.class}, version = 1) 17 | public abstract class AppDataBase extends RoomDatabase { 18 | public abstract PersonDao getPersonDao(); 19 | 20 | public abstract ClothesDao getClothesDao(); 21 | 22 | public abstract DogDao getDogDao(); 23 | 24 | //数据库变动添加Migration 25 | public static final Migration MIGRATION_1_2 = new Migration(1, 2) { 26 | @Override 27 | public void migrate(SupportSQLiteDatabase database) { 28 | //告诉person表,增添一个String类型的字段 son 29 | database.execSQL("ALTER TABLE person ADD COLUMN son TEXT"); 30 | } 31 | }; 32 | } 33 | 34 | -------------------------------------------------------------------------------- /app/src/main/java/com/lihang/viewmodelstu/roomabout/Clothes.java: -------------------------------------------------------------------------------- 1 | package com.lihang.viewmodelstu.roomabout; 2 | 3 | import androidx.room.Entity; 4 | import androidx.room.ForeignKey; 5 | import androidx.room.PrimaryKey; 6 | 7 | import static androidx.room.ForeignKey.CASCADE; 8 | 9 | /** 10 | * Created by leo 11 | * on 2019/10/11. 12 | */ 13 | @Entity(foreignKeys = @ForeignKey(onDelete = CASCADE,onUpdate = CASCADE,entity = Person.class,parentColumns = "uid",childColumns = "father_id")) 14 | public class Clothes { 15 | @PrimaryKey(autoGenerate = true) 16 | private int id; 17 | private String color; 18 | 19 | private int father_id; 20 | 21 | public int getId() { 22 | return id; 23 | } 24 | 25 | public void setId(int id) { 26 | this.id = id; 27 | } 28 | 29 | public String getColor() { 30 | return color; 31 | } 32 | 33 | public void setColor(String color) { 34 | this.color = color; 35 | } 36 | 37 | public int getFather_id() { 38 | return father_id; 39 | } 40 | 41 | public void setFather_id(int father_id) { 42 | this.father_id = father_id; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/src/main/java/com/lihang/viewmodelstu/roomabout/ClothesDao.java: -------------------------------------------------------------------------------- 1 | package com.lihang.viewmodelstu.roomabout; 2 | 3 | import java.util.List; 4 | 5 | import androidx.room.Dao; 6 | import androidx.room.Insert; 7 | import androidx.room.Query; 8 | 9 | /** 10 | * Created by leo 11 | * on 2019/10/11. 12 | */ 13 | @Dao 14 | public interface ClothesDao { 15 | //查询所有数据 16 | @Query("Select * from clothes") 17 | List getAll(); 18 | 19 | //删除全部数据 20 | @Query("DELETE FROM clothes") 21 | void deleteAll(); 22 | 23 | @Insert 24 | void insert(Clothes... clothes); 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/lihang/viewmodelstu/roomabout/DBInstance.java: -------------------------------------------------------------------------------- 1 | package com.lihang.viewmodelstu.roomabout; 2 | 3 | import android.content.Context; 4 | 5 | import com.lihang.viewmodelstu.MyApplication; 6 | 7 | import androidx.room.Room; 8 | 9 | /** 10 | * Created by leo 11 | * on 2019/10/10. 12 | */ 13 | public class DBInstance { 14 | // private static final String DB_NAME = "/sdcard/LianSou/room_test.db"; 15 | private static final String DB_NAME = "room_test"; 16 | public static AppDataBase appDataBase; 17 | 18 | public static AppDataBase getInstance() { 19 | if (appDataBase == null) { 20 | synchronized (DBInstance.class) { 21 | if (appDataBase == null) { 22 | appDataBase = Room.databaseBuilder(MyApplication.getInstance(), AppDataBase.class, DB_NAME) 23 | //不推荐打开这句,但是为了demo展示,我只能打开了 24 | .allowMainThreadQueries() 25 | // .addMigrations(AppDataBase.MIGRATION_1_2) 26 | .build(); 27 | } 28 | } 29 | } 30 | return appDataBase; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/src/main/java/com/lihang/viewmodelstu/roomabout/Person.java: -------------------------------------------------------------------------------- 1 | package com.lihang.viewmodelstu.roomabout; 2 | 3 | import java.io.Serializable; 4 | 5 | import androidx.annotation.NonNull; 6 | import androidx.room.ColumnInfo; 7 | import androidx.room.Embedded; 8 | import androidx.room.Entity; 9 | import androidx.room.Ignore; 10 | import androidx.room.Index; 11 | import androidx.room.Insert; 12 | import androidx.room.PrimaryKey; 13 | 14 | /** 15 | * Created by leo 16 | * on 2019/10/10. 17 | */ 18 | //1、@Entity:数据表的实体类 19 | //2、@Entity(tableName = "person") 这样可以自定义表明,如果不设置则默认类名为表名 20 | //3、@Entity(primaryKeys = {"name","age"}),联合主键(不恰当的比喻):如果一张表以人名为主键,很可能有同名覆盖掉数据, 21 | // 所以这个时候,我们用如果用人名和年龄,或者是人名和出生日期联合起来当主键,那就是唯一的。 22 | 23 | //为了能保存数据,使数据持久化且Room必须能够对它进行操作,你可以用public修饰属性,或者你也可以设置成private,但必须提供set和get方法 24 | @Entity 25 | public class Person { 26 | public Person(String name, int age) { 27 | this.name = name; 28 | this.age = age; 29 | } 30 | 31 | //@PrimaryKey:每一个实体类都需要唯一的表示,true表示自增长 32 | @PrimaryKey(autoGenerate = true) 33 | //@ColumnInfo:数据表中字段名称。如果不设置则默认为属性名 34 | @ColumnInfo(name = "uid") 35 | private int uid; 36 | 37 | private String name; 38 | private int age; 39 | 40 | //@Ignore:标注不需要添加到数据表中的属性 41 | @Ignore 42 | private int money; 43 | 44 | //@Embedded 实体类中引用其他实体类。这样的话Address里属性也成为了表字段 45 | //@Embedded(prefix = "one"),这个是区分唯一性的,比如说一这个人可能有2个地址类似于tag,那么在数据表中就会以prefix+属性值命名 46 | @Embedded 47 | private Address address; 48 | 49 | // private String son; 50 | // 51 | // public String getSon() { 52 | // return son; 53 | // } 54 | // 55 | // public void setSon(String son) { 56 | // this.son = son; 57 | // } 58 | 59 | public int getUid() { 60 | return uid; 61 | } 62 | 63 | public void setUid(int uid) { 64 | this.uid = uid; 65 | } 66 | 67 | public String getName() { 68 | return name; 69 | } 70 | 71 | public void setName(String name) { 72 | this.name = name; 73 | } 74 | 75 | public int getAge() { 76 | return age; 77 | } 78 | 79 | public void setAge(int age) { 80 | this.age = age; 81 | } 82 | 83 | public int getMoney() { 84 | return money; 85 | } 86 | 87 | public void setMoney(int money) { 88 | this.money = money; 89 | } 90 | 91 | public Address getAddress() { 92 | return address; 93 | } 94 | 95 | public void setAddress(Address address) { 96 | this.address = address; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /app/src/main/java/com/lihang/viewmodelstu/roomabout/PersonDao.java: -------------------------------------------------------------------------------- 1 | package com.lihang.viewmodelstu.roomabout; 2 | 3 | import java.util.List; 4 | 5 | import androidx.room.Dao; 6 | import androidx.room.Delete; 7 | import androidx.room.Insert; 8 | import androidx.room.OnConflictStrategy; 9 | import androidx.room.Query; 10 | import androidx.room.Update; 11 | 12 | /** 13 | * Created by leo 14 | * on 2019/10/10. 15 | */ 16 | 17 | @Dao 18 | public interface PersonDao { 19 | //查询所有数据 20 | @Query("Select * from person") 21 | List getAll(); 22 | 23 | //删除全部数据 24 | @Query("DELETE FROM person") 25 | void deleteAll(); 26 | 27 | //一次插入单条数据 或 多条 28 | // @Insert(onConflict = OnConflictStrategy.REPLACE) 29 | @Insert 30 | void insert(Person... persons); 31 | 32 | //一次删除单条数据 或 多条 33 | @Delete 34 | void delete(Person... persons); 35 | 36 | //一次更新单条数据 或 多条 37 | @Update 38 | void update(Person... persons); 39 | 40 | //根据字段去查找数据 41 | @Query("SELECT * FROM person WHERE uid= :uid") 42 | Person getPersonByUid(int uid); 43 | 44 | //一次查找多个数据 45 | @Query("SELECT * FROM person WHERE uid IN (:userIds)") 46 | List loadAllByIds(List userIds); 47 | 48 | //多个条件查找 49 | @Query("SELECT * FROM person WHERE name = :name AND age = :age") 50 | Person getPersonByNameage(String name, int age); 51 | 52 | 53 | } 54 | -------------------------------------------------------------------------------- /app/src/main/java/com/lihang/viewmodelstu/roomabout/withrxjava/Dog.java: -------------------------------------------------------------------------------- 1 | package com.lihang.viewmodelstu.roomabout.withrxjava; 2 | 3 | import androidx.room.Entity; 4 | import androidx.room.PrimaryKey; 5 | 6 | /** 7 | * Created by leo 8 | * on 2019/10/12. 9 | */ 10 | @Entity 11 | public class Dog { 12 | @PrimaryKey(autoGenerate = true) 13 | private int id; 14 | private String name; 15 | private int color; 16 | 17 | public int getId() { 18 | return id; 19 | } 20 | 21 | public void setId(int id) { 22 | this.id = id; 23 | } 24 | 25 | public String getName() { 26 | return name; 27 | } 28 | 29 | public void setName(String name) { 30 | this.name = name; 31 | } 32 | 33 | public int getColor() { 34 | return color; 35 | } 36 | 37 | public void setColor(int color) { 38 | this.color = color; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/com/lihang/viewmodelstu/roomabout/withrxjava/DogDao.java: -------------------------------------------------------------------------------- 1 | package com.lihang.viewmodelstu.roomabout.withrxjava; 2 | 3 | 4 | import com.lihang.viewmodelstu.roomabout.Person; 5 | 6 | import java.util.List; 7 | 8 | import androidx.lifecycle.LiveData; 9 | import androidx.room.Dao; 10 | import androidx.room.Delete; 11 | import androidx.room.Insert; 12 | import androidx.room.Query; 13 | import androidx.room.Update; 14 | import io.reactivex.Completable; 15 | import io.reactivex.Flowable; 16 | import io.reactivex.Single; 17 | 18 | 19 | /** 20 | * Created by leo 21 | * on 2019/10/12. 22 | */ 23 | @Dao 24 | public interface DogDao { 25 | //返回值是插入成功的行id 26 | @Insert 27 | List insert(Dog... dogs); 28 | 29 | @Delete 30 | void delete(Dog... dogs); 31 | 32 | @Delete 33 | int delete(Dog dog); 34 | 35 | 36 | @Update 37 | void update(Dog... dogs); 38 | 39 | @Update 40 | int update(Dog dog); 41 | 42 | 43 | //查询所有对象 且 观察数据。用背压Flowable可以实现,如果需要一次性查询,可以用别的类型 44 | @Query("Select * from dog") 45 | Flowable> getAll(); 46 | 47 | 48 | //删除全部数据 49 | @Query("DELETE FROM dog") 50 | void deleteAll(); 51 | 52 | 53 | //根据字段去查找数据 54 | @Query("SELECT * FROM dog WHERE id= :id") 55 | Single getDogById(int id); 56 | 57 | 58 | @Query("SELECT * FROM dog WHERE id>= :minId AND id<= :maxId") 59 | LiveData> getToLiveData(int minId, int maxId); 60 | 61 | } 62 | -------------------------------------------------------------------------------- /app/src/main/java/com/lihang/viewmodelstu/ui/activity/LifecyclesActivity.java: -------------------------------------------------------------------------------- 1 | package com.lihang.viewmodelstu.ui.activity; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | 6 | import com.lihang.viewmodelstu.R; 7 | import com.lihang.viewmodelstu.observer.MyObserver; 8 | import com.lihang.viewmodelstu.utils.LogUtils; 9 | 10 | import androidx.annotation.NonNull; 11 | import androidx.annotation.Nullable; 12 | import androidx.lifecycle.Lifecycle; 13 | import androidx.lifecycle.LifecycleOwner; 14 | import androidx.lifecycle.LifecycleRegistry; 15 | import androidx.lifecycle.MutableLiveData; 16 | import androidx.lifecycle.Observer; 17 | 18 | /** 19 | * Created by leo 20 | * on 2019/10/14. 21 | */ 22 | public class LifecyclesActivity extends Activity implements LifecycleOwner { 23 | private MutableLiveData liveData = new MutableLiveData<>(); 24 | private LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this); 25 | 26 | @Override 27 | protected void onCreate(@Nullable Bundle savedInstanceState) { 28 | 29 | super.onCreate(savedInstanceState); 30 | setContentView(R.layout.activity_lifecycles); 31 | LogUtils.i("观察LiveData", " 没有走吗啊!"); 32 | liveData.observe(this, new Observer() { 33 | @Override 34 | public void onChanged(String s) { 35 | LogUtils.i("观察LiveData", " ==> " + s); 36 | } 37 | }); 38 | getLifecycle().addObserver(new MyObserver()); 39 | 40 | } 41 | 42 | @Override 43 | protected void onSaveInstanceState(@NonNull Bundle outState) { 44 | mLifecycleRegistry.markState(Lifecycle.State.CREATED); 45 | super.onSaveInstanceState(outState); 46 | } 47 | 48 | @NonNull 49 | @Override 50 | public Lifecycle getLifecycle() { 51 | return mLifecycleRegistry; 52 | } 53 | 54 | @Override 55 | protected void onStop() { 56 | super.onStop(); 57 | liveData.postValue("运行试试"); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /app/src/main/java/com/lihang/viewmodelstu/ui/activity/LiveDataActivity.java: -------------------------------------------------------------------------------- 1 | package com.lihang.viewmodelstu.ui.activity; 2 | 3 | import android.os.Bundle; 4 | import android.text.Editable; 5 | import android.text.TextWatcher; 6 | 7 | import com.lihang.viewmodelstu.R; 8 | import com.lihang.viewmodelstu.bean.TestBean; 9 | import com.lihang.viewmodelstu.databinding.ActivityLivedataBinding; 10 | import com.lihang.viewmodelstu.utils.LogUtils; 11 | import com.lihang.viewmodelstu.utils.ToastUtils; 12 | import com.lihang.viewmodelstu.viewmodel.LiveDataViewModel; 13 | 14 | import androidx.annotation.Nullable; 15 | import androidx.appcompat.app.AppCompatActivity; 16 | import androidx.databinding.DataBindingUtil; 17 | import androidx.lifecycle.LiveData; 18 | import androidx.lifecycle.MutableLiveData; 19 | import androidx.lifecycle.Observer; 20 | import androidx.lifecycle.ViewModelProviders; 21 | 22 | /** 23 | * Created by leo 24 | * on 2019/10/8. 25 | */ 26 | public class LiveDataActivity extends AppCompatActivity { 27 | ActivityLivedataBinding binding; 28 | private MutableLiveData liveData = new MutableLiveData<>(); 29 | private TestBean testBean = new TestBean(); 30 | private LiveDataViewModel model; 31 | 32 | @Override 33 | protected void onCreate(@Nullable Bundle savedInstanceState) { 34 | super.onCreate(savedInstanceState); 35 | setContentView(R.layout.activity_livedata); 36 | binding = DataBindingUtil.setContentView(this, R.layout.activity_livedata); 37 | binding.setOnlyLive(liveData.getValue()); 38 | binding.setDataBsource(testBean); 39 | binding.setLifecycleOwner(this); 40 | model = ViewModelProviders.of(this).get(LiveDataViewModel.class); 41 | binding.setLiveViewModel(model); 42 | addLiveObserve(); 43 | addTextViewChange(); 44 | 45 | } 46 | 47 | private void addTextViewChange() { 48 | binding.txtOnlyLive.addTextChangedListener(new TextWatcher() { 49 | @Override 50 | public void beforeTextChanged(CharSequence s, int start, int count, int after) { 51 | 52 | } 53 | 54 | @Override 55 | public void onTextChanged(CharSequence s, int start, int before, int count) { 56 | 57 | } 58 | 59 | @Override 60 | public void afterTextChanged(Editable s) { 61 | LogUtils.i("TextView的变化", "单独使用LiveData ==> " + s); 62 | } 63 | }); 64 | 65 | 66 | binding.txtDataBinding.addTextChangedListener(new TextWatcher() { 67 | @Override 68 | public void beforeTextChanged(CharSequence s, int start, int count, int after) { 69 | 70 | } 71 | 72 | @Override 73 | public void onTextChanged(CharSequence s, int start, int before, int count) { 74 | 75 | } 76 | 77 | @Override 78 | public void afterTextChanged(Editable s) { 79 | LogUtils.i("TextView的变化", "DataBinding双向绑定 ==> " + s); 80 | } 81 | }); 82 | 83 | 84 | binding.txtViewmodelLivedata.addTextChangedListener(new TextWatcher() { 85 | @Override 86 | public void beforeTextChanged(CharSequence s, int start, int count, int after) { 87 | 88 | } 89 | 90 | @Override 91 | public void onTextChanged(CharSequence s, int start, int before, int count) { 92 | 93 | } 94 | 95 | @Override 96 | public void afterTextChanged(Editable s) { 97 | LogUtils.i("TextView的变化", "ViewModel配合LiveData使用 ==> " + s); 98 | } 99 | }); 100 | 101 | 102 | } 103 | 104 | private void addLiveObserve() { 105 | liveData.observe(this, new Observer() { 106 | @Override 107 | public void onChanged(String s) { 108 | binding.setOnlyLive(s); 109 | LogUtils.i("观察LiveData", "单独使用LiveData ==> " + s); 110 | } 111 | }); 112 | } 113 | 114 | @Override 115 | protected void onStop() { 116 | super.onStop(); 117 | liveData.postValue("单独LiveData使用"); 118 | testBean.name.set("我是DataBinding双向绑定"); 119 | model.getData().postValue("ViewModel配合LiveData使用"); 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /app/src/main/java/com/lihang/viewmodelstu/ui/activity/RoomActivity.java: -------------------------------------------------------------------------------- 1 | package com.lihang.viewmodelstu.ui.activity; 2 | 3 | import android.os.Bundle; 4 | import android.view.View; 5 | 6 | import com.lihang.viewmodelstu.R; 7 | import com.lihang.viewmodelstu.databinding.ActivityRoomBinding; 8 | import com.lihang.viewmodelstu.roomabout.Clothes; 9 | import com.lihang.viewmodelstu.roomabout.DBInstance; 10 | import com.lihang.viewmodelstu.roomabout.Person; 11 | import com.lihang.viewmodelstu.utils.ActivityUtils; 12 | 13 | import androidx.annotation.Nullable; 14 | import androidx.appcompat.app.AppCompatActivity; 15 | import androidx.databinding.DataBindingUtil; 16 | 17 | /** 18 | * Created by leo 19 | * on 2019/10/10. 20 | */ 21 | public class RoomActivity extends AppCompatActivity implements View.OnClickListener { 22 | ActivityRoomBinding binding; 23 | 24 | @Override 25 | protected void onCreate(@Nullable Bundle savedInstanceState) { 26 | super.onCreate(savedInstanceState); 27 | setContentView(R.layout.activity_room); 28 | binding = DataBindingUtil.setContentView(this, R.layout.activity_room); 29 | binding.setOnClickListener(this); 30 | checkAll(); 31 | } 32 | 33 | @Override 34 | public void onClick(View v) { 35 | switch (v.getId()) { 36 | 37 | case R.id.btn_insert: 38 | Person person_ = new Person("Room", 18); 39 | DBInstance.getInstance().getPersonDao().insert(person_); 40 | checkAll(); 41 | break; 42 | case R.id.btn_insert_one: 43 | Person person = new Person("岩浆", 18); 44 | person.setUid(100); 45 | DBInstance.getInstance().getPersonDao().insert(person); 46 | checkAll(); 47 | break; 48 | 49 | case R.id.btn_insert_clothes_black: 50 | Clothes clothes = new Clothes(); 51 | clothes.setId(1); 52 | clothes.setColor("黑色"); 53 | clothes.setFather_id(100); 54 | DBInstance.getInstance().getClothesDao().insert(clothes); 55 | checkAll(); 56 | break; 57 | 58 | case R.id.btn_insert_clothes_red: 59 | Clothes clothes_ = new Clothes(); 60 | clothes_.setId(2); 61 | clothes_.setColor("红色"); 62 | clothes_.setFather_id(100); 63 | DBInstance.getInstance().getClothesDao().insert(clothes_); 64 | checkAll(); 65 | break; 66 | 67 | case R.id.btn_delete_: 68 | Person person1 = DBInstance.getInstance().getPersonDao().getPersonByUid(100); 69 | DBInstance.getInstance().getPersonDao().delete(person1); 70 | checkAll(); 71 | 72 | break; 73 | } 74 | } 75 | 76 | public void checkAll() { 77 | int allCount = DBInstance.getInstance().getPersonDao().getAll().size(); 78 | binding.txtAll.setText("当前人总数:" + allCount); 79 | 80 | int clothesCount = DBInstance.getInstance().getClothesDao().getAll().size(); 81 | binding.txtClothesAll.setText("当前衣服总数:" + clothesCount); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /app/src/main/java/com/lihang/viewmodelstu/ui/activity/ViewModelActivity.java: -------------------------------------------------------------------------------- 1 | package com.lihang.viewmodelstu.ui.activity; 2 | 3 | import android.os.Bundle; 4 | 5 | import com.lihang.viewmodelstu.R; 6 | import com.lihang.viewmodelstu.databinding.ActivityViewmodelBinding; 7 | import com.lihang.viewmodelstu.ui.fragment.OneFragment; 8 | import com.lihang.viewmodelstu.utils.LogUtils; 9 | import com.lihang.viewmodelstu.viewmodel.MyViewModel; 10 | 11 | import androidx.annotation.Nullable; 12 | import androidx.appcompat.app.AppCompatActivity; 13 | import androidx.databinding.DataBindingUtil; 14 | import androidx.fragment.app.FragmentActivity; 15 | import androidx.fragment.app.FragmentManager; 16 | import androidx.fragment.app.FragmentTransaction; 17 | import androidx.lifecycle.ViewModelProviders; 18 | 19 | /** 20 | * Created by leo 21 | * on 2019/10/8. 22 | */ 23 | /* 24 | * 我们在demo中使用了ViewProviders类。记得添加依赖:implementation 'android.arch.lifecycle:extensions:1.1.1' 25 | * 26 | * 27 | * 【ViewModel】 28 | * 简介: 29 | * ViewModel是以生命周期的方式存储与管理UI相关数据 30 | * 作用: 31 | * 1、在MVVM模式中,使Model与View分离 32 | * 2、存储数据 33 | * 3、负责为UI准备数据 34 | * 35 | * 1、ViewModel只会在Activity存活时,只会创建一次。(我们可以通过Activity生命周期打印,看结果) 36 | * 2、因为在Activity存活时,只创建一次,那么在此Activity下的所有Fragment都可以共享一个ViewModel 37 | * 3、由于 ViewModel 生命周期可能长与 activity 生命周期,所以为了避免内存泄漏Google禁止在ViewModel中持有Context或activity或view的引用。如果非得使用Context, 38 | * 可以继承AndroidViewModel 类中获取ApplicationContext 39 | * 40 | * 其他优势: 41 | * 1、之前我们在activity销毁重建时,可以用activity的onSaveInstanceState()机制保存和恢复数据,但缺点明显, 42 | * 只适合保存少量的可以被序列化、反序列化的数据。假如我们需要保存一个比较大的数据,这个时候ViewModel就可以实现。 43 | * 44 | * 2、app需要频繁异步请求数据,比如请求网络调接口,这些都是相当耗时。比如Activity被销毁后接口请求才返回,考虑到内存泄漏情况, 45 | * 会给我们增添好多复杂工作。 但现在我们利用ViewModel处理数据回调,可以解决此问题。 46 | * 47 | * 3、分担 UI controller,比如 Activity / Fragment 。为了避免臃肿和难以管理,我们可以分离出数据操作的职责给ViewModel。 48 | * 也就是使Model和View分离。 49 | * */ 50 | public class ViewModelActivity extends FragmentActivity { 51 | ActivityViewmodelBinding binding; 52 | 53 | @Override 54 | protected void onCreate(@Nullable Bundle savedInstanceState) { 55 | super.onCreate(savedInstanceState); 56 | setContentView(R.layout.activity_viewmodel); 57 | binding = DataBindingUtil.setContentView(this, R.layout.activity_viewmodel); 58 | addFragment(); 59 | MyViewModel myViewModel = ViewModelProviders.of(this).get(MyViewModel.class); 60 | LogUtils.i("MyViewModel的相关", "onCreate ==> " + myViewModel.hashCode()); 61 | } 62 | 63 | private void addFragment() { 64 | FragmentManager fragmentManager = getSupportFragmentManager(); 65 | FragmentTransaction ft = fragmentManager.beginTransaction(); 66 | OneFragment oneFragment = OneFragment.newInstance(0); 67 | OneFragment oneFragment_other = OneFragment.newInstance(1); 68 | ft.add(R.id.frameLayout, oneFragment); 69 | ft.add(R.id.frameLayout_other, oneFragment_other); 70 | ft.commit(); 71 | } 72 | 73 | @Override 74 | protected void onStart() { 75 | super.onStart(); 76 | MyViewModel myViewModel = ViewModelProviders.of(this).get(MyViewModel.class); 77 | LogUtils.i("MyViewModel的相关", "onStart ==> " + myViewModel.hashCode()); 78 | } 79 | 80 | @Override 81 | protected void onResume() { 82 | super.onResume(); 83 | MyViewModel myViewModel = ViewModelProviders.of(this).get(MyViewModel.class); 84 | LogUtils.i("MyViewModel的相关", "onResume ==> " + myViewModel.hashCode()); 85 | } 86 | 87 | @Override 88 | protected void onPause() { 89 | super.onPause(); 90 | MyViewModel myViewModel = ViewModelProviders.of(this).get(MyViewModel.class); 91 | LogUtils.i("MyViewModel的相关", "onPause ==> " + myViewModel.hashCode()); 92 | } 93 | 94 | @Override 95 | protected void onStop() { 96 | super.onStop(); 97 | MyViewModel myViewModel = ViewModelProviders.of(this).get(MyViewModel.class); 98 | LogUtils.i("MyViewModel的相关", "onStop ==> " + myViewModel.hashCode()); 99 | } 100 | 101 | 102 | @Override 103 | protected void onDestroy() { 104 | super.onDestroy(); 105 | MyViewModel myViewModel = ViewModelProviders.of(this).get(MyViewModel.class); 106 | LogUtils.i("MyViewModel的相关", "onDestroy ==> " + myViewModel.hashCode()); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /app/src/main/java/com/lihang/viewmodelstu/ui/activity/WithRxJavaActivity.java: -------------------------------------------------------------------------------- 1 | package com.lihang.viewmodelstu.ui.activity; 2 | 3 | import android.os.Bundle; 4 | import android.view.View; 5 | 6 | import com.lihang.viewmodelstu.R; 7 | import com.lihang.viewmodelstu.databinding.ActivityWithRxjavaBinding; 8 | import com.lihang.viewmodelstu.roomabout.DBInstance; 9 | import com.lihang.viewmodelstu.roomabout.withrxjava.Dog; 10 | import com.lihang.viewmodelstu.utils.LogUtils; 11 | import com.lihang.viewmodelstu.utils.ToastUtils; 12 | 13 | import java.util.List; 14 | import java.util.concurrent.Callable; 15 | 16 | import androidx.annotation.Nullable; 17 | import androidx.appcompat.app.AppCompatActivity; 18 | import androidx.databinding.DataBindingUtil; 19 | import androidx.lifecycle.LiveData; 20 | import androidx.lifecycle.Observer; 21 | import io.reactivex.Completable; 22 | import io.reactivex.CompletableObserver; 23 | import io.reactivex.Maybe; 24 | import io.reactivex.MaybeObserver; 25 | import io.reactivex.Single; 26 | import io.reactivex.SingleObserver; 27 | import io.reactivex.android.schedulers.AndroidSchedulers; 28 | import io.reactivex.disposables.Disposable; 29 | import io.reactivex.functions.Consumer; 30 | import io.reactivex.schedulers.Schedulers; 31 | 32 | /** 33 | * Created by leo 34 | * on 2019/10/12. 35 | */ 36 | public class WithRxJavaActivity extends AppCompatActivity implements View.OnClickListener { 37 | ActivityWithRxjavaBinding binding; 38 | 39 | @Override 40 | protected void onCreate(@Nullable Bundle savedInstanceState) { 41 | super.onCreate(savedInstanceState); 42 | setContentView(R.layout.activity_with_rxjava); 43 | binding = DataBindingUtil.setContentView(this, R.layout.activity_with_rxjava); 44 | binding.setOnClickListener(this); 45 | 46 | DBInstance.getInstance().getDogDao().getAll().subscribeOn(Schedulers.io()) 47 | .observeOn(AndroidSchedulers.mainThread()) 48 | .subscribe(new Consumer>() { 49 | @Override 50 | public void accept(List dogs) throws Exception { 51 | binding.txtAll.setText("当前狗狗总数" + dogs.size()); 52 | } 53 | }); 54 | } 55 | 56 | @Override 57 | public void onClick(View v) { 58 | switch (v.getId()) { 59 | case R.id.btn_insert_completable: 60 | Completable.fromCallable(new Callable>() { 61 | @Override 62 | public List call() throws Exception { 63 | Dog dog = new Dog(); 64 | return DBInstance.getInstance().getDogDao().insert(dog); 65 | } 66 | }).subscribeOn(Schedulers.io()) 67 | .observeOn(AndroidSchedulers.mainThread()) 68 | .subscribe(new CompletableObserver() { 69 | @Override 70 | public void onSubscribe(Disposable d) { 71 | 72 | } 73 | 74 | @Override 75 | public void onComplete() { 76 | LogUtils.i("使用Completable插入数据", "onComplete"); 77 | } 78 | 79 | @Override 80 | public void onError(Throwable e) { 81 | LogUtils.i("使用Completable插入数据", "onError"); 82 | } 83 | }); 84 | break; 85 | 86 | 87 | case R.id.btn_insert_single: 88 | Single.fromCallable(new Callable>() { 89 | @Override 90 | public List call() throws Exception { 91 | 92 | Dog dog = new Dog(); 93 | return DBInstance.getInstance().getDogDao().insert(dog); 94 | } 95 | }).subscribeOn(Schedulers.io()) 96 | .observeOn(AndroidSchedulers.mainThread()) 97 | .subscribe(new SingleObserver>() { 98 | @Override 99 | public void onSubscribe(Disposable d) { 100 | 101 | 102 | } 103 | 104 | @Override 105 | public void onSuccess(List o) { 106 | for (Long data : o) { 107 | LogUtils.i("使用Single插入数据", "onSuccess ==> " + data); 108 | } 109 | 110 | } 111 | 112 | @Override 113 | public void onError(Throwable e) { 114 | LogUtils.i("使用Single插入数据", "onError"); 115 | 116 | } 117 | }); 118 | break; 119 | 120 | case R.id.btn_insert_maybe: 121 | Maybe.fromCallable(new Callable>() { 122 | @Override 123 | public List call() throws Exception { 124 | 125 | Dog dog = new Dog(); 126 | return DBInstance.getInstance().getDogDao().insert(dog); 127 | } 128 | }).subscribeOn(Schedulers.io()) 129 | .observeOn(AndroidSchedulers.mainThread()) 130 | .subscribe(new MaybeObserver>() { 131 | @Override 132 | public void onSubscribe(Disposable d) { 133 | 134 | } 135 | 136 | @Override 137 | public void onSuccess(List longs) { 138 | for (Long data : longs) { 139 | LogUtils.i("使用Maybe插入数据", "onSuccess ==> " + data); 140 | } 141 | } 142 | 143 | @Override 144 | public void onError(Throwable e) { 145 | LogUtils.i("使用Maybe插入数据", "onError"); 146 | } 147 | 148 | @Override 149 | public void onComplete() { 150 | LogUtils.i("使用Maybe插入数据", "onComplete"); 151 | } 152 | }); 153 | break; 154 | 155 | case R.id.btn_with_livedata: 156 | 157 | DBInstance.getInstance().getDogDao().getToLiveData(2, 12).observe(this, new Observer>() { 158 | @Override 159 | public void onChanged(List dogs) { 160 | ToastUtils.showToast("查出来的当前size长度 ==> " + dogs.size()); 161 | } 162 | }); 163 | 164 | break; 165 | } 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /app/src/main/java/com/lihang/viewmodelstu/ui/fragment/OneFragment.java: -------------------------------------------------------------------------------- 1 | package com.lihang.viewmodelstu.ui.fragment; 2 | 3 | import android.os.Bundle; 4 | import android.view.LayoutInflater; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | 8 | import com.lihang.viewmodelstu.R; 9 | import com.lihang.viewmodelstu.databinding.FragmentOneBinding; 10 | import com.lihang.viewmodelstu.utils.ToastUtils; 11 | import com.lihang.viewmodelstu.viewmodel.MyViewModel; 12 | 13 | import androidx.annotation.NonNull; 14 | import androidx.annotation.Nullable; 15 | import androidx.databinding.DataBindingUtil; 16 | import androidx.fragment.app.Fragment; 17 | import androidx.lifecycle.ViewModelProviders; 18 | 19 | /** 20 | * Created by leo 21 | * on 2019/10/8. 22 | */ 23 | public class OneFragment extends Fragment { 24 | private int type; 25 | FragmentOneBinding binding; 26 | 27 | public static OneFragment newInstance(int type) { 28 | OneFragment fragment = new OneFragment(); 29 | fragment.type = type; 30 | return fragment; 31 | } 32 | 33 | 34 | @Nullable 35 | @Override 36 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 37 | binding = DataBindingUtil.inflate(inflater, R.layout.fragment_one, container, false); 38 | if (type == 0) { 39 | binding.relative.setBackgroundColor(getResources().getColor(R.color.color_1)); 40 | binding.btnOne.setText("Fragment - One:打印当前ViewHolder"); 41 | } else { 42 | binding.relative.setBackgroundColor(getResources().getColor(R.color.color_2)); 43 | binding.btnOne.setText("Fragment - Two:打印当前ViewHolder"); 44 | } 45 | binding.btnOne.setOnClickListener(new View.OnClickListener() { 46 | @Override 47 | public void onClick(View v) { 48 | ToastUtils.showToast(ViewModelProviders.of(getActivity()).get(MyViewModel.class).hashCode() + ""); 49 | } 50 | }); 51 | return binding.getRoot(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /app/src/main/java/com/lihang/viewmodelstu/utils/ActivityUtils.java: -------------------------------------------------------------------------------- 1 | package com.lihang.viewmodelstu.utils; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | 6 | /** 7 | * Created by leo 8 | * on 2019/10/8. 9 | */ 10 | public class ActivityUtils { 11 | //简单跳转 12 | public static void transfer(Context context, Class clazz) { 13 | Intent intent = new Intent(context, clazz); 14 | context.startActivity(intent); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/lihang/viewmodelstu/utils/LogUtils.java: -------------------------------------------------------------------------------- 1 | package com.lihang.viewmodelstu.utils; 2 | 3 | import android.util.Log; 4 | 5 | /** 6 | * Created by leo on 2017/9/12. 7 | */ 8 | 9 | public class LogUtils { 10 | 11 | //可以全局控制是否打印log日志 12 | private static boolean isEnableLog = true; 13 | private static int LOG_MAXLENGTH = 4000; 14 | public static final String TAG = LogUtils.class.getSimpleName(); 15 | private static final String TOP_DIVIDER = 16 | "┌────────────────────────────────────────────────────────"; 17 | 18 | private static final String BOTTOM_DIVIDER = 19 | "└────────────────────────────────────────────────────────"; 20 | private static final String MIDDLE_DIVIDER = "----------- 换行 ------------\n"; 21 | 22 | public static void v(String msg) { 23 | v(TAG, msg); 24 | } 25 | 26 | public static void v(String tagName, String msg) { 27 | if (isEnableLog) { 28 | if (msg == null) { 29 | Log.v(tagName, "null"); 30 | return; 31 | } 32 | int strLength = msg.length(); 33 | int start = 0; 34 | int end = LOG_MAXLENGTH; 35 | if (strLength > end) { 36 | StringBuffer sbf = new StringBuffer(); 37 | sbf.append(" \n" + TOP_DIVIDER).append(msg); 38 | String trueMsg = sbf.toString(); 39 | strLength = trueMsg.length(); 40 | while (strLength > end) { 41 | if (start == 0) { 42 | Log.v(tagName, trueMsg.substring(start, end)); 43 | start = end; 44 | end = end + LOG_MAXLENGTH; 45 | } else { 46 | end = end - MIDDLE_DIVIDER.length(); 47 | Log.v(tagName, MIDDLE_DIVIDER + trueMsg.substring(start, end)); 48 | start = end; 49 | end = end + LOG_MAXLENGTH; 50 | } 51 | } 52 | Log.v(tagName, trueMsg.substring(start, strLength)); 53 | Log.v(tagName, " \n" + BOTTOM_DIVIDER); 54 | } else { 55 | Log.v(tagName, msg); 56 | } 57 | } 58 | } 59 | 60 | public static void d(String msg) { 61 | d(TAG, msg); 62 | } 63 | 64 | public static void d(String tagName, String msg) { 65 | if (isEnableLog) { 66 | if (msg == null) { 67 | Log.d(tagName, "null"); 68 | return; 69 | } 70 | int strLength = msg.length(); 71 | int start = 0; 72 | int end = LOG_MAXLENGTH; 73 | if (strLength > end) { 74 | StringBuffer sbf = new StringBuffer(); 75 | sbf.append(" \n" + TOP_DIVIDER).append(msg); 76 | String trueMsg = sbf.toString(); 77 | strLength = trueMsg.length(); 78 | while (strLength > end) { 79 | if (start == 0) { 80 | Log.d(tagName, trueMsg.substring(start, end)); 81 | start = end; 82 | end = end + LOG_MAXLENGTH; 83 | } else { 84 | end = end - MIDDLE_DIVIDER.length(); 85 | Log.d(tagName, MIDDLE_DIVIDER + trueMsg.substring(start, end)); 86 | start = end; 87 | end = end + LOG_MAXLENGTH; 88 | } 89 | } 90 | Log.d(tagName, trueMsg.substring(start, strLength)); 91 | Log.d(tagName, " \n" + BOTTOM_DIVIDER); 92 | } else { 93 | Log.d(tagName, msg); 94 | } 95 | } 96 | } 97 | 98 | public static void i(String msg) { 99 | i(TAG, msg); 100 | } 101 | 102 | 103 | public static void i(String tagName, String msg) { 104 | if (isEnableLog) { 105 | if (msg == null) { 106 | Log.i(tagName, "null"); 107 | return; 108 | } 109 | int strLength = msg.length(); 110 | int start = 0; 111 | int end = LOG_MAXLENGTH; 112 | if (strLength > end) { 113 | StringBuffer sbf = new StringBuffer(); 114 | sbf.append(" \n" + TOP_DIVIDER).append(msg); 115 | String trueMsg = sbf.toString(); 116 | strLength = trueMsg.length(); 117 | while (strLength > end) { 118 | if (start == 0) { 119 | Log.i(tagName, trueMsg.substring(start, end)); 120 | start = end; 121 | end = end + LOG_MAXLENGTH; 122 | } else { 123 | end = end - MIDDLE_DIVIDER.length(); 124 | Log.i(tagName, MIDDLE_DIVIDER + trueMsg.substring(start, end)); 125 | start = end; 126 | end = end + LOG_MAXLENGTH; 127 | } 128 | } 129 | Log.i(tagName, trueMsg.substring(start, strLength)); 130 | Log.i(tagName, " \n" + BOTTOM_DIVIDER); 131 | } else { 132 | Log.i(tagName, msg); 133 | } 134 | } 135 | } 136 | 137 | public static void w(String msg) { 138 | w(TAG, msg); 139 | } 140 | 141 | public static void w(String tagName, String msg) { 142 | if (isEnableLog) { 143 | if (msg == null) { 144 | Log.w(tagName, "null"); 145 | return; 146 | } 147 | int strLength = msg.length(); 148 | int start = 0; 149 | int end = LOG_MAXLENGTH; 150 | if (strLength > end) { 151 | StringBuffer sbf = new StringBuffer(); 152 | sbf.append(" \n" + TOP_DIVIDER).append(msg); 153 | String trueMsg = sbf.toString(); 154 | strLength = trueMsg.length(); 155 | while (strLength > end) { 156 | if (start == 0) { 157 | Log.w(tagName, trueMsg.substring(start, end)); 158 | start = end; 159 | end = end + LOG_MAXLENGTH; 160 | } else { 161 | end = end - MIDDLE_DIVIDER.length(); 162 | Log.w(tagName, MIDDLE_DIVIDER + trueMsg.substring(start, end)); 163 | start = end; 164 | end = end + LOG_MAXLENGTH; 165 | } 166 | } 167 | Log.w(tagName, trueMsg.substring(start, strLength)); 168 | Log.w(tagName, " \n" + BOTTOM_DIVIDER); 169 | } else { 170 | Log.w(tagName, msg); 171 | } 172 | } 173 | } 174 | 175 | public static void e(String msg) { 176 | e(TAG, msg); 177 | } 178 | 179 | public static void e(String tagName, String msg) { 180 | if (isEnableLog) { 181 | if (msg == null) { 182 | Log.e(tagName, "null"); 183 | return; 184 | } 185 | int strLength = msg.length(); 186 | int start = 0; 187 | int end = LOG_MAXLENGTH; 188 | if (strLength > end) { 189 | StringBuffer sbf = new StringBuffer(); 190 | sbf.append(" \n" + TOP_DIVIDER).append(msg); 191 | String trueMsg = sbf.toString(); 192 | strLength = trueMsg.length(); 193 | while (strLength > end) { 194 | if (start == 0) { 195 | Log.e(tagName, trueMsg.substring(start, end)); 196 | start = end; 197 | end = end + LOG_MAXLENGTH; 198 | } else { 199 | end = end - MIDDLE_DIVIDER.length(); 200 | Log.e(tagName, MIDDLE_DIVIDER + trueMsg.substring(start, end)); 201 | start = end; 202 | end = end + LOG_MAXLENGTH; 203 | } 204 | } 205 | Log.e(tagName, trueMsg.substring(start, strLength)); 206 | Log.e(tagName, " \n" + BOTTOM_DIVIDER); 207 | } else { 208 | Log.e(tagName, msg); 209 | } 210 | } 211 | } 212 | } 213 | -------------------------------------------------------------------------------- /app/src/main/java/com/lihang/viewmodelstu/utils/ToastUtils.java: -------------------------------------------------------------------------------- 1 | package com.lihang.viewmodelstu.utils; 2 | 3 | import android.content.Context; 4 | import android.widget.Toast; 5 | 6 | import com.lihang.viewmodelstu.MyApplication; 7 | 8 | 9 | /** 10 | * Created by leo on 2017/9/4. 11 | * 防止重复点击toast,一直显示未隐藏 12 | */ 13 | 14 | public class ToastUtils { 15 | private static Context context = MyApplication.getInstance().getApplicationContext(); 16 | /** 之前显示的内容 */ 17 | private static String oldMsg ; 18 | /** Toast对象 */ 19 | private static Toast toast = null ; 20 | /** 第一次时间 */ 21 | private static long oneTime = 0 ; 22 | /** 第二次时间 */ 23 | private static long twoTime = 0 ; 24 | 25 | /** 26 | * 显示Toast 27 | * @param message 28 | */ 29 | public static void showToast(String message){ 30 | if(toast == null){ 31 | toast = Toast.makeText(context, message, Toast.LENGTH_SHORT); 32 | toast.show() ; 33 | oneTime = System.currentTimeMillis() ; 34 | }else{ 35 | twoTime = System.currentTimeMillis() ; 36 | if(message.equals(oldMsg)){ 37 | if(twoTime - oneTime > Toast.LENGTH_SHORT){ 38 | toast.show() ; 39 | } 40 | }else{ 41 | oldMsg = message ; 42 | toast.setText(message) ; 43 | toast.show() ; 44 | } 45 | } 46 | oneTime = twoTime ; 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /app/src/main/java/com/lihang/viewmodelstu/viewmodel/LiveDataViewModel.java: -------------------------------------------------------------------------------- 1 | package com.lihang.viewmodelstu.viewmodel; 2 | 3 | import androidx.lifecycle.LiveData; 4 | import androidx.lifecycle.MutableLiveData; 5 | import androidx.lifecycle.ViewModel; 6 | 7 | /** 8 | * Created by leo 9 | * on 2019/10/8. 10 | */ 11 | public class LiveDataViewModel extends ViewModel { 12 | private MutableLiveData nameLiveData = new MutableLiveData<>(); 13 | 14 | public MutableLiveData getData() { 15 | return nameLiveData; 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/com/lihang/viewmodelstu/viewmodel/MyViewModel.java: -------------------------------------------------------------------------------- 1 | package com.lihang.viewmodelstu.viewmodel; 2 | 3 | import com.lihang.viewmodelstu.utils.LogUtils; 4 | 5 | import androidx.lifecycle.ViewModel; 6 | 7 | /** 8 | * Created by leo 9 | * on 2019/10/8. 10 | */ 11 | public class MyViewModel extends ViewModel { 12 | 13 | @Override 14 | protected void onCleared() { 15 | super.onCleared(); 16 | LogUtils.i("MyViewModel的相关","Activity被杀死后也会被销毁!"); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_lifecycles.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_livedata.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 13 | 14 | 17 | 18 | 19 | 20 | 26 | 27 | 32 | 37 | 38 | 44 | 45 | 46 | 47 | 48 | 53 | 58 | 59 | 65 | 66 | 67 | 72 | 77 | 78 | 84 | 85 | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 11 | 12 | 13 | 14 | 22 | 23 |