Android MVVM框架使用(十一)(功能开发)记事本

简介: Android MVVM框架使用(十一)(功能开发)记事本

前言


 对于一些常规的MVVM框架搭建也有一些了,那么对于一些小功能的开发也需要说明一下,注重实践,本文实践一下。一个功能并不一定能一篇文章就能写完。


在写之前先来看看完成后的效果图吧,如下图所示:


1026d0616e624630aff21712ee64500f.gif


正文


 从标题就看到了记事本的功能,这个功能还是比较有实用价值的,虽然每一个手机都自带这个功能,但依然有人去开发,因为这个功能可以考察开发者的一些基本功,从代码上业务需求上都可以考察到,很多的毕业设计就是搞一个记事本,还有我之前写的天气App和垃圾分类App也有类似的毕设,学习是好的,但要有自己的思考,写一个功能的时候要想一些细节。


我们先来定一下功能需求:创建笔记、删除笔记、修改笔记、显示笔记。


暂定这些功能点,那么我们应用要有一张表去操作笔记,主要实现功能就是增删改查。下面来实现这些功能,建议你不要直接看源码,有时候过程和思路比结果更重要。


一、记事本页面


既然要写一个记事本,那么首先要创建一个页面,我的代码依然还是写在MVVM框架中的,在activity包下新建一个NotebookActivity,对应的布局是activity_notebook.xml,下面我们先修改布局代码:


<?xml version="1.0" encoding="utf-8"?>
<layout 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">
    <data>
        <variable
            name="hasNotebook"
            type="Boolean" />
        <import type="android.view.View" />
    </data>
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true"
        android:orientation="vertical"
        tools:context=".ui.activity.NotebookActivity">
        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="@color/white"
            app:navigationIcon="@drawable/icon_back_black">
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:text="记事本"
                android:textColor="@color/black"
                android:textSize="18sp"
                android:textStyle="bold" />
        </androidx.appcompat.widget.Toolbar>
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_below="@+id/toolbar"
            android:background="@color/gray_white"
            android:orientation="vertical">
            <!--笔记列表-->
            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/rv_notebook"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:overScrollMode="never"
                android:paddingStart="8dp"
                android:visibility="@{hasNotebook ? View.VISIBLE : View.GONE}"
                android:paddingEnd="8dp"
                android:paddingTop="8dp" />
            <!--没有记录布局-->
            <LinearLayout
                android:id="@+id/lay_no_record"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:gravity="center"
                android:visibility="@{hasNotebook ? View.GONE : View.VISIBLE}"
                android:orientation="vertical">
                <ImageView
                    android:layout_width="96dp"
                    android:layout_height="96dp"
                    android:src="@mipmap/icon_no_record" />
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="4dp"
                    android:text="没有记录"
                    android:textColor="@color/dark_gray"
                    android:textSize="16sp" />
            </LinearLayout>
        </RelativeLayout>
        <com.google.android.material.floatingactionbutton.FloatingActionButton
            android:id="@+id/fab_add_notebook"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentEnd="true"
            android:layout_alignParentBottom="true"
            android:layout_margin="20dp"
            android:onClick="toEdit"
            android:src="@mipmap/icon_add"
            app:backgroundTint="@color/white"
            tools:ignore="UsingOnClickInXml" />
    </RelativeLayout>
</layout>


这里用到的图标去我源码中拿,我贴出来就不是png了,然后进入AndroidManifest.xml中去修改页面样式,给NotebookActivity增加一个主题,如下图所示:


ddab65edee1f4691afc2a8f3bf384dd4.png


再修改一下代码,下面修改NotebookActivity中的代码,如下图所示:


b59663b8e6d34985a8e24dcb230cd564.png


这里继承了BaseActivity,然后使用了ViewBinding和状态栏设置,还有返回监听。运行一下:


bad25062066a4676904e49ceffbdef3b.png


这里现在没有数据,先不管它,看到右下角有一个按钮,这个按钮点击之后进行日记编辑,增加记事。下面来写这个功能,也就是增加。


