如何应对 Android 面试官 -> 玩转 Jetpack Room

Android应用开发面试之Jetpack面试题分析汇总 Jetpack简介请简述一下Jetpack是什么,以及它在Android开发中的作用。Jetpack相比传统Android SDK有哪些主要优势?Jetpack核心组件你能列举并解释Jetpack中的一些核心组件(如LiveData, ViewModel, Room, Navigation等)吗?这些组件是如何帮助开发者实现MVC、MVP或MVVM等架构模式的? 阅读详情

前言


在这里插入图片描述

Android Jetpack 的出现统一了 Android 开发生态,各种三方库逐渐被官方组件所取代。
Room 也同样如此,逐渐取代竞品成为最主流的数据库 ORM 框架。
这当然不仅仅因为其官方身份,更是因为其良好的开发体验,大大降低了 SQLite 的使用门槛。

相对于SQLiteOpenHelper等传统方法,使用Room操作SQLite有以下优势:

1.编译期的SQL语法检查

2.开发高效,避免大量模板代码

3.API设计友好,容易理解

4.可与 LiveData 关联,具备 LiveData Lifecycle 的所有魅力

Room 的使用,主要涉及三个类: Entity、DataBase、DAO

  • Database: 访问底层数据库的入口;
  • Entity: 代表数据库中的表(table),一般用注解;
  • Data Access Object (DAO): 数据库访问者;

这三个组件的概念也出现在其他 ORM 框架中,有过使用经验的同学理解起来并不困难:通过 Database 获取 DAO,然后通过 DAO 查询并获取 entities,最终通过 entities 对数据库 table 中数据进行读写;

在这里插入图片描述

用法篇


使用方式我们介绍下基础使用和结合 MVVM 的使用

基础使用

导入依赖

// 下面是 ROOM依赖相关的代码
def room_version = "xxx"
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version" // use kapt for Kotlin

// optional - Guava support for Room, including Optional and ListenableFuture
implementation "androidx.room:room-guava:$room_version"

我们先来了解下它的简单使用,遵循 Entity、DAO、DataBase

我们先来声明 Entity

@Entity
public class Student {

    // 主键 SQL 唯一的 autoGenerate 自增长
    @PrimaryKey(autoGenerate = true)
    private int uid;

    @ColumnInfo(name = "name")
    private String name;

    @ColumnInfo(name = "pwd")
    private String password;

    @ColumnInfo(name = "address")
    private int address;

    public Student(String name, String password, int address) {
        this.name = name;
        this.password = password;
        this.address = address;
    }

    public int getUid() {
        return uid;
    }

