Android Studio 之 ROM【3】,LiveData+ViewModel+AsyncTask+Repository+RecyclerView
教程地址: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的更多相关文章
- Android Studio 之 ROM【2】, LiveData+ViewModel+AsyncTask+Repository
改造上一节 ROM[1], 1.利用 LiveData<List<Word>> 与 observe 中的 onChanged 配合,删除掉之前的textView更新函数(upd ...
- Android Studio 之 ROM【1】, Entity,Dao,Database
Android Studio 之 ROM, Entity,DAO,DataBase 1.Entity 实体类 package com.example.roombasic; import android ...
- 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 ...
- Android Studio 之 LiveData 的配合使用,底层数据变化,自动通知界面
Android Studio 之 LiveData 的配合使用,底层数据变化,自动通知界面 viewModelWithLikeData.getLikeNumber().observe(this, ne ...
- Android studio 分析内存泄漏
以前用eclipse的时候,我们采用的是DDMS和MAT,不仅使用步骤复杂繁琐,而且要手动排查内存泄漏的位置,操作起来比较麻烦.后来随着Android studio的潮流,我也抛弃了eclipse加入 ...
- Android 适配多种ROM的快捷方式
快捷方式 应该来说 很多人都做过,我们就来看一下基本的快捷方式 是怎么实现的,会有什么问题? 首先 肯定要获取权限: <!-- 添加快捷方式 --> <uses-permission ...
- [App]Android Studio First App
准备着看Android Studio的体验如何. 通过Android Studio构建一个默认的项目,添加一些元素 <RelativeLayout xmlns:android="htt ...
- Ubuntu 14.04 64位安装Android Studio 和 genymotion (下)
接上一篇,上回书说到,我们可以进android studio的编辑器了.感觉不错.挺好的,先不说genymotion,先看看你的android项目有没有r文件,项目有没有错误? 如果没有问题的话,下面 ...
- linux安装安卓开发工具android studio
http://www.android-studio.org/ http://android-studio.org/index.php/docs/guide 最近要接触android编程,本来想装ecl ...
随机推荐
- Blockstack: A Global Naming and Storage System Secured by Blockchains
作者:Muneeb Ali, Jude Nelson, Ryan Shea, and Michael Freedman Blockstack Labs and Princeton University ...
- C#中的System.Type和System.RuntimeType之间的区别
string str = string.Empty; Type strType = str.GetType(); Type strTypeType = strType.GetType(); strTy ...
- web api与mvc的区别
MVC主要用来构建网站,既关心数据也关心页面展示,而Web API只关注数据 Web API支持格式协商,客户端可以通过Accept header通知服务器期望的格式 Web API支持Self Ho ...
- 调试 Go 的代码生成
原文:https://studygolang.com/articles/19815 这是一个创建于 2019-04-17 23:12:26 的文章,其中的信息可能已经有所发展或是发生改变. 2016 ...
- asp.net core 在centeros 7.x下创建服务
Netcore服务生成说明 如有个项目/opt/wwwroot/dpms.1633.com 启动为/usr/bin/dotnet /opt/wwwroot/dpms.1633.com/DPMS.Web ...
- 【JZOJ】2126. 最大约数和
题目大意 选取和不超过S的若干个不同的正整数,使得所有数的约数(不含它本身)之和最大. 分析 把我们分解出来的因数进行合并,存在一个不知名的数组里,然后我们大可开始我们的迪屁!!(bag),我们可以 ...
- JDK安装—JAVA
下载JDK 下载地址:http://www.oracle.com/technetwork/java/javase/downloads/index.html 关于版本选择需要注意的问题: 如果eclip ...
- Class版本号和Java版本对应关系
1.背景 版本号不对,会报错,如下 2.版本对应情况 JDK 1.8 = 52 JDK 1.7 = 51 JDK 1.6 =50 JDK 1.5 = 49 JDK 1.4 = 48 JDK 1. ...
- Linux小知识点
磁盘 Linux的磁盘类型有IDE和SCSI两种. IDE的命名方式是采用/dev/hdx(x代表磁盘块),其下的分区则是/dev/hdxy(y代表该磁盘上的分区号) SCSI则是采用/dev/sdx ...
- c语言基础之getopt()
getopt() #include <unistd.h> int getopt(int argc, char * const argv[], const char *optstring); ...