教程地址:https://www.bilibili.com/video/av65180549

源码地址:https://github.com/longway777/Android-2019-Tutorial-RoomBasic-step-3

RecyclerView 是一个回收视图,当滚动出屏幕外面的内容会自动回收,回收系统资源

相同的内容,支持用不同的样式来呈现!

创建2个 Layout 资源文件

<?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="wrap_content"
android:background="?attr/selectableItemBackground"
android:clickable="true"> <androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.1" /> <androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.85" /> <TextView
android:id="@+id/textViewNumber"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/guideline2"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="1" /> <TextView
android:id="@+id/textViewEnglish"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="TextView"
android:textSize="18sp"
app:layout_constraintBottom_toTopOf="@+id/textViewChinese"
app:layout_constraintEnd_toStartOf="@+id/guideline3"
app:layout_constraintHorizontal_bias="0.1"
app:layout_constraintStart_toStartOf="@+id/guideline2"
app:layout_constraintTop_toTopOf="parent" /> <TextView
android:id="@+id/textViewChinese"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:text="TextView"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="@+id/textViewEnglish"
app:layout_constraintTop_toBottomOf="@+id/textViewEnglish" /> <ImageView
android:id="@+id/imageView2"
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/guideline3"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_chevron_right_black_24dp" />
</androidx.constraintlayout.widget.ConstraintLayout>

  

<?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:background="?attr/selectableItemBackground"
android:clickable="true"
android:orientation="vertical"> <androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:foreground="?selectableItemBackground"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"> <androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"> <androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.10948905" /> <androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.85" /> <TextView
android:id="@+id/textViewNumber"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/guideline4"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="1" /> <TextView
android:id="@+id/textViewEnglish"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="TextView"
android:textSize="24sp"
app:layout_constraintBottom_toTopOf="@+id/textViewChinese"
app:layout_constraintEnd_toStartOf="@+id/guideline5"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="@+id/guideline4"
app:layout_constraintTop_toTopOf="parent" /> <TextView
android:id="@+id/textViewChinese"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:text="TextView"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="@+id/textViewEnglish"
app:layout_constraintTop_toBottomOf="@+id/textViewEnglish" /> <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/guideline5"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_chevron_right_black_24dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>

  

2.创建 适配器 Adapter类 ,继承自  RecylerView.Adapter ,是 RecyclerView 的内容管理器

package com.example.roombasic;

import android.content.Intent;
import android.net.Uri;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView; import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView; import java.util.ArrayList;
import java.util.List; public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> { //用来存放数据的列表
List<Word> allWords = new ArrayList<>();
boolean use_CellCard; //是否使用 cell_card 这个样式 public MyAdapter(boolean use_CellCard) {
this.use_CellCard = use_CellCard;
} public void setAllWords(List<Word> allWords) {
this.allWords = allWords;
} @NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
//
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext()); //用开关控件,控制不同的样式
View itemView ;
if(use_CellCard)
itemView = layoutInflater.inflate(R.layout.cell_card,parent,false);
else
itemView = layoutInflater.inflate(R.layout.cell_normal,parent,false); return new MyViewHolder(itemView);
} //数据绑定
@Override
public void onBindViewHolder(@NonNull final MyViewHolder holder, 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.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Uri uri = Uri.parse("http://m.youdao.com/dict?le=eng&q=" + holder.textViewEnglish.getText()); Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(uri); holder.itemView.getContext().startActivity(intent);
}
}); } //返回列表数据的总个数
@Override
public int getItemCount() {
return allWords.size();
} // 因为需要管理三个内容,左边的数字,右上英文,右下汉字,所以创建三个值来管理
// 创建一个属于 Adapter 自身的 ViewHolder
//加 static 防内存泄漏
static class MyViewHolder extends RecyclerView.ViewHolder{ TextView textViewNumber,textViewEnglish,textViewChinese; public MyViewHolder(@NonNull View itemView) {
super(itemView); textViewNumber = itemView.findViewById(R.id.textViewNumber);
textViewEnglish = itemView.findViewById(R.id.textViewEnglish);
textViewChinese = itemView.findViewById(R.id.textViewChinese);
}
}
}

  

  

3. MainActivity.java 类

