(终极Android Jetpack参考)

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<Word> getAllWords();
                }
        
        请注意,Dao应该是abstract classinterface。 其余的是自我解释的,如前所述,在这种情况下,从数据库中查询会返回一个对象列表。例如,List<Word> and no a Cursor.。
      • 如果用LiveData <List <Word >>替换List <Word>那么它恰好会为数据库中的每个更改返回一个更新的对象列表。 这是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:
      • ViewModelAndroidViewModel扩展
            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>可以使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);
           }
        });
        
    • 这里,mModelViewModel实例,并假设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
        
  • 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通过创建适当的变量来访问数据类,如上所示。
    • 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组件)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容

  • 用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你...
    hw1212阅读 12,473评论 2 59
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,569评论 25 707
  • 人生一条路,走自己的路! 人生两件宝,身体好,心不老! 有一种心情,叫喜怒哀乐; 有一种味道,叫酸甜苦辣; 有一种...
    卓添阅读 200评论 0 0
  • 今年的国产剧好像都很“长脸”的样子。比如说《楚乔传》——据说是中国第一部播放量破400亿的选手(虽然我没看过吧)。...
    有剧Shirley阅读 607评论 2 4
  • 这一套龙猫耗时断断续续两天,毕竟还有其他的事情要忙。前面也说过我是宫崎骏的忠粉,龙猫的题材,好看也好画。微混迹二次...
    葡萄子酱阅读 1,577评论 11 19