App 组件化/模块化—Android 框架组件
来源:原创 时间:2017-10-27 浏览:0 次面临越来越杂乱的 App 需求,Google 官方发布了Android 结构组件库(Android Architecture Components )。为开发者更好的开发 App 供给了十分好的样本。这个结构里的组件是合作 Android 组件生命周期的,所以它能够很好的躲避组件生命周期办理的问题。今日我们就来看看这个库的运用。
通用的结构原则
官方主张在架构 App 的时分遵从以下两个原则:
重视别离
其间前期开发 App 最常见的做法是在 Activity 或许 Fragment 中写了许多的逻辑代码,导致 Activity 或 Fragment 中的代码很臃肿,十分不易保护。现在许多 App 开发者都留意到了这个问题,所曾经两年 MVP 结构就十分有商场,现在普及率也很高。
模型驱动UI
模型耐久化的优点就是:即便体系回收了 App 的资源用户也不会丢掉数据,而且在网络不稳定的情况下 App 仍然能够正常地运转。然后确保了 App 的用户体会。
App 结构组件
结构供给了以下几个中心组件,我们将经过一个实例来阐明这几个组件的运用。
ViewModel
LiveData
Room
假定要完成一个用户信息展现页面。这个用户信息是经过REST API 从后台获取的。
树立UI
我们运用 fragment (UserProfileFragment.java) 来完成用户信息的展现页面。为了驱动 UI,我们的数据模型需求持有以下两个数据元素
用户ID: 用户的仅有标识。能够经过 fragment 的 arguments 参数进行传递这个信息。这样做的优点就是如果体系销毁了运用,这个参数会被保存而且下次从头启动时能够康复之前的数据。
用户目标数据:POJO 持有用户数据。
我们要创立 ViewModel 目标用于保存以上数据。
那什么是 ViewModel 呢?
A ViewModel provides the data for a specific UI component, such as a fragment or activity, and handles the communication with the business part of data handling, such as calling other components to load the data or forwarding user modifications. The ViewModel does not know about the View and is not affected by configuration changes such as recreating an activity due to rotation.
ViewModel 是一个结构组件。它为 UI 组件 (fragment或activity) 供给数据,而且能够调用其它组件加载数据或许转发用户指令。ViewModel 不会关怀 UI 长什么样,也不会遭到 UI 组件装备改动的影响,例如不会受旋转屏暗地 activity 从头启动的影响。因而它是一个与 UI 组件无关的。
public class UserProfileViewModel extends ViewModel {
private
String
userId;
private
User
user;
public
void
init(
String
userId) {
this
.userId = userId;
}
public
User
getUser() {
return
user;
}
}
public class UserProfileFragment extends LifecycleFragment {
private
static
final
String
UID_KEY =
"uid"
;
private
UserProfileViewModel
viewModel;
@Override
public
void
onActivityCreated(
@Nullable
Bundle
savedInstanceState) {
super
.onActivityCreated(savedInstanceState);
String
userId = getArguments().getString(UID_KEY);
viewModel =
ViewModelProviders
.of(
this
).get(
UserProfileViewModel
.
class
);
viewModel.init(userId);
}
@Override
public
View
onCreateView(
LayoutInflater
inflater,
@Nullable
ViewGroup
container,
@Nullable
Bundle
savedInstanceState) {
return
inflater.inflate(R.layout.user_profile, container,
false
);
}
}
需求的是:由于结构组件现在还处于预览版别,这儿 UserProfileFragment 是承继于 LifecycleFragment 而不是 Fragment。待正式发布版别之后 Android Support 包中的 Fragment 就会默许完成 LifecycleOwner 接口。而 LifecycleFragment 也是完成了 LifecycleOwner 接口的。即正式版别发布时 Support 包中的 UI 组件类就是支撑结构组件的。
现在现已有了 UI 组件和 ViewModel,那么我们怎么将它们进行衔接呢?这时分就需求用到 LiveData 组件了。
LiveData is an observable data holder. It lets the components in your app observe LiveDataobjects for changes without creating explicit and rigid dependency paths between them. LiveData also respects the lifecycle state of your app components (activities, fragments, services) and does the right thing to prevent object leaking so that your app does not consume more memory.
LiveData 的运用有点像 RxJava。因而完全能够运用 RxJava 来代替 LiveData 组件。
现在我们修正一下 UserProfileViewModel 类
public
class
UserProfileViewModel
extends
ViewModel
{
...
private
LiveData
<
User
> user;
public
LiveData
<
User
> getUser() {
return
user;
}
}
将 Useruser 替换成 LiveDatauser
然后再修正 UserProfileFragment 类中
@Override
public
void
onActivityCreated(
@Nullable
Bundle
savedInstanceState) {
super
.onActivityCreated(savedInstanceState);
viewModel.getUser().observe(
this
, user -> {
// update UI
});
}
当用户数据发作改动时,就会告诉 UI 进行更新。ViewModel 与 UI 组件的交互就是这么简略。
但仔细的朋友可能发现了:fragment 在 onActivityCreated 办法中添加了相应的监听,可是没有在其它对应的生命周期中移除监听。有经历的朋友就会觉得这是不是有可能会发作引证走漏问题呢?其实不然,LiveData 组件内部现已为开发者做了这些作业。即 LiveData 会再正确的生命周期进行回调。
获取数据
现在现已成功的把 ViewModel 与 UI 组件(fragment)进行了通讯。那么 ViewModel 又是怎么获取数据的呢?
假定我们的数据是经过REST API 从后天获取的。我们运用 Retrofit 库完成网络恳求。
以下是恳求网络接口 Webservice
public
interface
Webservice
{
/**
* @GET declares an HTTP GET request
* @Path("user") annotation on the userId parameter marks it as a
* replacement for the {user} placeholder in the @GET path
*/
@GET
(
"/users/{user}"
)
Call
<
User
> getUser(
@Path
(
"user"
)
String
userId);
}
ViewModel 能够引证 Webservice 接口,可是这样做违反了我们在上文说到的重视别离原则。由于我们引荐运用 Repository 模型对 Webservice 进行封装。
Repository modules are responsible for handling data operations. They provide a clean API to the rest of the app. They know where to get the data from and what API calls to make when data is updated. You can consider them as mediators between different data sources (persistent model, web service, cache, etc.).
关于 Repository 形式能够参阅我的上一篇《App 组件化/模块化之路——Repository形式》
以下是运用 Repository 封装 WebService
public
class
UserRepository
{
private
Webservice
webservice;
// ...
public
LiveData
<
User
> getUser(
int
userId) {
// This is not an optimal implementation, we'll fix it below
final
MutableLiveData
<
User
> data =
new
MutableLiveData
<>();
webservice.getUser(userId).enqueue(
new
Callback