    public void setUid(int uid) {
        this.uid = uid;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public int getAddress() {
        return address;
    }

    public void setAddress(int address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "Student{" +
                "uid=" + uid +
                ", name='" + name + '\'' +
                ", password='" + password + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

这样 Entity 我们就声明好了;@ColumnInfo 注解可有可无,没有就会使用我们声明的属性来创建列名,声明了就用我们声明的来创建列名;

接下来,我们来声明 Dao,用来做增、删、改、查操作;

@Dao
public interface StudentDao {

    @Insert
    void insert(Student... students);

    @Delete
    void delete(Student student);

    @Update
    void update(Student student);

    @Query("select * from Student")
    List<Student> getAll();

    // 查询一条记录
    @Query("select * from Student where name like:name")
    Student findByName(String name);

    // 数组查询 多个记录
    @Query("select * from Student where uid in(:userIds)")
    List<Student> getAllId(int[] userIds);

    // 就是只查询 name pwd 给 StudentTuple 类接收
    @Query("select name,pwd from Student")
    StudentTuple getRecord();
}

PS:Dao 的声明必须要用 interface来声明;

如果我们只想查询数据库表中的 某x个字段,那么我们需要声明一个类来接收相关字段,切这个类中声明的字段要和 Entity 中保持一致;

public class StudentTuple {

    @ColumnInfo(name = "name")
    public String name;

    @ColumnInfo(name="pwd")
    public String password;

    public StudentTuple(String name, String password) {
        this.name = name;
        this.password = password;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "StudentTuple{" +
                "name='" + name + '\'' +
                ", password='" + password + '\'' +
                '}';
    }

}

这个类 @Entity 不能加,加了就是一张表了;

接下来,我们来声明 Database

@Database(entities = { Student.class }, version = 1, exportSchema = false)
public abstract class AppDataBase extends RoomDatabase {
    // 暴露dao
    public abstract StudentDao userDao();
}
  1. 必须要用抽象类

  2. 必须要继承 RoomDatabase

  3. 要写 exportSchema = false 导出模式,防止后续升级的异常

通过 APT 技术帮我们生成具体的实现类,所以 Dao 和 Database 都需要抽象的类;

接下来,我们在 Activity 中调用;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        // 数据库的操作应该是在子线程
        DbTest t = new DbTest();
        t.start();
    }
    
    public class DbTest extends Thread {
        @Override
        public void run() {
            // 核心逻辑1 数据库的操作都在这里
            AppDataBase marsDB = Room.databaseBuilder(getApplicationContext(),
                    AppDataBase.class,
                    "MarsDB")
                    // 可以设置强制主线程,默认是让你用子线程
                    // .allowMainThreadQueries()
                    .build();

            // 执行增、删、改、查操作
            StudentDao dao = marsDB.userDao();
            // 增
            dao.insert(new Student("Mars0", "123", 1));
            dao.insert(new Student("Mars1", "456", 2));
            dao.insert(new Student("Mars2", "789", 3));
            dao.insert(new Student("Mars3", "111", 4));

            // 查询全部数据
            List<Student> all = dao.getAll();
            Log.d("Mars", "run: all.toString(): " + all.toString());

            Log.i("Mars", "--------------------------");

            // 查询名字为 Mars3 的一条数据
            Student mars3 = dao.findByName("Mars3");
            Log.d("Mars", "run: mars.toString(): " + mars.toString());

            Log.i("Mars", "--------------------------");

            // 查询 2 3 4 uid的三条数据
            List<Student> allID = dao.getAllId(new int[]{2, 3, 4});
            Log.d("Mars", "run: allID.toString(): " + allID.toString());

            Log.i("Mars", "--------------------------");

            // 查询student表里面的数据  到  StudentTuple里面去
            StudentTuple record = dao.getRecord();
            Log.d("Derry", "run: record.toString(): " + record.toString());
            
            // 更新
            dao.update(new Student("Mars3", "112", 4))
            
            // 删除
            dao.delete(new Student("Mars3", "112", 4))
        }
    }
}

增、删、改、查的基础使用就是这些,相对我们直接操作 SQLite 要方便很多;

Jetpack Room 结合 MVVM 使用

在这里插入图片描述

我们先来看下 MVVM 的标准架构图,可以看到 Room 通过 Repository 连接到 Model 层中的 Room,我们就按照这个架构图来看下如何结合 MVVM 使用;

老三件,Entity、Dao、Database,我们可以直接复用前面基础使用中创建的;Database 我们稍微改造下,不再 Activity 中进行数据库的创建了,我们可以改成单例的模式,以及可以在主线程中创建数据库;

@Database(entities = {Student.class}, version = 2, exportSchema = false)
public abstract class AppDatabase  extends RoomDatabase {
    
    /** 单例属性 */
    private static AppDatabase instance;
    
    // 对外暴露唯一实例
    public static synchronized AppDatabase getInstance(Context context) {
        if (instance == null) {
            instance = Room.databaseBuilder(context.getApplicationContext(),
                    AppDatabase.class
                    , "MarsDB")
                    // 可以强制在主线程运行数据库操作
                    .allowMainThreadQueries()
                    .build();
        }
        return instance;
    }

    public abstract StudentDao studentDao();
}

支持 LiveData

Dao 中也需要改造下,支持 LiveData,主要是查询操作;

@Dao
public interface StudentDao {

    @Insert
    void insert(Student... students);

    @Delete
    void delete(Student student);