二、编辑页面


 编辑页面可用于新增笔记、查看笔记、修改笔记、删除笔记,一个页面要具备这些功能,是需要好好设计一下的,先完成简单的界面设计。这里同样要新增一个Activity,在activity包下新增一个EditActivity,对应的布局是activity_edit.xml,因为编辑页面中有两个输入框,因此我需要改一下默认的输入框光标样式。在drawable下新增一个custom_cursor.xml,代码如下:


<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <size android:width="1dp" />
    <solid android:color="@color/purple_700" />
</shape>


然后我们修改一下activity_edit.xml中的代码:


<?xml version="1.0" encoding="utf-8"?>
<layout 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">
    <data>
    </data>
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true"
        tools:context=".ui.activity.EditActivity">
        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="@color/white"
            app:navigationIcon="@mipmap/ic_edit_return">
            <ImageView
                android:id="@+id/iv_ok"
                android:layout_width="36dp"
                android:layout_height="36dp"
                android:layout_gravity="end"
                android:layout_marginEnd="16dp"
                android:foreground="?attr/selectableItemBackground"
                android:padding="4dp"
                android:src="@mipmap/ic_black_ok"
                android:visibility="gone" />
        </androidx.appcompat.widget.Toolbar>
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_below="@+id/toolbar"
            android:orientation="vertical"
            android:paddingStart="12dp"
            android:paddingEnd="16dp">
            <androidx.appcompat.widget.AppCompatEditText
                android:id="@+id/et_title"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@null"
                android:hint="标题"
                android:textColor="@color/black"
                android:textColorHint="@color/black"
                android:textCursorDrawable="@drawable/custom_cursor"
                android:textSize="36sp" />
            <androidx.appcompat.widget.AppCompatEditText
                android:id="@+id/et_content"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_below="@+id/et_title"
                android:background="@null"
                android:cursorVisible="true"
                android:gravity="top"
                android:paddingTop="4dp"
                android:textCursorDrawable="@drawable/custom_cursor" />
        </LinearLayout>
    </RelativeLayout>
</layout>


这个布局里面用到的图标依然到我的源码里面去找,我就不贴了。


同时也需要改一个AndroidManifest.xml中的NotebookActivity的主题,如下图所示:


6b1c695887f744f6b2a6683df3bae02d.png


然后我们修改一下EditActivity中的代码:


public class EditActivity extends BaseActivity implements View.OnClickListener {
    private ActivityEditBinding binding;
    private InputMethodManager inputMethodManager;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = DataBindingUtil.setContentView(this, R.layout.activity_edit);
        setStatusBar(true);
        back(binding.toolbar);
        //新增时 获取焦点
        showInput();
        initView();
    }
    private void initView() {
        //监听输入
        listenInput(binding.etTitle);
        listenInput(binding.etContent);
        binding.ivOk.setOnClickListener(this);
    }
    /**
     * 监听输入
     * @param editText 输入框
     */
    private void listenInput(final AppCompatEditText editText) {
        editText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }
            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
            }
            @Override
            public void afterTextChanged(Editable s) {
                if (s.length() > 0) {
                    binding.ivOk.setVisibility(View.VISIBLE);
                } else {
                    if (binding.etTitle.getText().length() == 0 && binding.etContent.getText().length() == 0  ){
                        binding.ivOk.setVisibility(View.GONE);
                    }
                }
            }
        });
    }
    /**
     * 显示键盘
     */
    public void showInput() {
        binding.etContent.requestFocus();
        inputMethodManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
        inputMethodManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
    }
    /**
     * 隐藏键盘
     */
    public void dismiss() {
        if (inputMethodManager != null) {
            inputMethodManager.hideSoftInputFromWindow(binding.etContent.getWindowToken(), 0);    
        }
    }
    @Override
    protected void onPause() {
        super.onPause();
        dismiss();
    }
    @Override
    public void onBackPressed() {
        super.onBackPressed();
        dismiss();
    }
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.iv_ok://提交
                showMsg("提交");
                break;
        }
    }
}


