什么是Android Jetpack
Android Jetpack是下一代组件和工具,以及旨在加速Android开发的架构指南。 主要原因是:
- 构建高质量,强大的应用程序
- 消除样板代码
- 加快发展
Architecture Components(架构组件)
-
Room
- 使用对象映射技术访问流畅的SQLite数据库。
-
Need(需求):
- 更少的模板代码。即,将数据作为对象而不是作为内容值发送到SQLite数据库,并将执行查询的结果作为对象返回为游标。
- 编译SQLite查询的时间验证。
- 支持Live Data和RxJava等观察
- 使用Annotations实现其功能,使API简单易用。
-
Annotations(注解):
- @Entity:定义数据库表的模式。
- @dao:代表数据库访问对象,用于对数据库执行读取或写入操作
- @database:作为数据库持有人。 根据提供的条件创建新数据库,如果已存在,则建立与预先存在的数据库的连接。
-
Code(代码):
-
@Entity:
@Entity(tableName = "word_table") public class Word { @PrimaryKey @NonNull @ColumnInfo(name = "word") private String mWord; public Word(String word) {this.mWord = word;} public String getWord(){return this.mWord;} }
- Room应该可以访问Entity类的成员变量,它应该能够设置或重置或更新存储在成员变量中的值,因此注意虽然成员变量被声明为private,但是有一个公共构造函数, getter访问成员变量。
-
@dao:
请注意,Dao应该是abstract class或interface。 其余的是自我解释的,如前所述,在这种情况下,从数据库中查询会返回一个对象列表。例如,List<Word> and no a Cursor.。@Dao public interface WordDao { @Insert void insert(Word word); @Query("DELETE FROM word_table") void deleteAll(); @Query("SELECT * from word_table ORDER BY word ASC") List<Word> getAllWords(); }
- 如果用
LiveData <List <Word >>
替换List <Word>
那么它恰好会为数据库中的每个更改返回一个更新的对象列表。 这是LiveData的主要原则之一 -
@database:
请注意,这必须是抽象的并扩展类RoomDatabase。 实体包含必须在数据库中创建的数据库表,并且@doa应该有一个抽象的getter方法@Database(entities = {Word.class}, version = 1) public abstract class WordRoomDatabase extends RoomDatabase { public abstract WordDao wordDao(); }
-
Database Connection(数据库连接):
这里,WordRoomDatabase db = Room.databaseBuilder( context.getApplicationContext(), WordRoomDatabase.class, "word_database") .fallbackToDistructiveMigration() .build();
.fallbackToDistructiveMigration()
是一个可选属性,表示数据库模式是否已更改,清除当前现有数据库中存在的所有数据。创建数据库的多个实例是昂贵的,不推荐使用,因此将其保留为单例(它只能有一个类的实例)可以派上用场。 -
Additional Hints(附加提示)
- 使用
@PrimayKey(autoGenerate = true)
自动生成主键,它通常应用于整数值,因此从1开始并保持自身递增。 - 要将成员变量的值传递给查询,请使用
:
例如:@Query("SELECT * from word_table ORDER BY word LIKE :current_word")
- 创建并使用Repository类来处理数据操作。 您可以处理自定义逻辑,例如,如果您从网络获取数据但没有与Internet的现有连接,则您必须获取并显示缓存的数据或来自dao。
- 使用
-
@Entity:
-
ViewModel
- 以生命周期意识的方式管理与UI相关的数据。
- 由于它在配置更改后仍然存在,因此有可能取代AsyncTask Loaders。
-
Need:
- UI与Data的高度分离。
- 没有责任太多的重大活动。
- UI控制器显示数据。
- ViewModel保存UI数据。
- Reason:
- 假设你的某个实例有一个具有多个UI元素的Activity,并且会根据用户输入更新状态,现在当设备进行配置更改时,数据将因为重新创建活动而丢失。 配置改变。当然,你可以利用
onSavedInstanceState()
但是忘记单个字段会导致应用程序出现不一致,这里是ViewModel
进入智能播放的地方。 - 在ViewModel中,由于UI数据与活动生命周期分离,因此它可以超越配置更改对数据所产生的影响。 因此,在重新创建活动之后,可以从ViewModel获取UI数据以分别更新UI。
-
Representation:
-
Code:
- 从
ViewModel
或AndroidViewModel
扩展public class MyViewModel extends ViewModel { // Should contain all the UI Data (As LiveData if possible) // Getters and Setters }
- 将
ViewModel
链接到Activitypublic class MyActivity extends AppCompatActivity { public void onCreate(Bundle savedInstanceState) { // Create a ViewModel the first time the system calls an activity's onCreate() method. // Re-created activities receive the same MyViewModel instance created by the first activity. // ViewModelProvider provides ViewModel for a given lifecycle scope. MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class); model.getUsers().observe(this, users -> { // update UI }); } }
- 重要的提示:
-
View Model
可以存活:- 配置更改
-
View Model
无法生存:- 按返回,例如:销毁活动。
- 通过多任务处理活动。
-
View Model
不能替代:- 坚持
- 在保存的实例状态
- 用
Activity lifecycle
替代App lifecycle
-
- 从
-
LiveData
在基础数据库更改时通知视图
-
Need(需要):
- 反应性UI。
- 仅在到达
onStart()
和onResume()
时更新。 - 自动清理自己。
- 允许与数据库通信到UI而不知道它。
-
Representation(表示):
-
Code:
- 使用
MutableLiveData <String>
可以使String
成为可能的LiveData - 要使用来自实时数据的实时数据更新UI,我们可以使用类似于观察者模式的模式。
mModel.getCurrentName().observe(this, new Observer<String>() { @Override public void onChanged(@Nullable final String newName) { // Update the UI, in this case, a TextView. mTextView.setText(newName); } });
- 使用
这里,
mModel
是ViewModel
实例,并假设getCurrentName()
返回一个MutableLiveData <String>
,并在其上设置观察者,当MutableLiveData
中的数据发生变化时,会调用onChanged()
。-
Arguments:
-
this
: 指定它具有工作的活动 .例如:LifeCycleOwner - 'Observer<type>' : type 取决于实时数据的返回类型。
-
-
Lifecycles
-
Terms:
- Lifecycle:定义Android生命周期的对象。
- Lifecycle Owner:这是一个界面:
- Lifecycle Observer: 观察Lifecycle Owner。
-
Code:
- 假设我们想要一个必须知道生命周期的监听器:
public class MyObserver implements LifecycleObserver { @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) public void connectListener() { ... } @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE) public void disconnectListener() { ... } } lifecycleOwner.getLifecycle().addObserver(new MyObserver());
- 现在根据Activity或Fragment的当前状态执行操作。
public class MyObserver implements LifecycleObserver { public void enable(){ enable = true; if(lifecycle.getState().isAtleast(STARTED)){ // action after onStart is reached } }
- 假设我们想要一个必须知道生命周期的监听器:
-
Important Note(重要的提示):
- 最初Lifecycle Library保持可选,但现在它已经成为Android开发的基础部分,AppCompatActivity和Fragment类继承了Lifecycle Library的开箱即用。
class AppCompatActivity : LifecycleOwner class Fragment : LifecycleOwner
- 最初Lifecycle Library保持可选,但现在它已经成为Android开发的基础部分,AppCompatActivity和Fragment类继承了Lifecycle Library的开箱即用。
-
Terms:
-
Data Binding
声明性地将可观察数据绑定到UI元素。
它是一种经过验证的无样板UI解决方案。
-
Code:
data class User(val name: String, ... )
<layout> <data> <variable name="user" type="User"/> </data> <TextView android:text="@{user.name}"/> </layout>
- 这里的代码是自我解释器,考虑到你在Kotlin中有一个
data class
数据类,它有许多字段,这些字段具有必须在UI中更新的实时数据,然后它可以直接在XML文档中解析。 UI通过创建适当的变量来访问数据类,如上所示。
- 这里的代码是自我解释器,考虑到你在Kotlin中有一个
Important Note(重要的提示):
它们具有对LiveData的本机支持,因此可以使用类似于上面显示的实例的LiveData。
-
但这还不足以观察它,因为数据绑定没有生命周期。 这可以通过在创建绑定实例时添加LifecycleOwner来修复。
binding.setLifecycleOwner(lifecycleOwner)
这有助于使用LiveData使UI中的数据保持最新。
-
Paging
- 逐渐从您的数据源按需加载信息。
- 换句话说,延迟加载Recycler View。
-
Need
- 方便
- 多层
- 表现
- 了解生命周期
- 灵活的不同背景API和数据结构。
- 如果存在要加载的非常大的数据列表,则它在处理内存约束方面非常低效,数据源也可以来自不同的位置,例如来自云的数据源以及来自数据库的其他位置(如果网络不可用等等)。
- 分页库附带一个
PagedList
类,它是一个Java List实现,它与异步数据源一起使用。 - 每次访问PagedList中的一个项目时,它都会从数据源中赖加载数据。即,在滚动时会从数据源中获取更多数据。
- 最常见的问题之一是,如果数据是从数据源中获取的,该数据源由于查询而返回了数千行,即使用户只能看到8到10,这些千字仍然可以在UI中充满。 查询结果的行。 这是无效的(请注意,回收站视图只能通过回收列表项资源来帮助处理resorces,它与数据无关)。 这是Paging通过按需提供数据(当用户滚动时)到回收器视图的位置。
- Code:
-
Important Note(重要的提示):
- 分页支持RxJava。
- ListAdapter:ListAdapter是一个RecyclerView适配器,它显示一个列表。
// Call 1 listAdapter.submitList(listOf(1,2,3,4)) // Call 2 listAdapter.submitList(listOf(1,3,4)) // 当第二个语句在执行1st之后执行时,它只是删除'2', // 因为它在后台线程中找到两个更新之间的差异并相应地执行UI更新。 // 这使它变得高效。
- 允许占位符
不使用占位符:将列表大小视为列表的大小,直到它被分页,一旦我们到达分页项目的底部,滚动条跳转到滚动界面的中间,我们可以滚动到下一组 列出在到达第一个分页列表末尾后分页的项目。 这在原理上不是那么好,甚至在处理滚动条的动画时更糟糕。
-
使用占位符:整个列表的大小将被采用,直到项目数据变为空,然后被分页的内容显示在列表中,并且重新显示以占位符的形式显示,默认情况下启用,一旦它们被分页 数据将填补这些占位符。
-
取决于数据源
-
位置数据源(最佳选择)
- 使用滚动跳转到列表的中间,然后从可见的初始位置开始分页。即,可见占位符。
-
ItemKeyed数据源
- 给定页面,可以使用列表中的第一项来标识前一页,并且可以使用列表中的最后一项来标识以下项。 如果数据源在平均值中更新,则从可见列表的开始元素获取页面大小的列表,并执行diff并使更改膨胀。
-
PageKeyed数据源
- 用于服务器端API。
-
表示:
-
最好的方法:
-
表示:
I
II
-
由于以下原因,第一种技术效率不高:
- 网络不好。
- 虽然它们存在,但不使用数据库中的本地数据。
这是第二种自我解释的技术。
-
-
Navigation
WorkManager
Foundation components(基础组件)
- AppCompat
- Android KTX
- Multidex
- Test
Behaviour Components(行为组件)
- Download manager
- Media & playback
- Notifications
- Permissions
- Sharing
- Slices
UI components(UI组件)
- Animation & transitions
- Auto
- Emoji
- Fragment
- Layout
- Palette
- TV
- Wear OS by Google