├── .gitignore ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── sample │ │ └── app │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── sample │ │ │ └── app │ │ │ ├── application │ │ │ └── AppContext.java │ │ │ ├── bean │ │ │ └── AccountBean.java │ │ │ ├── model │ │ │ └── AccountModel.java │ │ │ └── ui │ │ │ ├── BottomFragment.java │ │ │ ├── MainActivity.java │ │ │ └── TopFragment.java │ └── res │ │ ├── drawable │ │ └── fragment_background_shape.xml │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── fragment_bottom.xml │ │ └── fragment_top.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 │ └── sample │ └── app │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── image ├── 1.png └── 2.png └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # Files for the ART/Dalvik VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # Generated files 12 | bin/ 13 | gen/ 14 | out/ 15 | 16 | # Gradle files 17 | .gradle/ 18 | build/ 19 | 20 | # Local configuration file (sdk path, etc) 21 | local.properties 22 | 23 | # Proguard folder generated by Eclipse 24 | proguard/ 25 | 26 | # Log Files 27 | *.log 28 | 29 | # Android Studio Navigation editor temp files 30 | .navigation/ 31 | 32 | # Android Studio captures folder 33 | captures/ 34 | 35 | # Intellij 36 | *.iml 37 | .idea/workspace.xml 38 | .idea/tasks.xml 39 | .idea/gradle.xml 40 | .idea/dictionaries 41 | .idea/libraries 42 | 43 | # Keystore files 44 | *.jks 45 | 46 | # External native build folder generated in Android Studio 2.2 and later 47 | .externalNativeBuild 48 | 49 | # Google Services (e.g. APIs or Firebase) 50 | google-services.json 51 | 52 | # Freeline 53 | freeline.py 54 | freeline/ 55 | freeline_project_description.json 56 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # About ViewModel And LiveData 2 | ### 关于ViewModel 3 | 4 | ViewModel类的设计目的是以一种关注生命周期的方式存储和管理与UI相关的数据。 5 | 例如:Activity在配置发生改变时(屏幕旋转),Activity就会重新创建,onCreate()方法也会重新调用。我们可以在onSaveInstanceState()方法中保存数据,并从onCreate()方法中通过Bundle恢复数据,但这种方法只适用于可以对其进行序列化的少量数据,而不适用于潜在的大量数据。使用ViewModel的话ViewModel会自动保留之前的数据并给新的Activity或Fragment使用。直到当前Activity被系统销毁时,Framework会调用ViewModel的onCleared()方法,我们可以在onCleared()方法中做一些资源清理操作。 6 | 7 | ### 关于LiveData 8 | 9 | LiveData是一个可观察的数据持有者类。与常见的观察者不同,LiveData是有生命周期感知的。这意味着它尊重其他应用程序组件的生命周期,比如Activity、Fragment或Service。这种感知确保LiveData只更新处于生命周期状态内的应用程序组件。 10 | 11 | LiveData是由observer类表示的观察者视为处于活动状态,如果其生命周期处于STARTED或RESUMED状态。LiveData会将观察者视为活动状态,并通知其数据的变化。LiveData未注册的观察对象以及非活动观察者是不会收到有关更新的通知。 12 | 13 | ### LiveData的优点: 14 | 15 | - 确保UI界面的数据状态 16 | >LiveData遵循观察者模式。LiveData在生命周期状态更改时通知Observer对象,更新这些Observer对象中的UI。观察者可以在每次应用程序数据更改时更新UI,而不是每次发生更改时更新UI。 17 | 18 | - 没有内存泄漏 19 | >当观察者被绑定他们对应的LifeCycle以后,当页面销毁时他们会自动被移除,不会导致内存溢出。 20 | 21 | - 不会因为Activity的不可见导致Crash 22 | >当Activity不可见时,即使有数据变化,LiveData也不会通知观察者。因为此时观察者的LifeCyele并不处于Started或者RESUMED状态。 23 | 24 | - 配置的改变 25 | >当前Activity配置改变(如屏幕方向),导致重新从onCreate走一遍,这时观察者们会立刻收到配置变化前的最新数据。 26 | 27 | - 共享资源 28 | >只需要一个LocationLivaData,连接系统服务一次,就能支持所有的观察者。 29 | 30 | - 不用再人为的处理生命周期 31 | >Activity或者Fragment只要在需要观察数据的时候观察数据即可,不需要理会生命周期变化了。这一切都交给LiveData来自动管理。 32 | 33 | ### 添加ViewModel和LiveData库的依赖 34 | 35 | 首先在Google的Maven存储库(项目最外层的build.gradle文件中添加如下: 36 | 37 | ```Java 38 | allprojects { 39 | repositories { 40 | jcenter() 41 | google() 42 | } 43 | } 44 | ``` 45 | 46 | 然后再app/build.gradle文件中添加相关依赖 47 | 48 | ```Java 49 | dependencies { 50 | compile fileTree(include: ['*.jar'], dir: 'libs') 51 | // ViewModel和LiveData依赖 52 | implementation "android.arch.lifecycle:extensions:1.1.0" 53 | annotationProcessor "android.arch.lifecycle:compiler:1.1.0" 54 | ...... 55 | } 56 | ``` 57 | 58 | ### 定义ViewModel和创建LiveData 59 | 60 | ```Java 61 | public class AccountModel extends AndroidViewModel{ 62 | 63 | // 创建LiveData 64 | private MutableLiveData mAccount = new MutableLiveData<>(); 65 | 66 | public AccountModel(@NonNull Application application) { 67 | super(application); 68 | } 69 | 70 | public void setAccount(String name, String phone, String blog){ 71 | mAccount.setValue(new AccountBean(name, phone, blog)); 72 | } 73 | 74 | public MutableLiveData getAccount(){ 75 | return mAccount; 76 | } 77 | 78 | // 当MyActivity被销毁时,Framework会调用ViewModel的onCleared() 79 | @Override 80 | protected void onCleared() { 81 | Log.e("AccountModel", "==========onCleared()=========="); 82 | super.onCleared(); 83 | } 84 | } 85 | ``` 86 | 87 | ### 使用 88 | 89 | ```Java 90 | public class MainActivity extends AppCompatActivity { 91 | 92 | private AccountModel mModel; 93 | 94 | @Override 95 | protected void onCreate(Bundle savedInstanceState) { 96 | super.onCreate(savedInstanceState); 97 | setContentView(R.layout.activity_main); 98 | final TextView mText = findViewById(R.id.textView); 99 | mModel = ViewModelProviders.of(this).get(AccountModel.class); 100 | findViewById(R.id.main_set_button).setOnClickListener(new View.OnClickListener() { 101 | @Override 102 | public void onClick(View v) { 103 | // 设置一条数据 104 | // mModel.setAccount("秦川小将", "182*****008", "http://blog.csdn.net/mjb00000"); 105 | // post一条数据 106 | mModel.getAccount().postValue(new AccountBean("秦川小将", "182*****008", "http://blog.csdn.net/mjb00000")); 107 | } 108 | }); 109 | mModel.getAccount().observe(this, new Observer() { 110 | @Override 111 | public void onChanged(@Nullable AccountBean accountBean) { 112 | mText.setText(AccountModel.getFormatContent(accountBean.getName(), accountBean.getPhone(), accountBean.getBlog())); 113 | } 114 | }); 115 | } 116 | } 117 | ``` 118 | 119 | ### 在同一个Activity中的数据共享 120 | 121 | 在同一个Activity中存在多个Fragment时,相互传递数据,一般通过定义接口来实现,Acticity从中协调。使用ViewModel能轻易解决Activity和Fragment之间的通信。 122 | 123 | - Activity不需要做任何事情,不需要干涉这两个Fragment之间的通信。 124 | - Fragment不需要互相知道,即使一个消失不可见,另一个也能正常的工作。 125 | - Fragment有自己的生命周期,它们之间互不干扰,即便你用一个FragmentC替代了B,FragmentA也能正常工作,没有任何问题。 126 | 127 | ##### Activity与Fragment和Fragment与Fragment之间的数据共享 128 | 129 | ```Java 130 | public class MainActivity extends AppCompatActivity { 131 | 132 | private AccountModel mModel; 133 | 134 | @Override 135 | protected void onCreate(Bundle savedInstanceState) { 136 | super.onCreate(savedInstanceState); 137 | setContentView(R.layout.activity_main); 138 | final TextView mText = findViewById(R.id.textView); 139 | // 添加Fragment试图 140 | getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container_1, new TopFragment()).commit(); 141 | getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container_2, new BottomFragment()).commit(); 142 | // 初始化ViewModel 143 | mModel = ViewModelProviders.of(this).get(AccountModel.class); 144 | findViewById(R.id.main_set_button).setOnClickListener(new View.OnClickListener() { 145 | @Override 146 | public void onClick(View v) { 147 | // 设置一条数据 148 | // mModel.setAccount("秦川小将", "182*****008", "http://blog.csdn.net/mjb00000"); 149 | // post一条数据 150 | mModel.getAccount().postValue(new AccountBean("秦川小将", "182*****008", "http://blog.csdn.net/mjb00000")); 151 | } 152 | }); 153 | mModel.getAccount().observe(this, new Observer() { 154 | @Override 155 | public void onChanged(@Nullable AccountBean accountBean) { 156 | mText.setText(AccountModel.getFormatContent(accountBean.getName(), accountBean.getPhone(), accountBean.getBlog())); 157 | } 158 | }); 159 | } 160 | } 161 | ``` 162 | 163 | Fragment1 164 | 165 | ```Java 166 | public class TopFragment extends Fragment { 167 | 168 | private AccountModel mModel; 169 | private TextView mText; 170 | 171 | @Override 172 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 173 | return inflater.inflate(R.layout.fragment_top, container, false); 174 | } 175 | 176 | @Override 177 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { 178 | super.onViewCreated(view, savedInstanceState); 179 | mText = view.findViewById(R.id.fragment_text_view); 180 | mModel = ViewModelProviders.of(getActivity()).get(AccountModel.class); 181 | view.findViewById(R.id.fragment_set_button).setOnClickListener(new View.OnClickListener() { 182 | @Override 183 | public void onClick(View v) { 184 | mModel.getAccount().postValue(new AccountBean("秦川小将", "182*****008", "这段数据是从Fragment中Post出来的")); 185 | } 186 | }); 187 | mModel.getAccount().observe(this, new Observer() { 188 | @Override 189 | public void onChanged(@Nullable AccountBean accountBean) { 190 | mText.setText(AccountModel.getFormatContent(accountBean.getName(), accountBean.getPhone(), accountBean.getBlog())); 191 | } 192 | }); 193 | } 194 | } 195 | ``` 196 | 197 | Fragment2 198 | 199 | ```Java 200 | public class BottomFragment extends Fragment { 201 | 202 | private AccountModel mModel; 203 | private TextView mText; 204 | 205 | @Override 206 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 207 | return inflater.inflate(R.layout.fragment_bottom, container, false); 208 | } 209 | 210 | @Override 211 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { 212 | super.onViewCreated(view, savedInstanceState); 213 | mText = view.findViewById(R.id.fragment_text_view); 214 | mModel = ViewModelProviders.of(getActivity()).get(AccountModel.class); 215 | mModel.getAccount().observe(this, new Observer() { 216 | @Override 217 | public void onChanged(@Nullable AccountBean accountBean) { 218 | mText.setText(AccountModel.getFormatContent(accountBean.getName(), accountBean.getPhone(), accountBean.getBlog())); 219 | } 220 | }); 221 | } 222 | } 223 | ``` 224 | 225 | ##### 示例图 226 | 227 | 从Activity中post出数据 228 | 229 | ![从Activity中post出数据](https://github.com/mengjingbo/ViewModelAndLiveDataSample/blob/master/image/1.png?raw=true) 230 | 231 | 从Fragment中post出数据 232 | 233 | ![从Fragment中post出数据](https://github.com/mengjingbo/ViewModelAndLiveDataSample/blob/master/image/2.png?raw=true) 234 | 235 | [查看案例源代码](https://github.com/mengjingbo/ViewModelAndLiveDataSample) 236 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 26 5 | defaultConfig { 6 | applicationId "com.sample.app" 7 | minSdkVersion 15 8 | targetSdkVersion 26 9 | versionCode 1 10 | versionName "1.0" 11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | implementation fileTree(dir: 'libs', include: ['*.jar']) 23 | // ViewModel and LiveData 24 | implementation "android.arch.lifecycle:extensions:1.1.0" 25 | annotationProcessor "android.arch.lifecycle:compiler:1.1.0" 26 | // Other 27 | implementation 'com.android.support:support-v4:26.1.0' 28 | implementation 'com.android.support:appcompat-v7:26.1.0' 29 | testImplementation 'junit:junit:4.12' 30 | 31 | } 32 | -------------------------------------------------------------------------------- /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/sample/app/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.sample.app; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.sample.app", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/sample/app/application/AppContext.java: -------------------------------------------------------------------------------- 1 | package com.sample.app.application; 2 | 3 | import android.app.Application; 4 | 5 | /** 6 | * 作者:秦川小将 7 | * 时间:2018/3/7 8 | * 描述: 9 | */ 10 | public class AppContext extends Application{ 11 | 12 | @Override 13 | public void onCreate() { 14 | super.onCreate(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/sample/app/bean/AccountBean.java: -------------------------------------------------------------------------------- 1 | package com.sample.app.bean; 2 | 3 | /** 4 | * 作者:秦川小将 5 | * 时间:2018/3/7 6 | * 描述: 7 | */ 8 | public class AccountBean { 9 | 10 | private String name; 11 | private String phone; 12 | private String blog; 13 | 14 | public AccountBean(String name, String phone, String blog) { 15 | this.name = name; 16 | this.phone = phone; 17 | this.blog = blog; 18 | } 19 | 20 | public String getName() { 21 | return name; 22 | } 23 | 24 | public void setName(String name) { 25 | this.name = name; 26 | } 27 | 28 | public String getPhone() { 29 | return phone; 30 | } 31 | 32 | public void setPhone(String phone) { 33 | this.phone = phone; 34 | } 35 | 36 | public String getBlog() { 37 | return blog; 38 | } 39 | 40 | public void setBlog(String blog) { 41 | this.blog = blog; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/src/main/java/com/sample/app/model/AccountModel.java: -------------------------------------------------------------------------------- 1 | package com.sample.app.model; 2 | 3 | import android.app.Application; 4 | import android.arch.lifecycle.AndroidViewModel; 5 | import android.arch.lifecycle.MutableLiveData; 6 | import android.arch.lifecycle.ViewModel; 7 | import android.support.annotation.NonNull; 8 | import android.util.Log; 9 | 10 | import com.sample.app.bean.AccountBean; 11 | 12 | /** 13 | * 作者:秦川小将 14 | * 时间:2018/3/7 15 | * 描述: 16 | */ 17 | public class AccountModel extends AndroidViewModel{ 18 | 19 | private MutableLiveData mAccount = new MutableLiveData<>(); 20 | 21 | public AccountModel(@NonNull Application application) { 22 | super(application); 23 | } 24 | 25 | public void setAccount(String name, String phone, String blog){ 26 | mAccount.setValue(new AccountBean(name, phone, blog)); 27 | } 28 | 29 | public MutableLiveData getAccount(){ 30 | return mAccount; 31 | } 32 | 33 | // 当MyActivity被销毁时,Framework会调用ViewModel的onCleared() 34 | @Override 35 | protected void onCleared() { 36 | Log.e("AccountModel", "==========onCleared()=========="); 37 | super.onCleared(); 38 | } 39 | 40 | public static String getFormatContent(String name, String phone, String blog) { 41 | StringBuilder mBuilder = new StringBuilder(); 42 | mBuilder.append("昵称:"); 43 | mBuilder.append(name); 44 | mBuilder.append("\n手机:"); 45 | mBuilder.append(phone); 46 | mBuilder.append("\n博客:"); 47 | mBuilder.append(blog); 48 | return mBuilder.toString(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/sample/app/ui/BottomFragment.java: -------------------------------------------------------------------------------- 1 | package com.sample.app.ui; 2 | 3 | import android.arch.lifecycle.Observer; 4 | import android.arch.lifecycle.ViewModelProvider; 5 | import android.arch.lifecycle.ViewModelProviders; 6 | import android.os.Bundle; 7 | import android.support.annotation.Nullable; 8 | import android.support.v4.app.Fragment; 9 | import android.view.LayoutInflater; 10 | import android.view.View; 11 | import android.view.ViewGroup; 12 | import android.widget.TextView; 13 | 14 | import com.sample.app.R; 15 | import com.sample.app.bean.AccountBean; 16 | import com.sample.app.model.AccountModel; 17 | 18 | /** 19 | * 作者:秦川小将 20 | * 时间:2018/3/8 21 | * 描述: 22 | */ 23 | public class BottomFragment extends Fragment { 24 | 25 | private AccountModel mModel; 26 | private TextView mText; 27 | 28 | @Override 29 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 30 | return inflater.inflate(R.layout.fragment_bottom, container, false); 31 | } 32 | 33 | @Override 34 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { 35 | super.onViewCreated(view, savedInstanceState); 36 | mText = view.findViewById(R.id.fragment_text_view); 37 | mModel = ViewModelProviders.of(getActivity()).get(AccountModel.class); 38 | mModel.getAccount().observe(this, new Observer() { 39 | @Override 40 | public void onChanged(@Nullable AccountBean accountBean) { 41 | mText.setText(AccountModel.getFormatContent(accountBean.getName(), accountBean.getPhone(), accountBean.getBlog())); 42 | } 43 | }); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/sample/app/ui/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.sample.app.ui; 2 | 3 | import android.arch.lifecycle.Observer; 4 | import android.arch.lifecycle.ViewModelProviders; 5 | import android.os.Bundle; 6 | import android.support.annotation.Nullable; 7 | import android.support.v7.app.AppCompatActivity; 8 | import android.view.View; 9 | import android.widget.TextView; 10 | 11 | import com.sample.app.R; 12 | import com.sample.app.bean.AccountBean; 13 | import com.sample.app.model.AccountModel; 14 | 15 | /** 16 | * 作者:秦川小将 17 | * 时间:2018/3/7 18 | * 描述: 19 | */ 20 | public class MainActivity extends AppCompatActivity { 21 | 22 | private AccountModel mModel; 23 | 24 | @Override 25 | protected void onCreate(Bundle savedInstanceState) { 26 | super.onCreate(savedInstanceState); 27 | setContentView(R.layout.activity_main); 28 | final TextView mText = findViewById(R.id.textView); 29 | getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container_1, new TopFragment()).commit(); 30 | getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container_2, new BottomFragment()).commit(); 31 | mModel = ViewModelProviders.of(this).get(AccountModel.class); 32 | findViewById(R.id.main_set_button).setOnClickListener(new View.OnClickListener() { 33 | @Override 34 | public void onClick(View v) { 35 | mModel.setAccount("秦川小将", "182*****008", "http://blog.csdn.net/mjb00000"); 36 | } 37 | }); 38 | mModel.getAccount().observe(this, new Observer() { 39 | @Override 40 | public void onChanged(@Nullable AccountBean accountBean) { 41 | mText.setText(AccountModel.getFormatContent(accountBean.getName(), accountBean.getPhone(), accountBean.getBlog())); 42 | } 43 | }); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/sample/app/ui/TopFragment.java: -------------------------------------------------------------------------------- 1 | package com.sample.app.ui; 2 | 3 | import android.arch.lifecycle.Observer; 4 | import android.arch.lifecycle.ViewModelProvider; 5 | import android.arch.lifecycle.ViewModelProviders; 6 | import android.os.Bundle; 7 | import android.support.annotation.Nullable; 8 | import android.support.v4.app.Fragment; 9 | import android.view.LayoutInflater; 10 | import android.view.View; 11 | import android.view.ViewGroup; 12 | import android.widget.TextView; 13 | 14 | import com.sample.app.R; 15 | import com.sample.app.bean.AccountBean; 16 | import com.sample.app.model.AccountModel; 17 | 18 | /** 19 | * 作者:蒙景博 20 | * 时间:2018/3/7 21 | * 描述: 22 | */ 23 | public class TopFragment extends Fragment { 24 | 25 | private AccountModel mModel; 26 | private TextView mText; 27 | 28 | @Override 29 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 30 | return inflater.inflate(R.layout.fragment_top, container, false); 31 | } 32 | 33 | @Override 34 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { 35 | super.onViewCreated(view, savedInstanceState); 36 | mText = view.findViewById(R.id.fragment_text_view); 37 | mModel = ViewModelProviders.of(getActivity()).get(AccountModel.class); 38 | view.findViewById(R.id.fragment_set_button).setOnClickListener(new View.OnClickListener() { 39 | @Override 40 | public void onClick(View v) { 41 | mModel.getAccount().postValue(new AccountBean("秦川小将", "182*****008", "这段数据是从Fragment中Post出来的")); 42 | } 43 | }); 44 | mModel.getAccount().observe(this, new Observer() { 45 | @Override 46 | public void onChanged(@Nullable AccountBean accountBean) { 47 | mText.setText(AccountModel.getFormatContent(accountBean.getName(), accountBean.getPhone(), accountBean.getBlog())); 48 | } 49 | }); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/fragment_background_shape.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 15 | 16 | 22 | 23 |