package com.example.roombasic;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.Switch;
import android.widget.TextView; import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.Observer;
import androidx.lifecycle.SavedStateViewModelFactory;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import java.util.List; public class MainActivity extends AppCompatActivity { //WordDatabase wordDatabase;
//WordDao wordDao;
Button buttonInsert,buttonUpdate,buttonClear,buttonDelete;
TextView textView;
LiveData<List<Word>> allWordsLive; WordViewModel wordViewModel; RecyclerView recyclerView;
MyAdapter myAdapter1; //cell_normal
MyAdapter myAdapter2; //cell_card ,这里必须弄2个适配器,要不然一切换数据加载不出来!?? Switch aSwitch; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//wordDatabase = Room.databaseBuilder(this,WordDatabase.class,"word_database")
//.allowMainThreadQueries() //allowMainThreadQueries() 强制允许在主线程运行
// .build(); //wordDao = wordDatabase.getWordDao(); //wordViewModel = ViewModelProviders recyclerView = findViewById(R.id.recyclerView); myAdapter1 = new MyAdapter(false);
myAdapter2 = new MyAdapter(true); recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(myAdapter1); wordViewModel = new ViewModelProvider(this,new SavedStateViewModelFactory(getApplication(),this)).get(WordViewModel.class); //allWordsLive = wordDao.getAllWordLive(); textView = findViewById(R.id.textViewNumber);
buttonInsert = findViewById(R.id.buttonInsert);
buttonUpdate = findViewById(R.id.buttonUpdate);
buttonClear = findViewById(R.id.buttonClear);
buttonDelete = findViewById(R.id.buttonDelete);
aSwitch = findViewById(R.id.switch1); //开关监听,用的是哪种样式?
aSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(aSwitch.isChecked()){
recyclerView.setAdapter(myAdapter2);
}
else{
recyclerView.setAdapter(myAdapter1);
}
}
}); //利用 LiveData<> 与 observe的onChanged配合,数据自动刷新
//allWordsLive.observe(this, new Observer<List<Word>>() {
wordViewModel.getAllWordsLive().observe(this, new Observer<List<Word>>() {
@Override
public void onChanged(List<Word> words) {
//当数据改变时会自动呼叫这个函数
//String text="";
/*StringBuilder text = new StringBuilder();
textView.setText(text); //先将 textView 清空
for(int i=0;i<words.size();i++){
Word word = words.get(i);
text.append(word.getId() + ":" + word.getWord() + "=" + word.getChineseMeaning() + "\n"); textView.setText(text);
}*/ myAdapter1.setAllWords(words);
myAdapter1.notifyDataSetChanged(); myAdapter2.setAllWords(words);
myAdapter2.notifyDataSetChanged();
}
}); buttonInsert.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) { String[] english = new String[]{"Hello",
"World",
"Android",
"Google",
"Studio",
"Project",
"Database",
"RecyclerView",
"View",
"Value"
}; String[] chinese;
chinese = new String[]{"你好",
"世界",
"安卓",
"谷歌",
"工作室",
"项目",
"数据库",
"回收站",
"视图",
"数值"
}; for(int i=0;i<english.length;i++){
wordViewModel.insertWords(new Word(english[i],chinese[i]));
} }
}); buttonUpdate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Word word = new Word("English","英语");
word.setId(76); //更新是用主键来更新的
wordViewModel.updateWords(word);
//wordDao.updateWords(word);
//new UpdateAsyncTask(wordDao).execute(word);
//updateView();
}
}); //删除所有的记录
buttonClear.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//wordDao.deleteAllWords();
//new DeleteAllAsyncTask(wordDao).execute();
//updateView();
wordViewModel.deleteAllWords();
}
}); buttonDelete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Word word = new Word("English","英语");
word.setId(76); //删除也是用主键来更新的
wordViewModel.deleteWords(word);
//wordDao.deleteWords(word);
//new DeleteAsyncTask(wordDao).execute(word);
//updateView();
}
}); } /*void updateView(){
List<Word> list = wordDao.getAllWords();
String text="";
textView.setText(text); //先将 textView 清空
for(int i=0;i<list.size();i++){
Word word = list.get(i);
text += word.getId() + ":" + word.getWord() + "=" + word.getChineseMeaning() + "\n"; textView.setText(text);
}
}*/ }

  

4.细节

项目每一行设置可点击,在cell_normal.xml 中 设置   android:clickable="true"

项目点击后,有一个背景, android:foreground="?selectableItemBackground"

 

