android mvvm官方demo,Android mvvm架构demo(DataBinding+LiveData+ViewModel+ Repository)

1.实现效果

实现页面加载Bing每日一图的功能

2.项目结构

image(忽略没有按分类创建).png

3.实现过程

1.注入依赖

//ViewModel与LiveData

implementation "android.arch.lifecycle:extensions:1.1.1"

//图片加载

implementation 'com.github.bumptech.glide:glide:4.9.0'

//网络请求

implementation 'com.squareup.retrofit2:retrofit:2.5.0'

implementation 'com.squareup.retrofit2:adapter-rxjava2:2.5.0'

implementation 'io.reactivex.rxjava2:rxandroid:2.0.2'

implementation 'io.reactivex.rxjava2:rxjava:2.1.12'

//GSON解析

implementation 'com.squareup.retrofit2:converter-gson:2.5.0'

同时需要启用DataBinding

android {

..........

dataBinding {

enabled = true

}

}

2.接口请求

https://cn.bing.com/HPImageArchive.aspx?format=js&idx=1&n=1

其中 format为请求格式,包含JSON、XML等,

idx为请求ID,n为每次请求的个数

(在AndroidManifest.xml文件内添加网络权限)

接口返回参数样式如下

{"images":[{"startdate":"20190724","fullstartdate":"201907241600","enddate":"20190725","url":"/th?id=OHR.CathedralMountBuffalo_ZH-CN4341947983_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp","urlbase":"/th?id=OHR.CathedralMountBuffalo_ZH-CN4341947983","copyright":"清晨暴雨中的Cathedral,澳大利亚布法罗山 (© Ilya Genkin/Alamy)","copyrightlink":"https://www.bing.com/search?q=Cathedral&form=hpcapt&mkt=zh-cn","title":"","quiz":"/search?q=Bing+homepage+quiz&filters=WQOskey:%22HPQuiz_20190724_CathedralMountBuffalo%22&FORM=HPQUIZ","wp":true,"hsh":"5c4b7b7d11456918494bc1ecea07951c","drk":1,"top":1,"bot":1,"hs":[]}],"tooltips":{"loading":"正在加载...","previous":"上一个图像","next":"下一个图像","walle":"此图片不能下载用作壁纸。","walls":"下载今日美图。仅限用作桌面壁纸。"}}

利用AS内GsonFormat插件自动生成ImageBean实体类

3.创建基础接受类BaseData

public class BaseData {

private T data;

private String message;

public BaseData() {

}

public BaseData(T data, String message) {

this.data = data;

this.message = message;

}

public T getData() {

return data;

}

public void setData(T data) {

this.data = data;

}

public String getMessage() {

return message;

}

public void setMessage(String message) {

this.message = message;

}

}

4.搭建基础网络请求框架

采用了Retrofit+Rxjava作为网络访问框架(都是些基础使用)

public class NetUtil {

private Retrofit retrofit;

public NetUtil() {

retrofit = new Retrofit.Builder()

.baseUrl("https://cn.bing.com/")

.addConverterFactory(GsonConverterFactory.create())

.addCallAdapterFactory(RxJava2CallAdapterFactory.create())

.build();

}

public interface ImageService {

@GET("HPImageArchive.aspx")

Observable getBingImage(@Query("format") String format,

@Query("idx") int idx,

@Query("n") int n);

}

public Observable getBingImage(String format, int idx, int n) {

return retrofit.create(ImageService.class).getBingImage(format, idx, n);

}

}

5.搭建Repository模块即具体的网络请求模块

public class ImageRepository {

private static final String TAG = "ImageRepository";

private NetUtil netUtil = new NetUtil();

private MutableLiveData> imageBean1 = new MutableLiveData<>();

private int idx = 1;

/**

* 获取图片

*/

public MutableLiveData> getBingImage() {

netUtil.getBingImage("js", idx, 1)

.subscribeOn(Schedulers.io())

.observeOn(AndroidSchedulers.mainThread())

.subscribe(new Observer() {

@Override

public void onSubscribe(Disposable d) {

}

@Override

public void onNext(ImageBean imageBean) {

imageBean1.setValue(new BaseData<>(imageBean, null));

}

@Override

public void onError(Throwable e) {

}

@Override

public void onComplete() {

}

});

return imageBean1;

}

/**

* 获取下一张图片

*/

public MutableLiveData> getNextImage() {

if (idx > 6) {

imageBean1.setValue(new BaseData(null, "已经是最后一张啦"));

return imageBean1;

}

++idx;

return getBingImage();

}

/**

* 获取上一张图片

*/

public MutableLiveData> getPreviousImage() {

if (idx < 1) {

imageBean1.setValue(new BaseData(null, "已经是第一张啦"));

return imageBean1;

}

--idx;

return getBingImage();

}

}

即使Repository模块看起来没有必要,它也有着重要的作用。它从应用程序的其余部分提取数据源。现在我们的ViewModel不知道数据是由NetUtil获取的,这意味着我们可以根据需要将其交换为其他实现。所以下一步就是创建对应的ViewModel

6.创建对应的ViewModel

