Android JetPack架构——联合记事本Demo一篇打通对Sqlite的增编削查联合常 ...

打印 上一主题 下一主题

主题 533|帖子 533|积分 1599

为什么要用Jetpack?
========================================================================
关于为什么要用Jetpack,我参考了很多的博客和官方文档,开阔了我对Android生态圈的明白和熟悉,在Jetpack推出前出现的许很多多强盛的第三方框架与语言,典型代表无疑是强盛的RxJava在Jetpack仍然有很多粉丝在一些功能在用它来替代Jetpack中的一些组件。
比如Jetpack衍生出的目前十分火热的MVVM架构(下方记事本的编写中将采用,你可以在代码耦合性中领会到它与传统MVC架构或之后出现MVP架构之间的差异),其中焦点组件LiveData其着实RxJava中早已经可以实现,另有需要使用Jetpack嘛?
答案是肯定的,大量的第三方框架与应用很多时候并不是最佳实现,尤其在Google对Android进行不断更新改进的情况下。Android Jetpack于谷歌而言,这是他们重新整理和同一安卓生态环境刻意的表现,Android Jetpack所显现的内容,也是谷歌想拓展和维护的方向。于长期苦恼于第三方库选择的广大Android开辟者而言,这是谷歌为我们提供的一盏明灯。
JetPack官方架构模式
========================================================================
以下是Google官方保举的架构模式

使用此架构能带来什么利益?



  • UI和业务逻辑解耦。
  • 有效避免生命周期组件内存泄漏。
  • 提高模块可测试性。
  • 提高应用稳定性,有效低落以下非常发生概率。
   针对Jetpack架构中繁多的组件,下面我详细介绍一款数据库交互组件Room。其余组件在Demo中使用也会做相应阐明
  什么是Room?为什么要使用Room?
==============================================================================
Room是Google提供的一个ORM库。
Room长期性库在 SQLite 的底子上提供了一个抽象层,让用户可以或许在充分利用 SQLite 的强盛功能的同时,获享更矫健的数据库访问机制。
Room组件架构体系
=====================================================================
Entity,Dao,Database为Room的3大基本组件,差异组件之间的关系如图

Database:包罗数据库持有者,并作为应用已生存的长期关系型数据的底层毗连的主要接入点
使用方法:用@Database来注解类,且使用 @Database解释的类应满意以下条件


  • 是扩展RoomDatabase的抽象类。
  • 在解释中添加与数据库关联的实体列表。
  • 包罗具有 0 个参数且返回使用 @Dao 解释的类的抽象方法。
在运行时,可以通过调用 Room.databaseBuilder() 或 Room.inMemoryDatabaseBuilder() 获取 Database 的实例。
Entity:表示数据库中的表
使用方法:用@Entit来注解实体类。
Dao:提供访问数据库的方法
使用方法:@Dao用来注解一个接口或者抽象方法。
记事本应用讲解
==================================================================
Room作为JetPack架构组件中关于SQLite数据库的架构组件,对应有着自己的知识体系。下面通过记事本Demo对Room本身组件联合MVVM架构所涉及的知识体系做一个总结.
由于涉及到别的一些组件,在有使用到时会做扼要介绍.

记事本Demo效果图:

1.编写Room数据库

1.1 编写数据库实体类

@Data
@Entity(tableName = “note”)
public class Note implements Serializable {
@PrimaryKey(autoGenerate = true)
private int id;
@ColumnInfo(name = “title”)
private String title;
@ColumnInfo(name = “content”)
private String content;
@ColumnInfo(name = “last_update_time”)
private Date lastUpdateTime;
}
1.2 编写数据库管理类Database

   注意:因为实体类中存在复杂数据类型——时间类。以是在数据库管理中需要使用@TypeConverters注入转换类,对复杂类型进行同一的转换处置处罚
  @Database(entities = {Note.class},version = 1,exportSchema = false)
