image.png
什么是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;}
}
大多数注释都是不言自明的,其中@Entity接收并声明即将创建的表的tableName(如果没有提到tableName,则该表将占用该类的名称,在本例中为:Word)并且该类还有许多可选属性,例如设置列名(如果节点指定它占用变量的名称),重要的是要注意实体类中的所有声明都被视为数据库的列。(这里"one" 例如, mWord).您可以使用@Ignore注释将声明忽略为数据库中的列。
Room应该可以访问Entity类的成员变量,它应该能够设置或重置或更新存储在成员变量中的值,因此注意虽然成员变量被声明为private,但是有一个公共构造函数, getter访问成员变量。
@dao:
@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 getAllWords();
}
请注意,Dao应该是abstract class或interface。 其余的是自我解释的,如前所述,在这种情况下,从数据库中查询会返回一个对象列表。例如,List and no a Cursor.。
如果用LiveData >替换List 那么它恰好会为数据库中的每个更改返回一个更新的对象列表。 这是LiveData的主要原则之一
@database:
@Database(entities = {Word.class}, version = 1)
public abstract class WordRoomDatabase extends RoomDatabase {
public abstract WordDao wordDao();
}
请注意,这必须是抽象的并扩展类RoomDatabase。 实体包含必须在数据库中创建的数据库表,并且@doa应该有一个抽象的getter方法
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。
ViewModel
以生命周期意识的方式管理与UI相关的数据。
由于它在配置更改后仍然存在,因此有可能取代AsyncTask Loaders。
Need:
UI与Data的高度分离。
没有责任太多的重大活动。
UI控制器显示数据。
ViewModel保存UI数据。
Reason:
假设你的某个实例有一个具有多个UI元素的Activity,并且会根据用户输入更新状态,现在当设备进行配置更改时,数据将因为重新创建活动而丢失。 配置改变。当然,你可以利用 onSavedInstanceState() 但是忘记单个字段会导致应用程序出现不一致,这里是ViewModel进入智能播放的地方。
在ViewModel中,由于UI数据与活动生命周期分离,因此它可以超越配置更改对数据所产生的影响。 因此,在重新创建活动之后,可以从ViewModel获取UI数据以分别更新UI。
Representation:
image.png
Code:
从ViewModel或AndroidViewModel扩展
public class MyViewModel extends ViewModel {
// Should contain all the UI Data (As LiveData if possible)
// Getters and Setters
}
将ViewModel链接到Activity
public 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(表示):
LiveData
Code:
使用MutableLiveData 可以使String成为可能的LiveData
要使用来自实时数据的实时数据更新UI,我们可以使用类似于观察者模式的模式。
mModel.getCurrentName().observe(this, new Observer() {
@Override
public void onChanged(@Nullable final String newName) {
// Update the UI, in this case, a TextView.
mTextView.setText(newName);
}
});
这里,mModel是ViewModel实例,并假设getCurrentName()返回一个MutableLiveData ,并在其上设置观察者,当MutableLiveData中的数据发生变化时,会调用onChanged()。
Arguments:
this : 指定它具有工作的活动 .例如:LifeCycleOwner
'Observer' : 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
Data Binding
声明性地将可观察数据绑定到UI元素。
它是一种经过验证的无样板UI解决方案。
Code:
data class User(val name: String, ... )
这里的代码是自我解释器,考虑到你在Kotlin中有一个data class数据类,它有许多字段,这些字段具有必须在UI中更新的实时数据,然后它可以直接在XML文档中解析。 UI通过创建适当的变量来访问数据类,如上所示。
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:
如果使用Room,效果很好。
由于涉及回收器视图,因此使用简单的代码示例来解释分页有点复杂。 但我们强烈建议您通过Codelab进行分页和检出分页示例应用程序,以便您更清楚地了解它。
它与创建回收器视图非常相似,并且涉及适配器(如PageListAdapter)和LiveData中的一些更改。
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