public class DemoActivityViewModel extends AndroidViewModel {

private ImageRepository imageRepository ;

//存放从网络上获取的图片信息

private MutableLiveData> imageBean ;

public DemoActivityViewModel(@NonNull Application application) {

super(application);

imageRepository=new ImageRepository();

imageBean=new MutableLiveData<>();

}

public MutableLiveData> getImageBean() {

return imageBean;

}

/**

* 获取图片

*/

public void getImage() {

imageBean = imageRepository.getBingImage();

}

/**

* 获取下一张

*/

public void getNextImage() {

imageBean = imageRepository.getNextImage();

}

/**

* 获取上一张

*/

public void getPreviousImage() {

imageBean = imageRepository.getPreviousImage();

}

}

7.Activity内使用

public class DemoActivity extends AppCompatActivity {

private ActivityDemoBinding activityDemoBinding;

private DemoActivityViewModel demoActivityViewModel;

private ProgressDialog progressDialog;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

activityDemoBinding = DataBindingUtil.setContentView(this, R.layout.activity_demo);

demoActivityViewModel = ViewModelProviders.of(this).get(DemoActivityViewModel.class);

//绑定ViewModel

activityDemoBinding.setViewModel(demoActivityViewModel);

//绑定点击事件

activityDemoBinding.setEventListener(new OnEventListener());

progressDialog = new ProgressDialog(DemoActivity.this);

progressDialog.setMessage("加载中。。。。");

//获取第一张网络图片

demoActivityViewModel.getImage();

progressDialog.show();

demoActivityViewModel.getImageBean().observe(this, new Observer>() {

@Override

public void onChanged(BaseData imageBeanBaseData) {

if (imageBeanBaseData.getData() != null) {

//1.直接代码赋值

Glide.with(DemoActivity.this)

.load("https://www.bing.com" + imageBeanBaseData.getData().getImages().get(0).getUrl())

.into(activityDemoBinding.ivImg);

activityDemoBinding.tvContent.setText(imageBeanBaseData.getData().getImages().get(0).getCopyright());

//2.利用DataBinding直接赋值

activityDemoBinding.setImage(imageBeanBaseData.getData().getImages().get(0));

} else {

Toast.makeText(DemoActivity.this, imageBeanBaseData.getMessage(), Toast.LENGTH_SHORT).show();

}

progressDialog.dismiss();

}

});

}

public class OnEventListener {

public void onClick(View view) {

progressDialog.show();

switch (view.getId()) {

case R.id.tv_previous:

//获取上一张

demoActivityViewModel.getPreviousImage();

break;

case R.id.tv_next:

//获取下一张

demoActivityViewModel.getNextImage();

break;

default:

break;

}

}

}

}

与其对应的xml文件为:

xmlns:app="http://schemas.android.com/apk/res-auto"

xmlns:tools="http://schemas.android.com/tools">

name="viewModel"

type="com.example.myapplication.demo.DemoActivityViewModel" />

name="image"

type="com.example.myapplication.demo.ImageBean.ImagesBean" />

name="eventListener"

type="com.example.myapplication.demo.DemoActivity.OnEventListener" />

android:layout_width="match_parent"

android:layout_height="match_parent"

tools:context=".demo.DemoActivity">

android:id="@+id/tv"

android:layout_width="match_parent"

android:layout_height="50dp"

android:gravity="center"

android:text="Bing每日一图"

android:textColor="#000000"

app:layout_constraintBottom_toTopOf="@id/iv_img" />

android:id="@+id/iv_img"

android:layout_width="match_parent"

android:layout_height="200dp"

url="@{"https://www.bing.com"+image.url}" //此处需自定义BindingAdapter

app:layout_constraintTop_toBottomOf="@id/tv" />

android:id="@+id/tv_content"

android:layout_width="0dp"

android:layout_height="wrap_content"

android:layout_margin="15dp"

android:textColor="#000000"

android:textSize="15sp"

android:text="@{image.copyright}"

app:layout_constraintEnd_toEndOf="parent"

app:layout_constraintStart_toStartOf="parent"

app:layout_constraintTop_toBottomOf="@id/iv_img" />

android:id="@+id/tv_previous"

android:layout_width="0dp"

android:layout_height="50dp"

android:layout_marginStart="15dp"

android:layout_marginTop="15dp"

android:gravity="center"

android:text="上一张"

android:onClick="@{eventListener::onClick}"

app:layout_constraintEnd_toStartOf="@id/tv_next"

app:layout_constraintStart_toStartOf="parent"

app:layout_constraintTop_toBottomOf="@id/tv_content" />

android:id="@+id/tv_next"

android:layout_width="0dp"

android:layout_height="50dp"

android:layout_marginStart="15dp"

android:layout_marginTop="15dp"

android:layout_marginEnd="15dp"

android:gravity="center"

android:text="下一张"

android:onClick="@{eventListener::onClick}"

app:layout_constraintEnd_toEndOf="parent"

app:layout_constraintStart_toEndOf="@id/tv_previous"

app:layout_constraintTop_toBottomOf="@id/tv_content" />

在ImageView内自定义了一个url属性,此时需使用BindingAdapter去自定义实现,实现起来很简单:

public class DataBindingUtil {

@BindingAdapter(value = {"url"})

public static void loadImage(ImageView view, String url) {

Glide.with(view.getContext()).load(url).into(view);

}

}

至此一个很简单的MVVM架构的小demo就实现了。

推荐一个方便在github上阅读源码的谷歌浏览器插件:Sourcegraph。这个插件还支持搜索文件、代码等,反正比正常阅读要方便太多了。

效果.png

你可能感兴趣的:(android mvvm官方demo,Android mvvm架构demo(DataBinding+LiveData+ViewModel+ Repository))