@TypeConverters({Converters.class})
public abstract class NoteDatabase extends RoomDatabase {
private static NoteDatabase INSTANCE;
public synchronized static NoteDatabase getINSTANCE(Context context) {
if (INSTANCE==null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),NoteDatabase.class,“note_datebase”)
.fallbackToDestructiveMigration()
.build();
}
return INSTANCE;
}
/**


  • 在@Database中 多个entity则写多个Dao
*/
public abstract NoteDao getNoteDao();
}
1.3 编写数据库操纵接口Dao

@Dao
public interface NoteDao {
@Insert
void insertNotes(Note… notes);
@Update
void updateNotes(Note… notes);
@Delete
void deleteNotes(Note… notes);
@Query(“delete from note”)
void deleteAllNotes();
@Query(“select * from note order by last_update_time desc”)
LiveData<List> queryAllNotes();
@Query(“select * from note where content like :pattern order by last_update_time desc”)
LiveData<List> queryNotesWithPattern(String pattern);
}
2.编写数据仓库(Repository、AsyncTask)

如果此处不引入Repository类会造成什么影响呢?为什么要引入Repository?

对数据库的操纵(调用Dao)逻辑将放于ViewModel中(步骤5)。使得ViewModel中代码变得杂乱
引入仓库类,用于对数据库操纵并对ViewModel袒露方法。让ViewModel专注于数据处置处罚而非对数据库的调用,对ViewModel和Dao进一步解耦。
什么是AsyncTask?为什么需要引入AsyncTask?


  • 一个Android 已封装好的轻量级异步类,用于实现多线程、异步通信、消息通报
  • 数据库的操纵很重,一次读写操纵花费 10~20ms 是很常见的,如许的耗时很轻易造成界面的卡顿。以是通常情况下,条件允许情况下要避免在主线程中处置处罚数据库。
public class NoteRepository {
private NoteDao noteDao;
private LiveData<List> allNoteLive;
public NoteRepository(Context context){
NoteDatabase database = NoteDatabase.getINSTANCE(context);
noteDao = database.getNoteDao();
allNoteLive = noteDao.queryAllNotes();
}
public LiveData<List> getAllWordLive() {
return allNoteLive;
}
public LiveData<List> queryNotesWithPattern(String pattern){
//模糊匹配注意百分号
return noteDao.queryNotesWithPattern(“%”+pattern+“%”);
}
public void insertNotes(Note… notes){
new InsertAsyncTask(noteDao).execute(notes);
}
public void updateNotes(Note… notes){
new UpdateAsyncTask(noteDao).execute(notes);
}
public void deleteNotes(Note… notes){
new DeleteAsyncTask(noteDao).execute(notes);
}
public void deleteAllNotes(){
new DeleteAllAsyncTask(noteDao).execute();
}
//创建副线程类,继续AsyncTask实现
static class InsertAsyncTask extends AsyncTask<Note, Void, Void>{
private NoteDao noteDao;
InsertAsyncTask(NoteDao noteDao) {
this.noteDao = noteDao;
}
@Override
protected Void doInBackground(Note… notes) {
noteDao.insertNotes(notes);
return null;
}
}
static class UpdateAsyncTask extends AsyncTask<Note, Void, Void>{
private NoteDao noteDao;
UpdateAsyncTask(NoteDao noteDao) {
this.noteDao = noteDao;
}
@Override
protected Void doInBackground(Note… notes) {
noteDao.updateNotes(notes);
return null;
}
}
static class DeleteAllAsyncTask extends AsyncTask<Note, Void, Void>{
private NoteDao noteDao;
DeleteAllAsyncTask(NoteDao noteDao) {
this.noteDao = noteDao;
}
@Override
protected Void doInBackground(Note… notes) {
noteDao.deleteAllNotes();
return null;
}
}
static class DeleteAsyncTask extends AsyncTask<Note, Void, Void>{
private NoteDao noteDao;
DeleteAsyncTask(NoteDao noteDao) {
this.noteDao = noteDao;
}
@Override
protected Void doInBackground(Note… notes) {
noteDao.deleteNotes(notes);
return null;
}
}
}
3.编写ViewModel+LiveData