    @Update
    void update(Student student);

    @Query("select * from Student order by uid")
    LiveData<List<Student>> getAll();

    // 查询一条记录
    @Query("select * from Student where name like:name")
    LiveData<Student> findByName(String name);

    // 数组查询 多个记录
    @Query("select * from Student where uid in(:userIds)")
    LiveData<List<Student>> getAllId(int[] userIds);

    // 就是只查询 name pwd 给 StudentTuple 类接收
    @Query("select name,pwd from Student")
    LiveData<StudentTuple> getRecord();
}

针对查询操作,只需要将返回值改成 LiveData<> 进行包裹,就可以完美支持 LiveData 了;

支持 Repository

我们可以简单的来支持下 Repository 层,商业环境中,它应该是一个独立的模块,支持各个业务的 DAO 和 Net 的操作,内部根据业务判断 dao 和 net 的逻辑;本期我们为了体验 MVVM 的结合,设计的比较简单

public class StudentRepository {

    private StudentDao studentDao; // 用户操作 只面向DAO

    public StudentRepository(Context context) {
        AppDatabase database = AppDatabase.getInstance(context);
        studentDao = database.studentDao();
    }

    // 下面代码是:提供一些API给ViewModel使用
    
    // 增
    void insert(Student... students) {
        studentDao.insert(students);
    }

    // 删
    void delete(Student student) {
        studentDao.delete(student);
    }

    // 改
    void update(Student student) {
        studentDao.update(student);
    }

    // 查 关联 LiveData 暴露环节
    LiveData<List<Student>> getAllLiveDataStudent() {
        return studentDao.getAll();
    }
}

结合 ViewModel

接下来我们来声明 ViewModel,由架构图可以看到,ViewModel 操作的是 Repository;

public class StudentViewModel extends AndroidViewModel {

    private StudentRepository studentRepository; // 定义仓库 ViewModel 只操作仓库
    private LiveData<List<Student>> liveDataAllStudent; // 触发改变的 LiveData 的数据
    
    public StudentViewModel(Application application) {
        super(application);
        studentRepository = new StudentRepository(application);
        if (liveDataAllStudent == null) {
            liveDataAllStudent = studentRepository.getAllLiveDataStudent(); // 使用 LiveData 关联 Room
        }
    }

    // 增
    void insert(Student... students) {
        studentRepository.insert(students);
    }

    // 删
    void delete(Student student) {
        studentRepository.delete(student);
    }

    // 改
    void update(Student student) {
        studentRepository.update(student);
    }

    // 查 关联 LiveData
    LiveData<List<Student>> getAllLiveDataStudent() {
        if (liveDataAllStudent == null) {
            liveDataAllStudent = studentRepository.getAllLiveDataStudent(); // 使用 LiveData 关联 Room
        }
        return liveDataAllStudent;
    }
}

接下来,我们声明 Activity 来创建 ViewModel

public class MainActivity extends AppCompatActivity {

    private RecyclerView recyclerView;
    private StudentViewModel studentViewModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 创建 RV
        recyclerView = findViewById(R.id.recyclerView);
        
        // 创建 ViewModel
        studentViewModel = new ViewModelProvider(getViewModelStore(), new ViewModelProvider.AndroidViewModelFactory(getApplication())).get(StudentViewModel.class);
        // 观察者,如果使用了 DataBinding 以及 BindingAdapter 之后,这个 observe 的逻辑就可以删掉了
        studentViewModel.getAllLiveDataStudent().observe(this, new Observer<List<Student>>() {
            @Override
            public void onChanged(List<Student> students) {
                // 更新UI
                recyclerView.setAdapter(new GoodsAdapter(MainActivity.this, students));
            }
        });


