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

相关文章
|
1月前
|
搜索推荐 前端开发 API
探索安卓开发中的自定义视图:打造个性化用户界面
在安卓应用开发的广阔天地中,自定义视图是一块神奇的画布,让开发者能够突破标准控件的限制,绘制出独一无二的用户界面。本文将带你走进自定义视图的世界,从基础概念到实战技巧,逐步揭示如何在安卓平台上创建和运用自定义视图来提升用户体验。无论你是初学者还是有一定经验的开发者,这篇文章都将为你打开新的视野,让你的应用在众多同质化产品中脱颖而出。
57 19
|
1月前
|
JSON Java API
探索安卓开发:打造你的首个天气应用
在这篇技术指南中,我们将一起潜入安卓开发的海洋,学习如何从零开始构建一个简单的天气应用。通过这个实践项目,你将掌握安卓开发的核心概念、界面设计、网络编程以及数据解析等技能。无论你是初学者还是有一定基础的开发者,这篇文章都将为你提供一个清晰的路线图和实用的代码示例,帮助你在安卓开发的道路上迈出坚实的一步。让我们一起开始这段旅程,打造属于你自己的第一个安卓应用吧!
66 14
|
1月前
|
开发框架 Android开发 iOS开发
安卓与iOS开发中的跨平台策略:一次编码,多平台部署
在移动应用开发的广阔天地中,安卓和iOS两大阵营各占一方。随着技术的发展,跨平台开发框架应运而生,它们承诺着“一次编码,到处运行”的便捷。本文将深入探讨跨平台开发的现状、挑战以及未来趋势,同时通过代码示例揭示跨平台工具的实际运用。
123 3
|
1月前
|
搜索推荐 前端开发 测试技术
打造个性化安卓应用:从设计到开发的全面指南
在这个数字时代,拥有一个定制的移动应用不仅是一种趋势,更是个人或企业品牌的重要延伸。本文将引导你通过一系列简单易懂的步骤,从构思你的应用理念开始,直至实现一个功能齐全的安卓应用。无论你是编程新手还是希望拓展技能的开发者,这篇文章都将为你提供必要的工具和知识,帮助你将创意转化为现实。
|
1月前
|
Java Android开发 开发者
探索安卓开发:构建你的第一个“Hello World”应用
在安卓开发的浩瀚海洋中,每个新手都渴望扬帆起航。本文将作为你的指南针,引领你通过创建一个简单的“Hello World”应用,迈出安卓开发的第一步。我们将一起搭建开发环境、了解基本概念,并编写第一行代码。就像印度圣雄甘地所说:“你必须成为你希望在世界上看到的改变。”让我们一起开始这段旅程,成为我们想要见到的开发者吧!
42 0
|
XML Android开发 数据格式
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
1458 0
|
SQL 数据库 Android开发
Android记事本开发之SQLite数据库实现
package com.jk.service; /** * 完成数据库的创建和版本更新 */ import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase.CursorFactory; import
1617 0
|
Android开发 索引 数据库
Android记事本开发
数据库实现部分          界面设计 package com.jk; import java.util.List; import android.app.AlertDialog; import android.app.ListActivity; import android.content.Context; import android.content.DialogInterfa
1007 0
|
2月前
|
开发框架 前端开发 Android开发
安卓与iOS开发中的跨平台策略
在移动应用开发的战场上,安卓和iOS两大阵营各据一方。随着技术的演进,跨平台开发框架成为开发者的新宠,旨在实现一次编码、多平台部署的梦想。本文将探讨跨平台开发的优势与挑战,并分享实用的开发技巧,帮助开发者在安卓和iOS的世界中游刃有余。
|
2月前
|
缓存 前端开发 Android开发
安卓开发中的自定义视图:从零到英雄
【10月更文挑战第42天】 在安卓的世界里,自定义视图是一块画布,让开发者能够绘制出独一无二的界面体验。本文将带你走进自定义视图的大门,通过深入浅出的方式,让你从零基础到能够独立设计并实现复杂的自定义组件。我们将探索自定义视图的核心概念、实现步骤,以及如何优化你的视图以提高性能和兼容性。准备好了吗?让我们开始这段创造性的旅程吧!
39 1