这个页面的逻辑当前是这样的,有两个输入框,一个是标题一个是内容,当输入框有输入的时候显示一个提交按钮,当没有输入或者输入框为空的时候隐藏这个提交按钮,还有一个就是一进入当前页面,就显示内容的输入框光标,同时弹出软键盘。


这个页面也需要一个入口,也就是记事本页面点击右下角的按钮跳转过来,在activity_notebook.xml中修改浮动按钮的onClick事件。


1a074b6d45fb41d3a266ca79d13efb01.png


这里是一个toEdit,然后在NotebookActivity中新增一个toEdit方法


/**
     * 去编辑
     */
    public void toEdit(View view) {
        jumpActivity(EditActivity.class);
    }


当然了,我们的NotebookActivity也需要一个入口,在我的MVVM中我就在侧滑菜单中增加入口,首先增加一个路径图标,在drawable下新增一个icon_notebook.xml,代码如下:


<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:autoMirrored="true"
    android:tint="#000000"
    android:viewportWidth="24.0"
    android:viewportHeight="24.0">
    <path
        android:fillColor="@android:color/white"
        android:pathData="M14.17,3H5C3.9,3 3,3.9 3,5v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2V9.83c0,-0.53 -0.21,-1.04 -0.59,-1.41l-4.83,-4.83C15.21,3.21 14.7,3 14.17,3L14.17,3zM8,15h8c0.55,0 1,0.45 1,1v0c0,0.55 -0.45,1 -1,1H8c-0.55,0 -1,-0.45 -1,-1v0C7,15.45 7.45,15 8,15zM8,11h8c0.55,0 1,0.45 1,1v0c0,0.55 -0.45,1 -1,1H8c-0.55,0 -1,-0.45 -1,-1v0C7,11.45 7.45,11 8,11zM8,7h5c0.55,0 1,0.45 1,1v0c0,0.55 -0.45,1 -1,1H8C7.45,9 7,8.55 7,8v0C7,7.45 7.45,7 8,7z" />
</vector>


然后在nav_menu.xml中新增代码:


<item
        android:id="@+id/item_notebook"
        android:icon="@drawable/icon_notebook"
        android:title="记事本" />


添加位置如下图所示:


66fc9897bff443ac803c9a79071d7ac3.png


最后在HomeActivity中修改一下菜单点击代码,如下图所示:


70767c83dfba44cbbffb5b4e50a78ab0.png


下面我们运行一下:


84e52549d2b44e08b277f4be63c94996.gif


编辑页面写好了,需要写具体的功能了,这需要在数据库中一个笔记表。


三、增加笔记表


① Bean


 首先在bean包下新增一个Notebook类,代码如下:


