目录
1.MVC模式的简单理解
举个例子:在开发一个项目的时候,一般都是由多人一同开发完成,比如有人负责操作接口的规划与设计,有人负责程序代码的编写如果要能够做到程序项目的分工就必须在程序的结构上做适合的安排,如果,接口设计与修改涉及到程序代码的改变的话,那么两者的分工就会造成执行上的困难,良好的程序架构师将整个程序项目划分为如图的三个部分:
关系图解析:
Model:通常可以理解为数据,负责执行程序的核心运算与判断逻辑,通过view获得用户输入的数据,然后根据从数据库查询相关的信息,最后进行运算和判断,再将得到的结果交给view来显示;
view:用户的操作接口,说白了就是GUI(图形用户界面(Graphical User Interface),是指采用图形方式显示的计算机操作用户界面),应该使用哪种接口组件,组件间的排列位置与顺序都需要设计
Controller:控制器,作为model与view之间的枢纽,负责控制程序的执行流程以及对象之间的一个互动。
M:model:数据模型——数据源
V:view:显示的视图控件——AdapterView
C:controller:控制器——adapter
AdapterView即Adapter(适配器)控件
AdapterView适配器View常用的有:ListView、GridView、Spinner、RecycleView
其内容通常是一个包含多项相同格式资源的列表,每次只显示其中一项,这个存放Adapter控件内容的列表,在android被称为AdapterView(适配器view)使用的时候一般都会先给适配器填充内容,然后将已经设定好的内容的适配器(Adapter)设置到AdapterView上。
就像下面这张图片一样,每一个内容的布局基本都是一样的,只是内容不相同罢了。像这种布局类似,内容不同的,我们就可以采用适配器view进行设计,大大减少了代码量。
2.Adapter概念解析
BaseAdapter:抽象类,实际开发中我们会继承这个类并重写相关方法,用得最多的一个Adapter;
ArrayAdapter:支持泛型操作,最简单的一个Adapter,只能展现一行文字;
SimpleAdapter:同样具有良好扩展性的一个Adapter,可以自定义多种效果;
SimpleCursorAdapter:用于显示简单文本类型LitsView,一般在数据库那里会用到,不过有点过时,不推荐使用哦!
1.运用
布局
<?xml version="1.0" encoding="utf-8"?>
<ListView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/list_1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
</ListView>
simple_list_item_1.xml 这个可以根据自己的需要改变,下面是自带的。
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2006 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceListItemSmall"
android:gravity="center_vertical"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:minHeight="?android:attr/listPreferredItemHeightSmall" />
MainActivity.java
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//AdapterView--V
ListView listView=findViewById(R.id.list_1);
//数据源--M
String[] string={"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n","o","p","q","r","s","t","u","v","w","x","y","z"};
//控制器--C
ArrayAdapter<String>adapter=new ArrayAdapter<>(this, android.R.layout.simple_list_item_1,string);
//为ListView设置Adapter适配器
listView.setAdapter(adapter);
}
}
2.效果展示
3.ListView
BaseAdapter最基本的几个方法:
getCount:填充的数据集数
getItem:数据集中指定索引对应的数据项
getItemId:指定行所对应的ID
getView:每个Item所显示的内容
1.运用
布局
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<ListView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/list_1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
</ListView>
listview.xml
<?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="200dp">
<ImageView
android:id="@+id/imageView"
android:layout_width="200dp"
android:layout_height="200dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/a1" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="36dp"
android:text="TextView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.092"
app:layout_constraintStart_toEndOf="@+id/imageView"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="32dp"
android:text="TextView"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.092"
app:layout_constraintStart_toEndOf="@+id/imageView" />
</androidx.constraintlayout.widget.ConstraintLayout>
kinds.java
public class kinds {
private String title;
private String content;
private int id;
public kinds() {
}
public kinds(String title, String content, int id) {
this.title = title;
this.content = content;
this.id = id;
}
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;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
FirstAdapter.java
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.List;
public class FirstAdapter extends BaseAdapter {
private List<kinds> data;
private Context context;
public FirstAdapter(List<kinds> data, Context context) {
this.data = data;
this.context = context;
}
@Override
public int getCount() {
return data.size();
}
@Override
public Object getItem(int position) {
return data.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
convertView = LayoutInflater.from(context).inflate(R.layout.listview,parent,false);
ImageView imageView=convertView.findViewById(R.id.imageView);
TextView textView=convertView.findViewById(R.id.textView);
TextView textView2=convertView.findViewById(R.id.textView2);
imageView.setBackgroundResource(data.get(position).getId());
textView.setText(data.get(position).getTitle());
textView2.setText(data.get(position).getContent());
return convertView;
}
}
MainActivity.java
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
import java.util.LinkedList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private FirstAdapter firstAdapter;
List<kinds> list= new LinkedList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//AdapterView--V
ListView listView=findViewById(R.id.list_1);
for(int i=0;i<10;i++){
list.add(new kinds("今天还好吗?"+i,"今天没有怎么学习,所以不要开心"+i,R.drawable.a1));
}
firstAdapter=new FirstAdapter(list,MainActivity.this);
listView.setAdapter(firstAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(MainActivity.this,"点击了第"+position+"条数据",Toast.LENGTH_SHORT).show();
}
});
}
}
2.效果展示
有个点击事件,点击之后弹出消息提示
3.BaseAdapter优化
1.复用Convertview
inflate()每次都要加载一次xml,其实这个convertView是系统提供给我们的可供复用的view的缓存对象。
2.ViewHolder重用组件
用来保存我们xml文件里面的对象,从而达到复用。
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// convertView = LayoutInflater.from(context).inflate(R.layout.listview,parent,false);
// ImageView imageView=convertView.findViewById(R.id.imageView);
// TextView textView=convertView.findViewById(R.id.textView);
// TextView textView2=convertView.findViewById(R.id.textView2);
// imageView.setBackgroundResource(data.get(position).getId());
// textView.setText(data.get(position).getTitle());
// textView2.setText(data.get(position).getContent());
// return convertView;
ViewHolder holder=null;
if(convertView==null){
holder=new ViewHolder();
convertView=LayoutInflater.from(context).inflate(R.layout.listview,parent,false);
holder.imageView=convertView.findViewById(R.id.imageView);
holder.textView=convertView.findViewById(R.id.textView);
holder.textView2=convertView.findViewById(R.id.textView2);
convertView.setTag(holder);
}else{
holder=(ViewHolder) convertView.getTag();
}
holder.imageView.setBackgroundResource(data.get(position).getId());
holder.textView.setText(data.get(position).getTitle());
holder.textView2.setText(data.get(position).getContent());
return convertView;
}
static class ViewHolder{
ImageView imageView;
TextView textView;
TextView textView2;
}
4.ListView item多布局实现
重写 getItemViewType()方法对应View是哪个类别,以及getItemViewType()方法view返回,总共多少类别,然后再getView那里调用getItemViewType()获得对应类别,再加载对应的View.
一般我们看到的列表,不可能都是同一种风格的。就像这个,有些文章是有图片的,而有些是没有的。
1.运用
listview2.xml
<?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="200dp">
<ImageView
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="200dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:background="@drawable/a2"/>
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="44dp"
android:layout_marginLeft="44dp"
android:layout_marginTop="68dp"
android:text="TextView"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="44dp"
android:layout_marginLeft="44dp"
android:layout_marginBottom="40dp"
android:text="TextView"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
activity_main.xml和listview.xml文章上面都有,没有做任何改变。
SecondAdapter.java
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.List;
public class SecondAdapter extends BaseAdapter {
private List<kinds> data;
private Context context;
private static final int TYPE_A=0;
private static final int TYPE_B=1;
public SecondAdapter() {
}
public SecondAdapter(List<kinds> data, Context context) {
this.data = data;
this.context = context;
}
@Override
public int getCount() {
return data.size();
}
@Override
public Object getItem(int position) {
return data.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
int type=getItemViewType(position);//获取布局类型
ViewHolder holder1=null;
ViewHolder2 holder2=null;
if(convertView==null){
switch (type){
case TYPE_A:
holder1=new ViewHolder();
convertView= LayoutInflater.from(context).inflate(R.layout.listview,parent,false);
holder1.imageView=convertView.findViewById(R.id.imageView);
holder1.textView=convertView.findViewById(R.id.textView);
holder1.textView2=convertView.findViewById(R.id.textView2);
convertView.setTag(holder1);
break;
case TYPE_B:
holder2= new ViewHolder2();
convertView= LayoutInflater.from(context).inflate(R.layout.listview2,parent,false);
holder2.imageView=convertView.findViewById(R.id.imageView);
holder2.textView=convertView.findViewById(R.id.textView);
holder2.textView2=convertView.findViewById(R.id.textView2);
convertView.setTag(holder2);
break;
}
}else{
switch (type){
case TYPE_A:
holder1=(ViewHolder) convertView.getTag();
break;
case TYPE_B:
holder2=(ViewHolder2) convertView.getTag();
}
}
switch (type){
//因为我把第二个布局的图片换了一张,所以我们就把下面设置图片这个注释了
//要不然两个图片会显示一样的。
case TYPE_A:
//holder1.imageView.setBackgroundResource(data.get(position).getId());
holder1.textView.setText(data.get(position).getTitle());
holder1.textView2.setText(data.get(position).getContent());
break;
case TYPE_B:
//holder2.imageView.setBackgroundResource(data.get(position).getId());
holder2.textView.setText(data.get(position).getTitle());
holder2.textView2.setText(data.get(position).getContent());
break;
}
return convertView;
}
@Override
public int getItemViewType(int position) {
if(position%2==0)
return TYPE_A;
else
return TYPE_B;
}
@Override
public int getViewTypeCount() {
return 2;
}
static class ViewHolder{
ImageView imageView;
TextView textView;
TextView textView2;
}
static class ViewHolder2{
ImageView imageView;
TextView textView;
TextView textView2;
}
}
2.效果展示