        // 模拟 仓库
        new Thread()  {
            @Override
            public void run() {
                super.run();
                try {
                    Thread.sleep(6000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 默认给数据库 ROOM 增加数据
                for (int i = 0; i < 50; i++) {
                    studentViewModel.insert(new Student("Mars", "123", 1));
                }
            }
        }.start();


        // 模拟仓库 数据库数据被修改了,一旦数据库被修改,那么数据会驱动 UI 发生改变
        new Thread() {
            @Override
            public void run() {
                for (int i = 0; i < 50; i++) {
                    try {
                        Thread.sleep(1000);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    // 每隔一秒、更新一次,内部会 setValue,就会回调到 onChange 方法;
                    studentViewModel.update(new Student(6, "Mars" + i, "123", 1));
                }
            }
        }.start();
    }
}

运行之后,可以看到的效果就是,界面每隔 1s 更新一下;

源码篇


本质上是通过 APT 技术,帮我们生成了 Dao 和 Database 的具体实现;
在这里插入图片描述

为什么,使用了 LiveData 之后,就能自动的更新 UI 了,我们进入源码看下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

当我们执行编译之后,可以看到 Dao 有了实现,我们点击这个可以进入到实现层;

public LiveData<List<Student>> getAllLiveDataStudent() {
  final String _sql = "select * from Student order by uid";
  final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, 0);
  return new ComputableLiveData<List<Student>>(__db.getQueryExecutor()) {
    private Observer _observer;

    @Override
    protected List<Student> compute() {
      if (_observer == null) {
        _observer = new Observer("Student") {
          @Override
          public void onInvalidated(@NonNull Set<String> tables) {
            // 核心逻辑就在这里 Oberver 监听,Room 会把改变的数据发送过来,收到变化之后会进行刷新实现
            invalidate();
          }
        };
        __db.getInvalidationTracker().addWeakObserver(_observer);
      }
      final Cursor _cursor = __db.query(_statement);
      try {
        final List<Student> _result = new ArrayList<Student>(_cursor.getCount());
        while(_cursor.moveToNext()) {
          final Student _item;
          _item = __entityCursorConverter_comExampleRoomdemo02Student(_cursor);
          _result.add(_item);
        }
        return _result;
      } finally {
        _cursor.close();
      }
    }

    @Override
    protected void finalize() {
      _statement.release();
    }
  }.getLiveData();
}

核心逻辑就在这里 Oberver 监听,Room 会把改变的数据发送过来,收到变化之后会进行刷新实现,我们进入这个 invalidate 看下:

final Runnable mInvalidationRunnable = new Runnable() {
    @MainThread
    @Override
    public void run() {
        boolean isActive = mLiveData.hasActiveObservers();
        if (mInvalid.compareAndSet(false, true)) {
            if (isActive) {
                // 核心逻辑,最终执行了 mRefreshRunnable 这个 runnable
                mExecutor.execute(mRefreshRunnable);
            }
        }
    }
};


public void invalidate() {
    ArchTaskExecutor.getInstance().executeOnMainThread(mInvalidationRunnable);
}

核心逻辑,最终执行了 mRefreshRunnable 这个 runnable,我们进入这个 Runnable 看下:

final Runnable mRefreshRunnable = new Runnable() {
    @WorkerThread
    @Override
    public void run() {
        boolean computed;
        do {
            computed = false;
            if (mComputing.compareAndSet(false, true)) {
                try {
                    T value = null;
                    while (mInvalid.compareAndSet(true, false)) {
                        computed = true;
                        value = compute();
                    }
                    if (computed) {
                        // 核心逻辑,直接调用了 postValue 
                        mLiveData.postValue(value);
                    }
                } finally {
                    mComputing.set(false);
                }
            }
        } while (computed && mInvalid.get());
    }
};

最终调用了 LiveData 的 postValue 发送数据;

升级篇


Room 的数据库升级相对比较复杂;

暴力升级

public static synchronized AppDatabase getInstance(Context context) {
        if (instance == null) {
            instance = Room.databaseBuilder(context.getApplicationContext(),
                    AppDatabase.class
                    , "MarsDB")
                    // 可以强制在主线程运行数据库操作
                    .allowMainThreadQueries()
                    // 暴力升级,强制执行(数据会丢失)(慎用)
                    .fallbackToDestructiveMigration()
                    .build();
        }
        return instance;
    }

fallbackToDestructiveMigration() 会强制升级数据库,但是可能会导致数据丢失,谨慎使用吧;

稳定升级

Room 提供了稳定升级的接口 .addMigrations()

这个接口需要我们实现 Migration,并实现具体的 migrate 逻辑;

static final Migration MIGRATION_1_2 = new Migration(1, 2) {
        @Override
        public void migrate(SupportSQLiteDatabase database) {
            // 在这里用 SQL 脚本完成数据的变化
            database.execSQL("alter table student add column flag integer not null default 1");
        }
    };

然后将 MIGRATION_1_2 传入到 addMigrations() 这个方法中;

数据库一般是不建议降级的,这块大家在使用过程中也尽量不要降级处理吧;

好了,room 就先写到这里吧~

欢迎三连


来都来了,点个关注,点个赞吧,你的支持是我最大的动力~

【面经分享】字节抖音Android客户端3,安卓开发kotlin推荐书籍 6. 算法 LeetCode 518. 零钱兑换 II 题目开始理解错了。最后这个题没完全做出来,面试官让我讲了下思路。 7. 反问 部门业务? 面试评价? 我还有什么需要学习的地方吗? 面试官反问:这次面试只是为了实习还是说有转正想法的? 部门业务开发语言? 多久能收到结果通知? 一面结束后等了十几分钟,HR 通知第二天二面。 二面(1 月 14 日,60 min) 1. 自我介绍 2. 项目介绍。用到了什么技术栈? ViewModel 的作用是什么? 你在 Frag 阅读详情

相关推荐

【仿真】Carla Python API实战:从零搭建自动驾驶测试环境

本文详细介绍了如何使用Carla Python API从零搭建自动驾驶测试环境。通过Carla仿真平台,开发者可以构建高度逼真的城市环境和车辆物理模型,利用Python API实现传感器配置、数据采集、场景构建及自动驾驶算法集成。文章还分享了实际项目中的调试技巧和性能优化经验,帮助读者快速掌握自动驾驶仿真测试的核心技术。

weixin_29050513的博客 213

如何应对 Android 面试官 -> 玩转 Jetpack Paging

Paging分页组件摘要 Paging是Jetpack提供的分页组件,用于在RecyclerView中优雅地分页加载数据,减少网络和系统资源消耗。核心优势包括: 增量加载数据,避免一次性加载过多 数据更新时仍保持流畅响应 高效利用资源,按需加载 核心使用步骤 定义数据源DataSource(PositionalDataSource/PageKeyedDataSource/ItemKeyedDataSource) 创建数据工厂DataSource.Factory 使用PagedListAdapter替代Rec

IT_Android的博客 1144

ubuntu18.04 升级Ubuntu 20.04

Ubuntu 18.04升级20.04指南:首先备份重要数据,更新当前系统并检查新版本可用性(sudo do-release-upgrade -c)。确认升级后执行sudo do-release-upgrade,按提示完成操作。升级过程需耐心等待,完成后重启系统。注意:升级前务必备份数据,确保系统为最新版本,以降低风险。升级后即可使用Ubuntu 20.04系统。

https://ophome.blog.youkuaiyun.com,在IT行业有多年的工作经验,尤其是在Python、Linux、负载均衡、Nginx和服务器运维等领域。 1058

如何应对 Android 面试官 -> 玩转 Jetpack WorkManager

WorkManager是Android Jetpack提供的后台任务管理组件,适用于需要保证执行的非即时性任务。它能够自动选择最佳执行方式(JobScheduler/Firebase JobDispatcher/AlarmManager),确保任务在应用退出或设备重启后仍能执行。主要特点包括跨API版本兼容、电量优化和任务管理,但不支持保活操作。使用步骤包括:1)继承Worker类实现任务逻辑;2)通过WorkManager.enqueue()启动任务。支持Activity与Worker之间的双向数据传递:

IT_Android的博客 1062

从零构建边缘AI数据管道:K230+ESP8266的物联网实践指南

本文详细介绍了如何利用K230开发板和ESP8266模块构建高可靠性的边缘AI数据管道,特别针对智能农业监测场景。通过完整的系统架构设计、AI模型部署、低功耗通信优化和云端集成方案,为开发者提供了一套可落地的物联网实践指南,重点解决了边缘计算环境下的数据传输稳定性和能效管理问题。

j2k3l4的博客 871

Windows 下 Codex MCP 服务配置全攻略:从环境搭建到实战避坑

本文详细介绍了在Windows系统下配置Codex MCP服务的完整流程与实战避坑指南。内容涵盖从Node.js环境搭建、Codex CLI安装,到核心配置文件config.toml的编写与解析,并重点解决了Windows平台特有的环境变量设置、MCP服务启动命令适配等关键难点,帮助开发者顺利完成从环境准备到编辑器插件连接的整个配置过程。

weixin_28826545的博客 2066

2024年Android最全Android Sunflower 带您玩转 Jetpack,阿里面试官必问

我见过很多技术leader在面试的时候,遇到处于迷茫期的大龄程序员,比面试官年龄都大。这些人有一些共同特征:可能工作了7、8年,还是每天重复给业务部门写代码,工作内容的重复性比较高,没有什么技术含量的工作。问到这些人的职业规划时,他们也没有太多想法。其实30岁到40岁是一个人职业发展的黄金阶段,一定要在业务范围内的扩张,技术广度和深度提升上有自己的计划,才有助于在职业发展上有持续的发展路径,而不至于停滞不前。不断奔跑,你就知道学习的意义所在!