@Entity(tableName = "notebook")
public class Notebook {
    @PrimaryKey(autoGenerate = true)
    private int uid;
    private String title;
    private String content;
    public int getUid() {
        return uid;
    }
    public void setUid(int uid) {
        this.uid = uid;
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public String getContent() {
        return content;
    }
    public void setContent(String content) {
        this.content = content;
    }
    @Ignore
    public Notebook(String title, String content) {
        this.title = title;
        this.content = content;
    }
    public Notebook() {}
}


这目前的表中我只设置了两个主要字段,标题和内容,uid自增。


② Dao


下面就是数据表的操作接口类,在dao包下新建一个NotebookDao接口,代码如下:


@Dao
public interface NotebookDao {
    @Query("SELECT * FROM notebook")
    Flowable<List<Notebook>> getAll();
    @Update
    Completable update(Notebook notebook);
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    Completable insert(Notebook notebook);
    @Delete
    Completable delete(Notebook notebook);
}


这里就是增删改查,相信你已经很熟悉了,如果你是从之前的文章一路看过来的话。


③ 数据库升级迁移


打开AppDatabase首先增加表和版本升级,如下图所示:


74e4d2a00e53467ba0d7622967a5d49f.png


下面增加刚才的Dao的实现,一行代码搞定,如下图所示:

public abstract NotebookDao notebookDao();


然后是数据库升级迁移,代码如下:


/**
     * 版本升级迁移到6 在数据库中新增一个笔记表
     */
    static final Migration MIGRATION_5_6 = new Migration(5, 6) {
        @Override
        public void migrate(@NonNull @NotNull SupportSQLiteDatabase database) {
            //创建笔记表
            database.execSQL("CREATE TABLE `notebook` " +
                    "(uid INTEGER NOT NULL, " +
                    "title TEXT, " +
                    "content TEXT, " +
                    "PRIMARY KEY(`uid`))");
        }
    };


最后添加迁移,如下图所示:


6f9ffb29bec247ada89788cb7cc55127.png


数据库搞定了,下面就是存储库了。


④ 新增存储库类


在repository包下新建一个NotebookRepository类,里面的代码如下:


public class NotebookRepository {
    private static final String TAG = NotebookRepository.class.getSimpleName();
    @Inject
    NotebookRepository() {}
    private final MutableLiveData<Notebook> notebookLiveData = new MutableLiveData<>();
    private final MutableLiveData<List<Notebook>> notebooksMutableLiveData = new MutableLiveData<>();
    public final MutableLiveData<String> failed = new MutableLiveData<>();
  public final List<Notebook> emptyList = new ArrayList<>();
    /**
     * 添加笔记
     */
    public void saveNotebook(Notebook notebook) {
        //保存到数据库
        Completable insert = BaseApplication.getDb().notebookDao().insert(notebook);
        //RxJava处理Room数据存储
        CustomDisposable.addDisposable(insert, () -> Log.d(TAG, "saveNotebook: 笔记数据保存成功"));
    }
    /**
     * 获取所有笔记
     */
    public MutableLiveData<List<Notebook>> getNotebooks() {
        Flowable<List<Notebook>> listFlowable = BaseApplication.getDb().notebookDao().getAll();
        CustomDisposable.addDisposable(listFlowable, notebooks -> {
            if (notebooks.size() > 0) {
                notebooksMutableLiveData.postValue(notebooks);
            } else {
                notebooksMutableLiveData.postValue(emptyList);
                failed.postValue("暂无数据");
            }
        });
        return notebooksMutableLiveData;
    }
}


这里存储里面现在是两个方法,一个用于查询,一个用于添加。然后就是新建ViewModel去操作这个存储库。


⑤ 新增ViewModel


这里其实有两个ViewModel,一个对应EditActivity,一个对应NotebookActivity,首先在viewmodels包下创建一个EditViewModel类,代码如下:


public class EditViewModel extends BaseViewModel {
    private final NotebookRepository notebookRepository;
    @ViewModelInject
    EditViewModel(NotebookRepository notebookRepository){
        this.notebookRepository = notebookRepository;
    }
    /**
     * 添加笔记
     */
    public void addNotebook(Notebook notebook) {
      failed = notebookRepository.failed;
        notebookRepository.saveNotebook(notebook);
    }
}


然后同样在viewmodels包下创建NotebookViewModel类,代码如下:


public class NotebookViewModel extends BaseViewModel {
    private final NotebookRepository notebookRepository;
    public LiveData<List<Notebook>> notebooks;
    @ViewModelInject
    NotebookViewModel(NotebookRepository notebookRepository){
        this.notebookRepository = notebookRepository;
    }
    public void getNotebooks() {
        failed = notebookRepository.failed;
        notebooks = notebookRepository.getNotebooks();
    }
}


⑥ 添加笔记


首先需要把EditViewModel与EditActivity进行绑定,如下图所示:


3ab2cfb81ac64627a79ce82e68224aad.png


然后就是很简单的时候,在点击右上角按钮时,进行保存笔记,在EditActivity中修改一下代码,如下图所示:


89f85a42f92c4aaea99da9b60327980b.png


这里我是保存了数据之后关掉当前页面,就会返回到之前的NotebookActivity,那么在这个页面就需要搜索当前数据库的表,然后通过列表加载出来。


四、显示笔记列表