为什么要使用ViewModel?

ViewModel 是数据与 UI 分离的中心层,提供了一个将数据转换为 UI 友爱型数据的场所。其次,它也提供了多 Fragment 复用相同 ViewModel 的机制。
为什么要使用LiveData?

LiveData 是一个可以感知 Activity 、Fragment生命周期的数据容器。当 LiveData 所持有的数据改变时,它会通知相应的界面代码进行更新。
此处为了方便,数据和界面的交互放在了Activity中,读者有需要可以使用Databinding对Activity进行进一步解耦.
public class NoteViewModel extends AndroidViewModel {
/**


  • 使用数据仓库处置处罚好的数据库交互逻辑
*/
private NoteRepository repository;
public NoteViewModel(@NonNull Application application) {
super(application);
repository = new NoteRepository(application);
}
public LiveData<List> getAllNoteLive() {
return repository.getAllWordLive();
}
public LiveData<List> queryNotesWithPattern(String pattern){
return repository.queryNotesWithPattern(pattern);
}
public void insertNotes(Note… notes){
repository.insertNotes(notes);
}
public void updateNotes(Note… notes){
repository.updateNotes(notes);
}
public void deleteNotes(Note… notes){
repository.deleteNotes(notes);
}
public void deleteAllNotes(){
repository.deleteAllNotes();
}
}
4.编写界面

   界面引入了RecyclerView,取代了传统ListView。如果没有使用过RecyclerView可以参照
  Android 控件 RecyclerView
   其中涉及到矢量图的使用,如果没有使用过矢量图可以参照
  Android中使用矢量图(快速运用)
4.1 编写主页的Fragment

fragment_notes.xml
<?xml version="1.0" encoding="utf-8"?> <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android=“http://schemas.android.com/apk/res/android”
xmlns:app=“http://schemas.android.com/apk/res-auto”
xmlns:tools=“http://schemas.android.com/tools”
android:id=“@+id/mainFragment”
android:layout_width=“match_parent”
android:layout_height=“match_parent”
tools:context=“.base.NotesFragment”>
  <androidx.recyclerview.widget.RecyclerView
android:id=“@+id/recyclerView”
android:layout_width=“match_parent”
android:layout_height=“match_parent” />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id=“@+id/floatingActionButton”
android:layout_width=“wrap_content”
android:layout_height=“wrap_content”
android:layout_gravity=“bottom|center”
android:layout_margin=“16dp”
android:clickable=“true”
app:srcCompat=“@drawable/ic_add_white_24dp” />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
cell_card.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=“http://schemas.android.com/apk/res/android”
xmlns:app=“http://schemas.android.com/apk/res-auto”
xmlns:tools=“http://schemas.android.com/tools”
android:layout_width=“match_parent”
android:layout_height=“wrap_content”
android:clickable=“true”
androidrientation=“vertical”>
<androidx.cardview.widget.CardView
android:layout_width=“match_parent”
android:layout_height=“match_parent”
android:layout_marginLeft=“8dp”
android:layout_marginTop=“8dp”
android:layout_marginRight=“8dp”
android:foreground=“?selectableItemBackground”>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width=“match_parent”
android:layout_height=“match_parent”>
<androidx.constraintlayout.widget.Guideline
android:id=“@+id/guideline1”
android:layout_width=“wrap_content”
android:layout_height=“wrap_content”
androidrientation=“vertical”
app:layout_constraintGuide_percent=“0.85” />
<ImageView
android:id=“@+id/imageView”
android:layout_width=“wrap_content”
android:layout_height=“wrap_content”
app:layout_constraintBottom_toBottomOf=“parent”
app:layout_constraintEnd_toEndOf=“parent”
app:layout_constraintStart_toStartOf=“@+id/guideline1”
app:layout_constraintTop_toTopOf=“parent”
app:srcCompat=“@drawable/ic_keyboard_arrow_right_black_24dp” />
<TextView
android:id=“@+id/textView_title”
android:layout_width=“0dp”
android:layout_height=“wrap_content”
android:layout_marginStart=“8dp”
android:layout_marginLeft=“8dp”
android:layout_marginTop=“8dp”
android:text=“TextView”
android:textSize=“24sp”
app:layout_constraintBottom_toTopOf=“@+id/textView_time”
app:layout_constraintEnd_toStartOf=“@+id/guideline1”
app:layout_constraintHorizontal_bias=“0.05”
app:layout_constraintStart_toStartOf=“parent”
app:layout_constraintTop_toTopOf=“parent” />
<TextView
android:id=“@+id/textView_time”
android:layout_width=“0dp”
android:layout_height=“wrap_content”
android:layout_marginBottom=“8dp”
android:text=“TextView”
app:layout_constraintBottom_toBottomOf=“parent”
app:layout_constraintEnd_toStartOf=“@+id/guideline1”
app:layout_constraintStart_toStartOf=“@+id/textView_title”
app:layout_constraintTop_toBottomOf=“@+id/textView_title” />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
4.2 编写主界面映射Fragment界面