Android Studio 之 ROM【3】,LiveData+ViewModel+AsyncTask+Repository+RecyclerView的更多相关文章

  1. Android Studio 之 ROM【2】, LiveData+ViewModel+AsyncTask+Repository

    改造上一节 ROM[1], 1.利用 LiveData<List<Word>> 与 observe 中的 onChanged 配合,删除掉之前的textView更新函数(upd ...

  2. Android Studio 之 ROM【1】, Entity,Dao,Database

    Android Studio 之 ROM, Entity,DAO,DataBase 1.Entity 实体类 package com.example.roombasic; import android ...

  3. How to distribute your own Android library through jCenter and Maven Central from Android Studio

    In Android Studio, if you wish to include any library to your application. You could just simply add ...

  4. Android Studio 之 LiveData 的配合使用,底层数据变化,自动通知界面

    Android Studio 之 LiveData 的配合使用,底层数据变化,自动通知界面 viewModelWithLikeData.getLikeNumber().observe(this, ne ...

  5. Android studio 分析内存泄漏

    以前用eclipse的时候,我们采用的是DDMS和MAT,不仅使用步骤复杂繁琐,而且要手动排查内存泄漏的位置,操作起来比较麻烦.后来随着Android studio的潮流,我也抛弃了eclipse加入 ...

  6. Android 适配多种ROM的快捷方式

    快捷方式 应该来说 很多人都做过,我们就来看一下基本的快捷方式 是怎么实现的,会有什么问题? 首先 肯定要获取权限: <!-- 添加快捷方式 --> <uses-permission ...

  7. [App]Android Studio First App

    准备着看Android Studio的体验如何. 通过Android Studio构建一个默认的项目,添加一些元素 <RelativeLayout xmlns:android="htt ...

  8. Ubuntu 14.04 64位安装Android Studio 和 genymotion (下)

    接上一篇,上回书说到,我们可以进android studio的编辑器了.感觉不错.挺好的,先不说genymotion,先看看你的android项目有没有r文件,项目有没有错误? 如果没有问题的话,下面 ...

  9. linux安装安卓开发工具android studio

    http://www.android-studio.org/ http://android-studio.org/index.php/docs/guide 最近要接触android编程,本来想装ecl ...

随机推荐

  1. pytest_demo_实战2_fixture应用

    1.py文件所在文件夹下创建 __init__.py 文件 2.文件夹目录下:创建conftest.py import pytest # @pytest.fixture() 里面没有参数,那么默认sc ...

  2. SpringBoot 通过jjwt快速实现token授权

    A 10分钟了解JSON Web令牌(JWT)https://baijiahao.baidu.com/s?id=1608021814182894637&wfr=spider&for=p ...

  3. .NET获取实例化对象的部分属性名称

    前言 项目中实例化的对象,对象中里面很有很多属性,有些是我们不需要的,有些是我们需要的,例如在下面的示例中:ID,CreateBy等属性在CB_Projects对象中是不需要的,在获取实例化对象属性名 ...

  4. template might not exist or might not be accessible by any of the configured Template Resolvers 完美解决

    初学者在maven spring boot web项目中使用thymeleaf 模板,经常会遇到  “template might not exist or might not be accessib ...

  5. JavaScript 总结[目录]

    ECMAScript 基础 一.JavaScript 基础 1.1 JavaScript 简介 1.2 JavaScript 书写位置 二.JavaScript 数据类型 2.1 JavaScript ...

  6. 打包工具webpack和热加载深入学习

    本次小编呢,为大家带来一篇深入了解打包工具 webpack. 我们今天使用的是 webpack3.8.1版本的,我们学习使用 3.8.1更稳定些,并学习自己如何配置文件,最新版本不需要自己配置文件,但 ...

  7. Asp.Net SignalR 使用记录 技术回炉重造-总纲 动态类型dynamic转换为特定类型T的方案 通过对象方法获取委托_C#反射获取委托_ .net core入门-跨域访问配置

    Asp.Net SignalR 使用记录   工作上遇到一个推送消息的功能的实现.本着面向百度编程的思想.网上百度了一大堆.主要的实现方式是原生的WebSocket,和SignalR,再次写一个关于A ...

  8. 【学习笔记】PYTHON语言程序设计(北理工 嵩天)

    1 Python基本语法元素 1.1 程序设计基本方法 计算机发展历史上最重要的预测法则     摩尔定律:单位面积集成电路上可容纳晶体管数量约2年翻倍 cpu/gpu.内存.硬盘.电子产品价格等都遵 ...

  9. Python基础(二)--基本数据类型、格式化输出、基本运算符

    一.基本数据类型 1.数字类型 #int整型 定义:age=10 #age=int(10) 用于标识:年龄,等级,身份证号,qq号,个数 #float浮点型 定义:salary=3.1 #salary ...

  10. MySQL读写分离之MyCAT

    Mycat实现MySQL主从复制读写分离 MyCAT的安装及部署 1.部署jdk环境 MyCAT用Java开发,需要有JAVA运行环境,mycat依赖jdk1.7的环境 1)上传jdk [root@l ...