 既然是一个列表,那么自然就需要有一个item的布局,在layout下新建一个item_notebook.xml,里面的代码如下:


<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable
            name="notebook"
            type="com.llw.mvvm.db.bean.Notebook" />
        <!--点击事件-->
        <variable
            name="onClick"
            type="com.llw.mvvm.ui.adapter.NotebookAdapter.ClickBinding" />
    </data>
    <RelativeLayout
        android:id="@+id/detail"
        android:foreground="?attr/selectableItemBackground"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="8dp"
        android:background="@drawable/shape_bg_white_radius_12"
        android:onClick="@{() -> onClick.itemClick(notebook,detail)}"
        android:padding="12dp">
        <TextView
            android:id="@+id/tv_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ellipsize="end"
            android:singleLine="true"
            android:text="@{notebook.title}"
            android:textColor="@color/black"
            android:textSize="16sp" />
        <TextView
            android:id="@+id/tv_content"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/tv_title"
            android:layout_marginTop="4dp"
            android:ellipsize="end"
            android:maxLines="3"
            android:text="@{notebook.content}"
            android:textSize="14sp" />
    </RelativeLayout>
</layout>


布局很简单,就是显示标题和内容,采用databinding的方式赋值,下面创建适配器,在adapter包下新建一个NotebookAdapter类,里面的代码如下:


public class NotebookAdapter extends BaseQuickAdapter<Notebook, BaseDataBindingHolder<ItemNotebookBinding>> {
    public NotebookAdapter(@Nullable List<Notebook> data) {
        super(R.layout.item_notebook, data);
    }
    @Override
    protected void convert(@NotNull BaseDataBindingHolder<ItemNotebookBinding> bindingHolder, Notebook notebook) {
        ItemNotebookBinding binding = bindingHolder.getDataBinding();
        if (binding != null) {
            binding.setNotebook(notebook);
            binding.setOnClick(new NotebookAdapter.ClickBinding());
            binding.executePendingBindings();
        }
    }
    public static class ClickBinding {
        public void itemClick(Notebook notebook, View view) {
        }
    }
}


这个代码也是很简单的,就是绑定数据绑定布局,下面就是显示列表了,也很简单,回到NotebookActivity,增加三个变量并添加了一个注解,如下图所示:


1fe38e57bc3d4951bcbace91e5661480.png


修改代码,如下图所示:


9a858f8afd39489da29fe88cd76daacf.png


首先是绑定ViewModel,然后在onResume的生命周期查询数据库中的数据,在编辑页面对数据进行修改之后会销毁掉,然后就会显示NotebookActivity,会触发onResume,再去查询一次数据。然后监听数据,有数据则加载列表,没有就显示那个空内容布局。下面来运行一下看看效果如何。


a400994a8ae14b76b03956f642db5ee5.gif


还是可以的吧,下面要做的就是修改笔记。


五、修改笔记


