Jetpack 是一个由多个库组成的套件,可帮助开发者遵循最佳做法、减少样板代码并编写可在各种 Android 版本和设备中一致运行的代码,让开发者可将精力集中于真正重要的编码工作。
Jetpack推出的主要目的是为了能够让开发者更加快速、方便以及高质量的完成产品开发
Life生命,cycle周期,顾名思义:Lifecycle是生命周期的意思。它是Jetpack中的一个 生命周期感知型组件 ,可执行操作来感知响应另一个组件(如 Activity 和 Fragment)的生命周期状态的变化。
LifeCycle可以帮助开发者创建可感知生命周期的组件。这样,组件便能够在其内部管理自己的生命周期,从而降低模块间的耦合度,并降低内存泄漏发生的可能性
举个例子,我们经常需要在页面的onCreate()方法中对组件进行初始化,在onPause()方法中停止组件,而在页面的onDestroy()方法中对组件进行资源回收工作。这样的工作非常烦琐,会让页面与组件之间的耦合度变高。但这些工作又不得不做,因为这可能会引发内存泄漏。
①导入依赖(这里直接去官网看最新的版本导入就可以了) 这里给出一些,按需选择,并不是全部都需要的
dependencies {
def lifecycle_version = "2.2.0"
def arch_version = "2.1.0"
// ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"
// LiveData
implementation "androidx.lifecycle:lifecycle-livedata:$lifecycle_version"
// 只有Lifecycles (不带 ViewModel or LiveData)
implementation "androidx.lifecycle:lifecycle-runtime:$lifecycle_version"
// Saved state module for ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifecycle_version"
// lifecycle注解处理器
annotationProcessor "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"
// 替换 - 如果使用Java8,就用这个替换上面的lifecycle-compiler
implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
//以下按需引入
// 可选 - 帮助实现Service的LifecycleOwner
implementation "androidx.lifecycle:lifecycle-service:$lifecycle_version"
// 可选 - ProcessLifecycleOwner给整个 app进程 提供一个lifecycle
implementation "androidx.lifecycle:lifecycle-process:$lifecycle_version"
// 可选 - ReactiveStreams support for LiveData
implementation "androidx.lifecycle:lifecycle-reactivestreams:$lifecycle_version"
// 可选 - Test helpers for LiveData
testImplementation "androidx.arch.core:core-testing:$arch_version"
}
②创建一个类实现LifecycleOwner:
public class MyLocationListener implements LifecycleObserver {
public MyLocationListener(Activity context, OnLocationChangeListener listener) {
//初始化操作
iniLocationManager();
}
private void iniLocationManager() {
}
//当Activity执行onResume()方法时,该方法会被自动调用
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
private void startGetLocation(){
Log.e("true","onResume"+"被调用了");
}
//当Activity执行onPause()方法时,该方法会被自动调用
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
private void stopGetLocation(){
Log.e("true","onPause"+"被调用了");
}
//当Activity执行onDestroy()方法时,该方法会被自动调用
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
private void delGetLocation(){
Log.e("true","onDestroy"+"被调用了");
}
//当地理位置发送改变时,通过该接口通知调用者
public interface OnLocationChangeListener{
void onChanged(double latitude,double longitude);
}
}
按照需求通过注解的方式来实现方法的调用。
③在需要被观察的activity或者fragment中添加Lifecycle对象,并且添加observer。 主MainActivity 在MainActivity中,只需要引用MyLocationListener即可,不用再关心Activity生命周期变化对该组件所带来的影响。生命周期的管理完全交给MyLocationListener内部自行处理。在Activity中要做的只是通过getLifecycle().addObserver()方法,将观察者与被观察者绑定起来,代码如下:
public class MainActivity extends AppCompatActivity {
private MyLocationListener myLocationListener;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myLocationListener = new MyLocationListener(this, new MyLocationListener.OnLocationChangeListener() {
@Override
public void onChanged(double latitude, double longitude) {
//展示收到的位置信息
}
});
//将观察者与被观察者绑定
getLifecycle().addObserver(myLocationListener);
}
}
ViewModel是Jetpack AAC的重要组件,同时也有一个同名抽象类。 ViewModel,意为 视图模型,即为界面准备数据的模型。简单理解就是,ViewModel为UI层提供数据。
①思路:
举个例子,如果您需要在Activity中显示用户信息,那么需要将获取用户信息的操作分放到ViewModel中,代码如下:
public class UserViewModel extends ViewModel {
private MutableLiveData userLiveData ;
private MutableLiveData loadingLiveData;
public UserViewModel() {
userLiveData = new MutableLiveData<>();
loadingLiveData = new MutableLiveData<>();
}
//获取用户信息,假装网络请求 2s后 返回用户信息
public void getUserInfo() {
loadingLiveData.setValue(true);
new AsyncTask() {
@Override
protected void onPostExecute(String s) {
loadingLiveData.setValue(false);
userLiveData.setValue(s);//抛出用户信息
}
@Override
protected String doInBackground(Void... voids) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
String userName = "AAAAAABBBBBBBBBBBBCCCCCCCCC";
return userName;
}
}.execute();
}
public LiveData getUserLiveData() {
return userLiveData;
}
public LiveData getLoadingLiveData() {
return loadingLiveData;
}
}
UserViewModel继承ViewModel,然后逻辑很简单:假装网络请求 2s后 返回用户信息,其中userLiveData用于抛出用户信息,loadingLiveData用于控制进度条显示。
再看UI层:
public class UserActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
Log.i(TAG, "onCreate: ");
TextView tvUserName = findViewById(R.id.textView);
ProgressBar pbLoading = findViewById(R.id.pb_loading);
//获取ViewModel实例
ViewModelProvider viewModelProvider = new ViewModelProvider(this);
UserViewModel userViewModel = viewModelProvider.get(UserViewModel.class);
//观察 用户信息
userViewModel.getUserLiveData().observe(this, new Observer() {
@Override
public void onChanged(String s) {
// update ui.
tvUserName.setText(s);
}
});
userViewModel.getLoadingLiveData().observe(this, new Observer() {
@Override
public void onChanged(Boolean aBoolean) {
pbLoading.setVisibility(aBoolean?View.VISIBLE:View.GONE);
}
});
//点击按钮获取用户信息
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
userViewModel.getUserInfo();
}
});
}
@Override
protected void onStop() {
super.onStop();
Log.i(TAG, "onStop: ");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.i(TAG, "onDestroy: ");
}
}
页面有个按钮用于点击获取用户信息,有个TextView展示用户信息。 在onCreate()中先 创建ViewModelProvider实例,传入的参数是ViewModelStoreOwner,Activity和Fragment都是其实现。然后通过ViewModelProvider的get方法 获取ViewModel实例,然后就是 观察ViewModel中的LiveData。
②总结:
LiveData是Jetpack提供的一种响应式编程组件,它可以包含任何类型的数据,并在数据发生变化的时候通知给观察者,适合与ViewModel结合在一起使用,就可以让ViewModel将数据的变化主动通知给Activity。
在开发中我们比较常用的就是 MutableLiveData ,他给我们暴露好了修改对应值的方法,LiveData的作者认为我们有这个功能就够了。
public class MutableLiveData extends LiveData {
public MutableLiveData(T value) {
super(value);
}
public MutableLiveData() {
super();
}
// 在子线程 中 更改数据 就需要用到postValue方法
@Override
public void postValue(T value) {
super.postValue(value);
}
@Override
public void setValue(T value) {
super.setValue(value);
}
}
一个简单的 使用MutableLiveData的实例
class LiveDataTestActivity : AppCompatActivity() {
val TAG = "LiveDataTestActivity"
var index = 1
val liveData:MutableLiveData by lazy {
MutableLiveData().also {
it.value = "周杰伦"
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
var binding = ActivityLiveDataTestBinding.inflate(layoutInflater)
setContentView(binding.root)
liveData.observe(this){
Log.e(TAG,it)
}
}
fun changeLivaData(view: View) {
liveData.value = "周杰伦${index++}"
}
}
首先调用liveData.observe注册一个观察者,观察者注册商后,用户点击xml上的按钮,liveData 会调用setValue方法(因为是kotlin省略了set) 然后在observe的回调中会打印对应的值,那么我们看看这个最终是怎么通知观察者 回调的呢。liveData调用了setValue方法,最后是调到Super了,也就是LiveData中的setValue方法。
DataBinding 是 Google 在 Jetpack 中推出的一款数据绑定的支持库,他的目的是一个帮助我们实现数据和UI绑定,并可以进行双向绑定。
实例化布局文件了,我们删除掉传统的setContentView(),通过 DataBindingUtil.setContentView()来实例化文件。实例化返回的布局文件对象,名字和布局文字名字一致,遵循大驼峰命名规则,后面加上Binding。然后通过binding对象得到控件,控件命名遵循小驼峰规则。
ActivityMainBinding binding=DataBindingUtil.setContentView(this,R.layout.activity_main);
binding.textHome.setText("hello databinding!");
如何将数据传递到布局文件中呢?首先,在布局文件中定义布局变量,指定对象的名字和类型,当然数据的操作在标签里。data标签里用于放在布局文件中各个UI控件所需要的数据,这些数据类型可以是自定义类型,也可以是基本类型。
public class Book {
private int id;
private String title;
private String author;
}
有时我们需要在布局文件中引入一些Java工具类或静态类,处理一些简单的逻辑在布局中,我们可以使用标签导入。使用alias,当类名有冲突时,其中一个类可使用别名重命名。默认导入java.lang.*
;
布局中的数据绑定使用“@{}”语法写入属性中,通过布局表达式的形式设置TextView的text。
DataBinding为了方便使用,对布局变量提供了Setter类,因此,在Activity中,通过setBook(),将Book对象传递给布局变量。
Book book = new Book(0, "android", "yhj");
//BR类似于Android中的R类,由DataBinding自动生成,用于存放所有布局变量的id。
//DataBinding为了方便使用提供了Setter类,直接使用setXxx()
//binding.setVariable(BR.book,book);
binding.setBook(book);
绑定后,就不需要再Activity中设置内容了,实现了布局与页面的解耦。 DataBinding具有Null校验,如果绑定值为null,则分配默认值null,如果类型为int,默认值为0。
本文主要讲了在Android jetpack中的重要组件,更多的jetpack技术请参考《jetpack技术与Android架构精讲》点击可查看详细类目。
在我们工作中,可维护、可扩展、可测试和可重用的业务架构对于提高应用程序的质量和效率意义非凡,而JetPack是帮助开发者快速地组织和管理应用程序的代码的工具包。希望这篇文章能够让大家了解到jetpack的重要性