为什么要如许处置处罚?

在fragment中编写好界面后,只需要在main_activity将界面映射过来,之后页面的切换与数据通报交由Navigation作为导航管理Fragment。期间你的路径与与数据设置只需在可视化中简单操纵即可。在main_activity只需要做很少的处置处罚即可

main_activity.xml
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android=“http://schemas.android.com/apk/res/android”
xmlns:app=“http://schemas.android.com/apk/res-auto”
xmlns:tools=“http://schemas.android.com/tools”
android:layout_width=“match_parent”
android:layout_height=“match_parent”
tools:context=“.MainActivity”>
<fragment
android:id=“@+id/fragment”
android:name=“androidx.navigation.fragment.NavHostFragment”
android:layout_width=“0dp”
android:layout_height=“0dp”
app:defaultNavHost=“true”
app:layout_constraintBottom_toBottomOf=“parent”
app:layout_constraintEnd_toEndOf=“parent”
app:layout_constraintStart_toStartOf=“parent”
app:layout_constraintTop_toTopOf=“parent”
app:navGraph=“@navigation/navigation” />
</androidx.constraintlayout.widget.ConstraintLayout>
5.编写RecyclerView的适配器

public class MyAdapt extends ListAdapter<Note, MyAdapt.MyViewHolder> {
public MyAdapt() {
super(new DiffUtil.ItemCallback() {
@Override
public boolean areItemsTheSame(@NonNull Note oldItem, @NonNull Note newItem) {
return oldItem.getId() == newItem.getId();
}
@Override
public boolean areContentsTheSame(@NonNull Note oldItem, @NonNull Note newItem) {
return oldItem.getContent().equals(newItem.getContent()) &&
oldItem.getLastUpdateTime().equals(newItem.getLastUpdateTime());
}
});
}
/**


  • 在适配器中创建 ViewHolder,选择item注入
*/
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
View itemView = layoutInflater.inflate(R.layout.cell_card, parent, false);
return new MyViewHolder(itemView);
}
/**


  • 对每条item进行数据绑定
  • 常常被呼唤,每次滚入滚出都会调用,以是监听绑定放入onCreateViewHolder中
*/
@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
Note note = getItem(position);
holder.textView_title.setText(note.getTitle());
//对日期格式化再输出
@SuppressLint(“SimpleDateFormat”) SimpleDateFormat simpleDateFormat = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”);
holder.textView_time.setText(simpleDateFormat.format(note.getLastUpdateTime()));
holder.itemView.setOnClickListener(v -> {
Bundle bundle = new Bundle();
bundle.putSerializable(“note”, note);
//通报参数
NavController navController = Navigation.findNavController(v);
navController.navigate(R.id.action_notesFragment_to_addFragment, bundle);
});
}
/**


  • 自界说 holder对应 item
  • 内部类最好使用static修饰,防止内存泄漏
*/
static class MyViewHolder extends RecyclerView.ViewHolder {
TextView textView_title, textView_time;
MyViewHolder(@NonNull View itemView) {
super(itemView);
textView_title = itemView.findViewById(R.id.textView_title);
textView_time = itemView.findViewById(R.id.textView_time);
}
}
}
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里不停到现在。
深知大多数初中级安卓工程师,想要提升技能,每每是自己探索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技能停滞不前!
因此网络整理了一份《2024年最新Android移动开辟全套学习资料》送给大家,初衷也很简单,就是盼望可以或许帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。