 修改笔记的前提是要查询到要修改的笔记,通过id进行查询,然后完成修改,说起来是挺简单的,当然了,实现起来也很简单,我们来实现吧。首先是列表item的点击事件,点击之后传递uid到EditActivity,通过通过uid去得到Notebook。


在NotebookAdapater中增加如下图所示代码:


6e32a0fa66bc486292b56221ab173596.png


因为我们的NotebookDao中并没有通过id查询笔记的方法,因此我们在NotebookDao中新加一个,代码如下:


@Query("SELECT * FROM notebook WHERE uid=:uid")
    Flowable<Notebook> findById(int uid);


然后去NotebookRepository中去对方法进行实现,这里我们需要实现两个方法,一个用于通过id查询,一个用于修改,在NotebookRepository中新增如下代码:


/**
     * 根据id获取笔记
     * @param uid id
     */
    public MutableLiveData<Notebook> getNotebookById(int uid) {
        Flowable<Notebook> flowable = BaseApplication.getDb().notebookDao().findById(uid);
        CustomDisposable.addDisposable(flowable, notebook -> {
           if (notebook != null) {
               notebookLiveData.postValue(notebook);
           } else {
               failed.postValue("未查询到笔记");
           }
        });
        return notebookLiveData;
    }
    /**
     * 更新笔记
     *
     * @param notebook
     */
    public void updateNotebook(Notebook notebook) {
        Completable update = BaseApplication.getDb().notebookDao().update(notebook);
        CustomDisposable.addDisposable(update, () -> {
            Log.d(TAG, "updateNotebook: " + "更新成功");
            failed.postValue("200");
        });
    }


存储库的方法写好了,下面就是在EditViewModel中去调用了,进入EditViewModel,新增如下代码:


public LiveData<Notebook> notebook;
  /**
     * 根据Id搜索笔记
     */
    public void queryById(int uid) {
        failed = notebookRepository.failed;
        notebook = notebookRepository.getNotebookById(uid);
    }
    /**
     * 更新笔记
     */
    public void updateNotebook(Notebook notebook) {
        failed = notebookRepository.failed;
        notebookRepository.updateNotebook(notebook);
    }


这个代码就没啥好说的,见过很多类似的了,最后就是在EditActivity。


进入EditActivity中,新增两个变量:


private int uid;
    private Notebook mNotebook;


首先要处理uid的问题,因为我们点击新增笔记和笔记笔记都是进入这个页面,所以要分情况处理。


1c162604b9fc418c9ba68691353806c6.png


这里我把showInput从移除掉了,根据现在的业务逻辑它不应该在onCreate中调用了,需要在initView方法中,下面我们看看怎么去修改。


2e3fb3f71dc94101a5d34eca376bdb8b.png


如图所示,这里获取uid,如果为-1表示为新增,否则就是更新。是更新的话就通过查询id然后观察返回的数据变化。


这里的binding.setNotebook(mNotebook);是直接通过单向绑定对控件进行赋值,因此这里需要修改一下activity_edit.xml中的代码:


bfd8cbbb741d48d3bd9078bf1c09b431.png

0bafc083ddcc40a7a38337259b6f894f.png


最后我们修改一下确定按钮的业务逻辑,如下图所示:


2f6e23ca5dd94423a37f547dd273d500.png


这个-1是用来做什么的我就不再多说了,这里修改数据之后,依然后关闭当前页面。我们的代码写完了,运行一下吧。


b248549565e54051b1df143f2b18330d.gif


修改就完成了,下面就是删除了。


六、删除笔记