2401_84545804的博客 1047

利用Arcgis提取nc数据并计算区域年均温

1.下载数据。2.解压数据至不含中文的路径中。打开工具箱中的多维分析工具-创建NetCDF栅格图层,导入数据。3.打开工具箱中的数据管理工具-图层和表视图-创建栅格图层,导入数据,对输出数据进行命名,得到月均温栅格数据。4.选择工具箱-Spatial Analyst工具(空间分析工具)-地图代数-栅格计算器,计算全国一年年均温。​5.将其导出为.tif格式数据,方便后期使用。6.选择工具箱-Spatial Analyst工具(空间分析工具)-区域分析--以表格显示分区统计,得到分区域的气温数据。

什么都学亿点点的博客 7990

Android面试终极指南:Jetpack Room高级面试题深度解析

在竞争激烈的Android开发岗位面试中,Jetpack Room作为官方推荐的本地数据库解决方案,已成为面试官重点考察的技术点。本文将从核心原理、性能优化到实战应用,全面解析Room面试中的高频问题与解题策略,助你轻松应对面试挑战。 [![Android面试指南](https://raw.gitcode.com/gh_mirrors/an/android-interview-questions

gitblog_01197的博客 855

unity打包流程整理-Windows/Mac/Linux平台

1.Platform(平台)功能: 选择目标构建的目标平台选项PC, Mac & Linux Standalone: 适用于 Windows、Mac 和 Linux 平台2.Target Platform(目标平台)功能: 选择具体的操作系统版本选项Windows: 针对 Windows 操作系统Mac: 针对 macOS 操作系统Linux: 针对 Linux 操作系统3.Architecture(架构)功能: 选择应用程序的目标处理器架构选项x86: 针对 32 位系统。

weixin_42333247的博客 5135

YOLO26涨点改进 | 全网独家,注意力创新改进篇 | Arxiv2025 | YOLO26引入MSLA多尺度线性注意力模块,高效提取多尺度特征和建模长程依赖,含多种创新改进,助力有效涨点

本文提出了一种多尺度线性注意力模块(MSLA)来优化YOLO26模型。MSLA通过并行使用不同尺寸的深度可分离卷积(3×3至9×9)提取多尺度特征,并结合线性注意力机制高效建模全局依赖关系。该模块显著提升了模型对多尺度目标的检测能力,同时保持了轻量化特性。实验表明,MSLA能有效增强小目标检测和复杂场景下的分割精度。文章详细介绍了MSLA的网络结构、核心优势及实现代码,并提供了两种集成MSLA的YOLO26改进方案,为实时目标检测任务提供了高效解决方案。

Ai缝合怪、助力小伙伴高效发论文 292

Android jetpack最佳总结和实践,字节跳动面试官

2)类图Lifecycle组件成员Lifecycle被定义成了抽象类,LifecycleOwner、LifecycleObserver被定义成了接口。组件(Activity、Fragment)实现了LifecycleOwner接口,该只有一个返回Lifecycle对象的方getLifecyle(): LifecycleRegistry。Lifecycle的内部类State标明状态、Event表示事件。

2301_79056696的博客 583

基金估值核算系统三国杀:恒生 VS 赢时胜 VS 融选!

本文对比分析了恒生电子、赢时胜和融选科技三家金融科技公司的基金估值系统。恒生电子作为行业龙头,在公募基金领域占据较大份额,其新一代估值系统6.0采用微服务架构,自动化程度高;赢时胜在中型公募和券商资管领域优势明显,其V5.5系统在信创适配和复杂产品处理方面表现突出;融选科技作为新兴厂商,提供轻量化解决方案,适合中小型机构。文章从市场格局、系统定位、技术架构、成本构成和用户反馈五个维度进行深入比较,为金融机构选型提供参考。当前估值系统市场呈现"三国鼎立"格局,各具特色,选型需结合机构规模、

magbox520的博客 825

面试官:作为一名Android开发者,连jetpack都不懂?你还是改行吧!

JetPack自2018年面世,迎来了它的第三个年头。但是在国内的受欢迎程度远远及不上国外,国内开发者一听到别人说JetPack,脑海中蹦出来的词就是“不成熟”、“不好用”、“调试有点难”,但是事实真的是如此嘛? 我们首先来看看JetPack在发布的时候的雄心壮志: 以上来自谷歌语录,总结起来就是: JetPack是一整套组件库 它能帮我们写出优质应用 它能让我们不需要去写毫无营养的样板代码 4. 它能规范我们的开发行为 接下来来看看JetPack组件库到底包含了哪些组件: 从上图我们

Android 开发架构 428

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

如何快速上手Jetpack?Jetpack入门到精通再到(网易云,android音视频开发

像“解耦”等 含糊其辞的说法,已经不能够被面试官所认可,稍微对 MVVM 有一点经验的面试官都会请你举例说明,好证明你确实对 MVVM 有着正确、深入的理解,能够自然而然地写出标准化、规范化的代码,能够迅速适应各家公司自制的自动化模版工具。 如何快速掌握Jetpack呢? 特邀前腾讯IOT项目组资深工程师Derry老师给大家整理了即学即用《Jetpack架构组件从入门到精通》和《高级JetPack强化实战》,从入门到精通,教程通俗易懂,实例丰富,既有基础知识,也有进阶技能,能够帮助读者快速入门。从而解决项

wqwq_22的博客 496

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Android面试终极指南:Room数据库面试难题突破秘籍

在竞争激烈的Android开发岗位面试中,Room数据库作为Jetpack组件的核心成员,常常成为面试官考察的重点。本文将帮助你系统梳理Room数据库的核心知识点、常见面试题及解题思路,让你在面试中轻松应对各种挑战,脱颖而出。 [![Android面试问题封面图](https://raw.gitcode.com/gh_mirrors/an/android-interview-questions/

gitblog_00499的博客 939

Android 高级工程师面试参考答案:架构设计、Jetpack 与 Compose

本文探讨了Android开发中架构设计、Jetpack组件和Compose的实践要点。主要内容包括:MVVM相比MVP的优势在于集中管理页面状态,降低维护成本;ViewModel应作为状态协调者而非业务仓库;LiveData、StateFlow和SharedFlow需区分状态和事件;Jetpack组件解决特定复杂度问题;依赖注入提升代码可维护性;MVI适合复杂状态管理;Compose本质是声明式状态驱动UI;重组优化的核心是状态范围控制。文章强调架构选择应基于实际复杂度,而非盲目追随新技术。

帅次的博客 1522

不会吧!做Android开发还不会Jetpack架构组件?快来看看这篇文章吧!

1.Hilt - Jetpack 推荐的依赖注入类库2.Paging3 - 逐步加载和显示数据3.App Startup - 在应用启动时初始化组件5.更简单的动画 — core-animation 和 SeekableAnimatedVectorDrawable6.使用 Database Inspector 调试数据库。

2401_84545046的博客 597

7年老Android一次坑爹的面试经历,吊打面试官系列!

前言 网上有很多对程序员简历的一些指导,这里就不重述,大家可以搜下网上其他大神的总结,结合自身情况修改下。我有几点建议: 1.尽量不要花哨,程序员和设计师或者产品运营还不一样,我们的简历成功与否决定权还是在技术面试官那,而他们看重的是你的项目经验内容和技术等描述。 2.技能描述这块尽量只写你懂得而且理解深刻的,可以适当加入一些新技术或流行框架,不过这块需要理解,没来得及看源码的可以看看大神们对它的总结,网上一大堆。 3.项目经验这块尽量加入关键词,比如使用了什么技术、用到哪些设计模式、优化数据对比、扩展总结

m0_56037919的博客 187

阿里5次面试碰壁,100天深造-Jetpack架构组件从入门到精通,险获腾讯年薪45w+offer!

Jetpack是一套库、工具和指南,可以帮助开发者更轻松地编写优质应用。这些组件可以帮助开发者遵循最佳做法、让开发者摆脱编写样板代码的工作并简化复杂任务,以便开发者将精力集中放在所需的代码上。我见过很多技术leader在面试的时候,遇到处于迷茫期的大龄程序员,比面试官年龄都大。这些人有一些共同特征:可能工作了7、8年,还是每天重复给业务部门写代码,工作内容的重复性比较高,没有什么技术含量的工作。问到这些人的职业规划时,他们也没有太多想法。

2401_84132204的博客 1005

Android Jetpack从入门到精通,干货满满

11.1 Hilt - Jetpack 推荐的依赖注入类库11.2 Paging3 - 逐步加载和显示数据11.3 App Startup - 在应用启动时初始化组件11.5 更简单的动画 — core-animation 和 SeekableAnimatedVectorDrawable。

erhtre的博客 1452

2024年安卓最全Android Jetpack(一) 介绍,2024年最新面试几个月还没找到工作

首先是感觉自己的基础还是不够吧,大厂好像都喜欢问这些底层原理。之前的准备只涉及了Java、Android、计网、数据结构与算法这些方面,面对面试官对其他基础课程的考察显得捉襟见肘。下一步还是要查漏补缺,进行针对性复习。最后的最后,那套资料这次一定要全部看完,是真的太全面了,各个知识点都涵盖了,几乎我面试遇到的所有问题的知识点这里面都有!希望大家不要犯和我一样的错误呀!!!一定要看完!网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

2301_82244182的博客 982

Android 14+ 模拟器抓包实录:把 Burp CA 装成系统 CA,让 targetSdk≥34 的 App 乖乖解密

本文记录了在 Android 14+ 环境下,通过将 Burp CA 安装为系统信任锚,成功抓取 targetSdk=35 App 的 HTTPS 明文流量的完整实操过程。针对“浏览器可用、App 不可用”的典型现象,精准识别出根本原因是系统级证书信任策略变更(用户安装的 CA 被屏蔽),而非 SSL Pinning。仅通过 adb 命令将 CA 推送至系统证书存储并重启生效,无需 Frida、Objection 或修改 APK,实现零侵入解密。全文命令均基于 Windows + MuMu 模拟器环境实测通

JIANqiao19931029的博客 341
上一篇: 如何应对 Android 面试官 -> 玩转 Jetpack ViewModel
下一篇: 如何应对 Android 面试官 -> 玩转 Jetpack Navigation
老A说
博客等级 码龄14年 1181粉丝 85原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值