由于文件比较大,这里只是将部门目录截图出来,每个节点内里都包罗大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)

要如何成为Android架构师?

搭建自己的知识框架,全面提升自己的技能体系,并且往底层源码方向深入研讨。
大多数技能人喜欢用头脑脑图来构建自己的知识体系,一目了然。这里给大家分享一份大厂主流的Android架构师技能体系,可以用来搭建自己的知识框架,或者查漏补缺;

   对应这份技能大纲,我也整理了一套Android高级架构师完备系列的视频教程,主要针对3-5年Android开辟经验以上,需要往高级架构师层次学习提升的同学,在这里点击GitHub免费分享,盼望能帮你突破瓶颈,跳槽进大厂;
  末了我必须强调几点:
1.搭建知识框架可不是说你整理好要学习的知识顺序,然后看一遍明白了能复制粘贴就够了,大多都是需要你自己读懂源码和原理,能自己手写出来的。
2.学习的时候你一定要多看多练几遍,把知识才吃透,还要记笔记,这些很重要! 末了你达到什么水平取决你消化了多少知识
3.终极你的知识框架应该是一个完善的,分身广度和深度的技能体系。然后经过多次项目实战积累经验,你才能达到高级架构师的层次。
你只需要按照在这个大的框架去添补自己,年薪40W一定不是终点,技能无止境
年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里不停到现在。**
深知大多数初中级安卓工程师,想要提升技能,每每是自己探索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技能停滞不前!
因此网络整理了一份《2024年最新Android移动开辟全套学习资料》送给大家,初衷也很简单,就是盼望可以或许帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-f8QSnBMA-1711290026873)]
[外链图片转存中…(img-lji9bg8o-1711290026873)]
[外链图片转存中…(img-hIK8GATK-1711290026874)]
[外链图片转存中…(img-ODoRQWS1-1711290026874)]
由于文件比较大,这里只是将部门目录截图出来,每个节点内里都包罗大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
[外链图片转存中…(img-XZZlzZmW-1711290026874)]
要如何成为Android架构师?

搭建自己的知识框架,全面提升自己的技能体系,并且往底层源码方向深入研讨。
大多数技能人喜欢用头脑脑图来构建自己的知识体系,一目了然。这里给大家分享一份大厂主流的Android架构师技能体系,可以用来搭建自己的知识框架,或者查漏补缺;
[外链图片转存中…(img-DM0dBjbt-1711290026874)]
   对应这份技能大纲,我也整理了一套Android高级架构师完备系列的视频教程,主要针对3-5年Android开辟经验以上,需要往高级架构师层次学习提升的同学,在这里点击GitHub免费分享,盼望能帮你突破瓶颈,跳槽进大厂;
  末了我必须强调几点:
1.搭建知识框架可不是说你整理好要学习的知识顺序,然后看一遍明白了能复制粘贴就够了,大多都是需要你自己读懂源码和原理,能自己手写出来的。
2.学习的时候你一定要多看多练几遍,把知识才吃透,还要记笔记,这些很重要! 末了你达到什么水平取决你消化了多少知识
3.终极你的知识框架应该是一个完善的,分身广度和深度的技能体系。然后经过多次项目实战积累经验,你才能达到高级架构师的层次。
你只需要按照在这个大的框架去添补自己,年薪40W一定不是终点,技能无止境

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

温锦文欧普厨电及净水器总代理

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表