Android

Android JetPack学习总结(九)

Room(五)

将数据修改应用到UI

数据库中已经增加一条chinese_invisible的字段,用于记录中文意思是否显示。在ui中用一个switch来操作这一个数据段。

在recyclerView中,会给每一个switch绑定一个监听器,并且也会根据数据库中的字段来设置这个switch的初始状态。由于recyclerView是循环使用的,所以这个初始化操作可能会触发监听器,以改变数据库内容,为了解决这个bug,可以在初始化之前先将监听器设置为null:

@Override
    public void onBindViewHolder(@NonNull final MyViewHolder holder, final int position) {
        final Word word=allWords.get(position);
        holder.textViewNumber.setText(String.valueOf(position+1));
        holder.textViewEnglish.setText(word.getWord());
        holder.textViewChinese.setText(word.getChineseMeaning());
        holder.aSwitchChineseInvisible.setOnCheckedChangeListener(null);//!!防止回收的recyclerView会触发listener
        if (word.isChineseInvisible()){
            holder.textViewChinese.setVisibility(View.GONE);
            holder.aSwitchChineseInvisible.setChecked(true);
        }else {
            holder.textViewChinese.setVisibility(View.VISIBLE);
            holder.aSwitchChineseInvisible.setChecked(false);
        }
        holder.aSwitchChineseInvisible.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
                if (b){
                    holder.textViewChinese.setVisibility(View.GONE);
                    word.setChineseInvisible(true);
                }else {
                    holder.textViewChinese.setVisibility(View.VISIBLE);
                    word.setChineseInvisible(false);
                }
                wordViewModel.updateWords(word);
            }
        });
    }

由于ViewModel是利用LiveData来存储数据的,修改chineseInvisible的值,会导致LiveData的Observer被触发、更新UI,这样会在一个时间内进行两次UI的更新,会导致应用卡顿。很明显修改chineseInvisible不会导致数据元组数量改变,因此不需要去更新Apapter,可以在LiveData的Observe方法中取消修改操作会导致的UI更新。

//MainActivity
wordViewModel.getAllWordsLive().observe(this, new Observer<List<Word>>() {
            @Override
            public void onChanged(List<Word> words) {
                //在adapter中修改switch时也会触发这里更新视图,可以跳过修改操作
                int temp=myAdapter1.getItemCount();
                myAdapter1.setAllWords(words);
                myAdapter2.setAllWords(words);
                if (temp!=words.size()){
                    myAdapter2.notifyDataSetChanged();//通知数据更新
                    myAdapter1.notifyDataSetChanged();//通知数据更新
                }

            }
        });
扩大Switch的响应范围

可以设置switch的高度为match_constraint,宽度用padding来设置(宽度用match_constraint会导致switch右侧靠拢)。

image 4
image 5
添加分割线

使用Android自带的widgets中的Vertical DIvider,参数如下

image 6
<View
        android:id="@+id/divider"
        android:layout_width="1dp"
        android:layout_height="match_parent"
        android:layout_marginTop="8dp"
        android:layout_marginBottom="8dp"
        android:background="?android:attr/listDivider"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@+id/constraintLayout"
        app:layout_constraintStart_toStartOf="@+id/guideline6"
        app:layout_constraintTop_toTopOf="parent" />
image 7

发表评论