https://developer.android.google.cn/topic/libraries/architecture/lifecycle#kotlin
DataSource DataSourceFactory LiveData ViewModel
Building MVP apps: MVP Part I(MVP官网方法) ->http://www.gwtproject.org/articles/mvp-architecture.html#presenter
Android Jetpack LiveData解析 ->https://www.jianshu.com/p/b04abbb766e0
Android Jetpack->https://developer.android.google.cn/jetpack
androidx.lifecycle 软件包提供了可用于构建生命周期感知型组件的类和接口 - 这些组件可以根据 Activity 或 Fragment 的当前生命周期状态自动调整其行为。
使用生命周期感知型组件处理生命周期
lifecycle
类可以通过向其方法添加注解来监控组件的生命周期状态。然后,您可以通过调用 Lifecycle 类的 addObserver() 方法并传递观察者的实例来添加观察者,如以下示例中所示:
class MyObserver : LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
fun connectListener() {
...
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
fun disconnectListener() {
...
}
}
myLifecycleOwner.getLifecycle().addObserver(MyObserver())
LifecycleObserver connectListener disconnectListener
Lifecycle.Event.ON_RESUME Lifecycle.Event.ON_PAUSE
myLifecycleOwner.getLifecycle.addObserver(MyObserver)
ProcessLifecycleOwner
Public methods
static LifecycleOwner get()
The LifecycleOwner for the whole application process.
Lifecycle getLifecycle()
Returns the Lifecycle of the provider.
LifecycleOwner Lifecycle
@OnLifecycleEvent(Lifecycle.Event.ON_START)
fun start() {
if (enabled) {
// connect
}
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun stop() {
// disconnect if connected
}
OnLifecycleEvent(Lifecycle.Event.ON_START)
OnLifecycleEvent(Lifecycle.Event.ON_STOP)
NavController controller = Navigation.findNavController(v);
controller.navigate(R.id.action_testHomeFragment_to_testDetailFragment);
Navigation graph中直接设置转换动画,极大减少了工作量。当然如果对自带动画效果不满意,也可以创建Animation资源自己编写xml文件来创建动画。
NavHost:一个容器,用于显示
NavController:控制跳转流程
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_begin="335dp"
app:layout_constraintGuide_percent="0.5" />
getView().findViewById(R.id.button2).setOnClickListener(Navigation.createNavigateOnClickListener(R.id.action_testDetailFragment_to_testHomeFragment));
NavController controller = Navigation.findNavController(v);
controller.navigate(R.id.action_testHomeFragment_to_testDetailFragment);
NavHostFragment
public class NavHostFragment extends Fragment implements NavHost {
public interface NavHost {
clazz = Class.forName(name, true, context.getClassLoader());
Class.forName
public static final class Builder {
public Builder() {
}
@NonNull
public Builder setLaunchSingleTop(boolean singleTop) {
mSingleTop = singleTop;
return this;
}
@NonNull
public NavOptions build() {
return new NavOptions(mSingleTop, mPopUpTo, mPopUpToInclusive,
mEnterAnim, mExitAnim, mPopEnterAnim, mPopExitAnim);
}
Builder.build
NavAction NavArgument NavOptions
Method valueMethod = clazz.getDeclaredMethod("values");
clazz.getDeclaredMethod
NavArgument
A annotation = getDeclaredAnnotation(annotationClass);
getDeclaredAnnotation
public class NavController {
class NavControllerViewModel extends ViewModel {
NavControllerViewModel
ViewModel
NavControllerViewModel
@NonNull
static NavControllerViewModel getInstance(ViewModelStore viewModelStore) {
ViewModelProvider viewModelProvider = new ViewModelProvider(viewModelStore, FACTORY);
return viewModelProvider.get(NavControllerViewModel.class);
}
private static final ViewModelProvider.Factory FACTORY = new ViewModelProvider.Factory() {
@NonNull
@Override
@SuppressWarnings("unchecked")
public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
NavControllerViewModel viewModel = new NavControllerViewModel();
return (T) viewModel;
}
};
public class ViewModelProvider {
public interface Factory {
@NonNull
<T extends ViewModel> T create(@NonNull Class<T> modelClass);
}
}
abstract static class KeyedFactory implements Factory {
@NonNull
@Override
public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
throw new UnsupportedOperationException("create(String, Class<?>) must be called on "
+ "implementaions of KeyedFactory");
}
}
public ViewModelProvider(@NonNull ViewModelStore store, @NonNull Factory factory) {
mFactory = factory;
}
public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
viewModel = ((KeyedFactory) (mFactory)).create(key, modelClass);
}
使用 Room 引用复杂数据
Room 提供了在基元类型和盒装类型之间进行转换的功能,但不允许在实体之间进行对象引用。本文档介绍了如何使用类型转换器,以及 Room 为何不支持对象引用。
使用类型转换器
有时,您的应用需要使用自定义数据类型,其中包含您想要存储到单个数据库列中的值。如需为自定义类型添加此类支持,您需要提供一个 TypeConverter
,它可以在自定义类与 Room 可以保留的已知类型之间来回转换。
例如,如需保留 Date
的实例,可以编写以下 TypeConverter
将等效的 Unix 时间戳存储在数据库中:
class Converters {
@TypeConverter
fun fromTimestamp(value: Long?): Date? {
return value?.let { Date(it) }
}
@TypeConverter
fun dateToTimestamp(date: Date?): Long? {
return date?.time?.toLong()
}
}
前面的示例定义了 2 个函数,一个用于将 Date
对象转换为 Long
对象,另一个用于执行从 Long
到 Date
的反向转换。由于 Room 已经知道如何保留 Long
对象,因此可以使用此转换器保留 Date
类型的值。
接下来,将 @TypeConverters
注释添加到 AppDatabase
类中,以便 Room 可以使用您为该 AppDatabase
中的每个实体和 DAO 定义的转换器:
AppDatabase
@Database(entities = arrayOf(User::class), version = 1)
@TypeConverters(Converters::class)
abstract class AppDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
}
通过使用这些转换器,您就可以在其他查询中使用自定义类型,就像使用基元类型一样,如以下代码段所示:
User
@Entity
data class User(private val birthday: Date?)
UserDao
@Dao
interface UserDao {
@Query("SELECT * FROM user WHERE birthday BETWEEN :from AND :to")
fun findUsersBornBetweenDates(from: Date, to: Date): List<User>
}
您还可以将 @TypeConverters
限制为不同的范围,包括个别实体、DAO 和 DAO 方法。如需了解详情,请参阅 @TypeConverters
注释的参考文档。
了解 Room 为何不允许对象引用
Android DataBinding原理分析
深入Android databinding的使用和原理分析
DataSource DataSourceFactory LiveData ViewModel
Building MVP apps: MVP Part I(MVP官网方法) ->http://www.gwtproject.org/articles/mvp-architecture.html#presenter
Android Jetpack LiveData解析 ->https://www.jianshu.com/p/b04abbb766e0
Android Jetpack->https://developer.android.google.cn/jetpack
androidx.lifecycle 软件包提供了可用于构建生命周期感知型组件的类和接口 - 这些组件可以根据 Activity 或 Fragment 的当前生命周期状态自动调整其行为。
使用生命周期感知型组件处理生命周期
lifecycle
类可以通过向其方法添加注解来监控组件的生命周期状态。然后,您可以通过调用 Lifecycle 类的 addObserver() 方法并传递观察者的实例来添加观察者,如以下示例中所示:
class MyObserver : LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
fun connectListener() {
...
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
fun disconnectListener() {
...
}
}
myLifecycleOwner.getLifecycle().addObserver(MyObserver())
LifecycleObserver connectListener disconnectListener
Lifecycle.Event.ON_RESUME Lifecycle.Event.ON_PAUSE
myLifecycleOwner.getLifecycle.addObserver(MyObserver)
ProcessLifecycleOwner
Public methods
static LifecycleOwner get()
The LifecycleOwner for the whole application process.
Lifecycle getLifecycle()
Returns the Lifecycle of the provider.
LifecycleOwner Lifecycle
@OnLifecycleEvent(Lifecycle.Event.ON_START)
fun start() {
if (enabled) {
// connect
}
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun stop() {
// disconnect if connected
}
OnLifecycleEvent(Lifecycle.Event.ON_START)
OnLifecycleEvent(Lifecycle.Event.ON_STOP)
LiveData 是一种可观察的数据存储器类。与常规的可观察类不同,LiveData 具有生命周期感知能力,意指它遵循其他应用组件(如 Activity、Fragment 或 Service)的生命周期。这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者。
请确保用于更新界面的 LiveData 对象存储在 ViewModel 对象中,
public class NameActivity extends AppCompatActivity {
private NameViewModel model;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Other code to setup the activity...
// Get the ViewModel.
model = new ViewModelProvider(this).get(NameViewModel.class);
// Create the observer which updates the UI.
final Observer<String> nameObserver = new Observer<String>() {
@Override
public void onChanged(@Nullable final String newName) {
// Update the UI, in this case, a TextView.
nameTextView.setText(newName);
}
};
// Observe the LiveData, passing in this activity as the LifecycleOwner and the observer.
model.getCurrentName().observe(this, nameObserver);
}
}
ViewModelProvider .get NameViewModel
Observer nameObserver = new Observer
model.getCurrentName.observe this, nameObserver
public class NameViewModel extends ViewModel {
注意:您必须调用 setValue(T) 方法以从主线程更新 LiveData 对象。如果在 worker 线程中执行代码,则您可以改用 postValue(T) 方法来更新 LiveData 对象。
public class ConcertViewModel extends ViewModel {
private ConcertDao concertDao;
public final LiveData<PagedList<Concert>> concertList;
// Creates a PagedList object with 50 items per page.
public ConcertViewModel(ConcertDao concertDao) {
this.concertDao = concertDao;
concertList = new LivePagedListBuilder<>(
concertDao.concertsByDate(), 50).build();
}
}
ViewModel LiveData <PagedList>
ConcertViewModel LivePagedListBuilder
要显示来自后端服务器的数据,请使用同步版本的 Retrofit API,将信息加载到您自己的自定义 DataSource 对象中
网络和数据库
在开始观察数据库之后,您可以使用 PagedList.BoundaryCallback 监听数据库中的数据何时耗尽。然后,您可以从网络中获取更多项目并将它们插入到数据库中。如果界面正在观察数据库,则您只需执行此操作即可。
PagedList.BoundaryCallback
使用 CursorAdapter 将数据光标与列表视图相关联
您的应用可能会使用 CursorAdapter 将 Cursor 的数据与 ListView 相关联。在这种情况下,您通常需要从 ListView 迁移到 RecyclerView,以后者作为应用的列表界面容器,然后将 Cursor 组件替换为 Room 或 PositionalDataSource,具体取决于 Cursor 实例是否会访问 SQLite 数据库。
CursorAdapter Cursor ListView RecyclerView,以后者作为应用的列表界面容器,然后将
@Dao
public interface ConcertDao {
// The Integer type parameter tells Room to use a PositionalDataSource
// object, with position-based loading under the hood.
@Query("SELECT * FROM concerts ORDER BY date DESC")
DataSource.Factory<Integer, Concert> concertsByDate();
}
public class ConcertViewModel extends ViewModel {
private ConcertDao concertDao;
public final LiveData<PagedList<Concert>> concertList;
public ConcertViewModel(ConcertDao concertDao) {
this.concertDao = concertDao;
concertList = new LivePagedListBuilder<>(
concertDao.concertsByDate(), /* page size */ 50).build();
}
}
public class ConcertActivity extends AppCompatActivity {
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ConcertViewModel viewModel =
new ViewModelProvider(this).get(ConcertViewModel.class);
RecyclerView recyclerView = findViewById(R.id.concert_list);
ConcertAdapter adapter = new ConcertAdapter();
viewModel.concertList.observe(this, adapter::submitList);
recyclerView.setAdapter(adapter);
}
}
public class ConcertAdapter
extends PagedListAdapter<Concert, ConcertViewHolder> {
protected ConcertAdapter() {
super(DIFF_CALLBACK);
}
@Override
public void onBindViewHolder(@NonNull ConcertViewHolder holder,
int position) {
Concert concert = getItem(position);
if (concert != null) {
holder.bindTo(concert);
} else {
// Null defines a placeholder item - PagedListAdapter automatically
// invalidates this row when the actual object is loaded from the
// database.
holder.clear();
}
}
private static DiffUtil.ItemCallback<Concert> DIFF_CALLBACK =
new DiffUtil.ItemCallback<Concert>() {
// Concert details may have changed if reloaded from the database,
// but ID is fixed.
@Override
public boolean areItemsTheSame(Concert oldConcert, Concert newConcert) {
return oldConcert.getId() == newConcert.getId();
}
@Override
public boolean areContentsTheSame(Concert oldConcert,
Concert newConcert) {
return oldConcert.equals(newConcert);
}
};
}
使用 LiveData 观察分页数据
DataSource.Factory <Integer, Concert> concert
ViewModel
LiveData<PagedList<Concert>>
LivePagedListBuilder
ConcertViewModel ViewModelProvider .get ConcertViewModel.class
ConcertAdapter
viewModel.concertList.observe adapter.submitList
PagedListAdapter <ConcertViewHolder>
DIFF_CALLBACK
onBindViewHolder
holder.bindTo
holder.clear
DiffUtil.ItemCallback DIFF_CALLBACK
DiffUtil.ItemCallback
areContentsTheSame
areContentsTheSame
使用 RxJava2 观察分页数据
如果您倾向于使用 RxJava2 而不是 LiveData,则可以改为创建 Observable 或 Flowable 对象:
public class ConcertActivity extends AppCompatActivity {
private ConcertAdapter adapter = new ConcertAdapter();
private ConcertViewModel viewModel;
private CompositeDisposable disposable = new CompositeDisposable();
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
RecyclerView recyclerView = findViewById(R.id.concert_list);
viewModel = new ViewModelProvider(this).get(ConcertViewModel.class);
recyclerView.setAdapter(adapter);
}
@Override
protected void onStart() {
super.onStart();
disposable.add(viewModel.concertList
.subscribe(adapter.submitList(flowableList)
));
}
@Override
protected void onStop() {
super.onStop();
disposable.clear();
}
}
CompositeDisposable disposable CompositeDisposable
disposable.add viewModel.concertList .subscribe
adapter.submitList flowableList
disposable.clear
class MyActivity extends AppCompatActivity {
private MyLocationListener myLocationListener;
public void onCreate(...) {
myLocationListener = new MyLocationListener(this, location -> {
// update UI
});
}
@Override
public void onStart() {
super.onStart();
Util.checkUserStatus(result -> {
// what if this callback is invoked AFTER activity is stopped?
if (result) {
myLocationListener.start();
}
});
}
@Override
public void onStop() {
super.onStop();
myLocationListener.stop();
}
}
Lifecycle 是一个类,用于存储有关组件(如 Activity 或 Fragment)的生命周期状态的信息,并允许其他对象观察此状态。
Lifecycle 使用两种主要枚举跟踪其关联组件的生命周期状态:
Lifecycle
public class MyObserver implements LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
public void connectListener() {
...
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
public void disconnectListener() {
...
}
}
myLifecycleOwner.getLifecycle().addObserver(new MyObserver());
MyObserver LifecycleObserver
connectListener disconnectListener
myLifecycleOwner.getLifecycle.addObserver new MyObserver
LifecycleObserver
start
enabled
OnLifecycleEvent Lifecycle.Event.ONS
stop
public class MyActivity extends Activity implements LifecycleOwner {
private LifecycleRegistry lifecycleRegistry;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
lifecycleRegistry = new LifecycleRegistry(this);
lifecycleRegistry.markState(Lifecycle.State.CREATED);
}
@Override
public void onStart() {
super.onStart();
lifecycleRegistry.markState(Lifecycle.State.STARTED);
}
@NonNull
@Override
public Lifecycle getLifecycle() {
return lifecycleRegistry;
}
}
LifecycleOwner lifecycleRegistry = LifecycleRegistry
lifecycleRegistry.markState Lifecycle.State.CREATED
onStart
getLifecycle
LiveData 没有公开可用的方法来更新存储的数据。MutableLiveData 类将公开 setValue(T) 和 postValue(T) 方法,如果您需要修改存储在 LiveData 对象中的值,则必须使用这些方法。通常情况下会在 ViewModel 中使用 MutableLiveData,然后 ViewModel 只会向观察者公开不可变的 LiveData 对象。
MutableLiveData setValue
LiveData ViewModel
model getCurrentName setValue
onChanged
LiveData
@Override
protected void onActive() {
@Override
protected void onInactive() {
public class MyFragment extends Fragment {
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
LiveData<BigDecimal> myPriceListener = ...;
myPriceListener.observe(getViewLifeycleOwner(), price -> {
// Update the UI.
});
}
}
LiveData
.observe getViewLifeycleOwner,price-> {
LiveData<User> userLiveData = ...;
LiveData<String> userName = Transformations.map(userLiveData, user -> {
user.name + " " + user.lastName
});
LiveData Transformations.map
userLiveData,user
Transformations.switchMap
class MyViewModel extends ViewModel {
private final PostalCodeRepository repository;
private final MutableLiveData<String> addressInput = new MutableLiveData();
public final LiveData<String> postalCode =
Transformations.switchMap(addressInput, (address) -> {
return repository.getPostCode(address);
});
public MyViewModel(PostalCodeRepository repository) {
this.repository = repository
}
private void setInput(String address) {
addressInput.setValue(address);
}
}
MyViewModel ViewModel
MutableLiveData
LiveData Transformations.switchMap
addressInput
repository.getPostCode
addressInput.setValue
架构组件为界面控制器提供了 ViewModel 辅助程序类,该类负责为界面准备数据。
public class MyViewModel extends ViewModel {
private MutableLiveData<List<User>> users;
public LiveData<List<User>> getUsers() {
if (users == null) {
users = new MutableLiveData<List<User>>();
loadUsers();
}
return users;
}
private void loadUsers() {
// Do an asynchronous operation to fetch users.
}
}
MyViewModel ViewModel
MutableLiveData List
LiveData List User
ViewModel 对象存在的时间比视图或 LifecycleOwners 的特定实例存在的时间更长
LifecycleObservers LiveData
ViewModel 对象存在的时间范围是获取 ViewModel 时传递给 ViewModelProvider 的 Lifecycle。ViewModel 将一
CursorLoader 等加载器类经常用于使应用界面中的数据与数据库保持同步
CursorAdapter
ViewModelProvider
UI Controller ViewModel LiveData LiveData
DataSource