 删除的方法之前就写好了,因此Dao中不需要改动了,只要在NotebookRepository中增加删除的方法即可,代码如下:


/**
     * 删除笔记
     */
    public void deleteNotebook(Notebook notebook) {
        Completable delete = BaseApplication.getDb().notebookDao().delete(notebook);
        CustomDisposable.addDisposable(delete, () -> {
            Log.d(TAG, "deleteNotebook: " + "删除成功");
            failed.postValue("200");
        });
    }


然后是EditViewModel中去调用,在EditViewModel中新增代码如下所示:


/**
     * 删除笔记
     */
    public void deleteNotebook(Notebook notebook) {
        notebookRepository.deleteNotebook(notebook);
        failed = notebookRepository.failed;
    }


下面就是在EditActivity中去调用EditViewModel中的deleteNotebook方法,在标题哪里添加一个按钮,修改activity_edit.xml,代码如下:


<!--删除按钮-->
            <ImageView
                android:id="@+id/iv_delete"
                android:layout_width="36dp"
                android:layout_height="36dp"
                android:layout_gravity="end"
                android:layout_marginEnd="16dp"
                android:foreground="?attr/selectableItemBackground"
                android:padding="2dp"
                android:src="@mipmap/ic_delete"
                android:visibility="gone" />


注意添加的位置:


7c43c2f520e048eda64e68f6f93ae4f6.png


然后是修改EditActivity中的代码,主要就是注册按钮的监听,然后是调用删除的方法。


5c965ba77bea4fe1893d37a0c98c3fd2.png


删除笔记


96105fca256f43c299b741b9a5b05e95.png


运行一下:


f82e038b123c49b2a639a468a553beaa.gif


OK了,本篇文章就到这里了,下一篇可能会对记事本功能进行一个优化,主要是用户体验方面,时隔近一个月,再写文章时花费的时间依然很多,久违了的感觉。今天是周五了,周末愉快啊。

目录
打赏
0
1
0
0
27
分享
相关文章
Termux安卓终端美化与开发实战:从下载到插件优化,小白也能玩转Linux
Termux是一款安卓平台上的开源终端模拟器,支持apt包管理、SSH连接及Python/Node.js/C++开发环境搭建,被誉为“手机上的Linux系统”。其特点包括零ROOT权限、跨平台开发和强大扩展性。本文详细介绍其安装准备、基础与高级环境配置、必备插件推荐、常见问题解决方法以及延伸学习资源,帮助用户充分利用Termux进行开发与学习。适用于Android 7+设备,原创内容转载请注明来源。
226 76
布谷一对一直播源码android版环境配置流程及功能明细
部署需基于 CentOS 7.9 系统,硬盘不低于 40G,使用宝塔面板安装环境,包括 PHP 7.3(含 Redis、Fileinfo 扩展)、Nginx、MySQL 5.6、Redis 和最新 Composer。Swoole 扩展需按步骤配置。2021.08.05 后部署需将站点目录设为 public 并用 ThinkPHP 伪静态。开发环境建议 Windows 操作系统与最新 Android Studio,基础配置涉及 APP 名称修改、接口域名更换、包名调整及第三方登录分享(如 QQ、微信)的配置,同时需完成阿里云与腾讯云相关设置。
当flutter react native 等混开框架-并且用vscode-idea等编译器无法打包apk,打包安卓不成功怎么办-直接用android studio如何打包安卓apk -重要-优雅草卓伊凡
当flutter react native 等混开框架-并且用vscode-idea等编译器无法打包apk,打包安卓不成功怎么办-直接用android studio如何打包安卓apk -重要-优雅草卓伊凡
106 36
当flutter react native 等混开框架-并且用vscode-idea等编译器无法打包apk,打包安卓不成功怎么办-直接用android studio如何打包安卓apk -重要-优雅草卓伊凡
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
79 8
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
70 4
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
escrcpy:【技术党必看】Android开发,Escrcpy 让你无线投屏新体验!图形界面掌控 Android,30-120fps 超流畅!🔥
escrcpy 是一款基于 Scrcpy 的开源项目,使用 Electron 构建,提供图形化界面来显示和控制 Android 设备。它支持 USB 和 Wi-Fi 连接,帧率可达 30-120fps,延迟低至 35-70ms,启动迅速且画质清晰。escrcpy 拥有丰富的功能,包括自动化任务、多设备管理、反向网络共享、批量操作等,无需注册账号或广告干扰。适用于游戏直播、办公协作和教育演示等多种场景,是一款轻量级、高性能的 Android 控制工具。
104 1
Android记事本开发之界面设计
不得不提一下ADT自带的手机截屏很方便,就在DDMS里可以找到。 main.xml &lt;?xml version="1.0" encoding="utf-8"?&gt; &lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="v
1467 0
Android记事本开发之SQLite数据库实现
package com.jk.service; /** * 完成数据库的创建和版本更新 */ import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase.CursorFactory; import
1633 0
Android记事本开发
数据库实现部分          界面设计 package com.jk; import java.util.List; import android.app.AlertDialog; import android.app.ListActivity; import android.content.Context; import android.content.DialogInterfa
1015 0
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
212 20
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等