您的位置:首页 >  新闻中心 > 云通讯公告
  云通讯公告
 

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