习题模块总结作业
一、ListView
习题页面显示章节习题
习题详情页面显示习题的题目及选项,选择选项后判断选项是否正确
1.简单介绍ListView
listview是一个以垂直方式在项目中显示视图的列表。是一种不能实现确定视图中的内容的适配器视图(adapter view)。数据和视图的绑定,需要通过继承ListViewAdapter接口的适配器实现。确保当上下滚动的时候,能够动态刷新视图内容。通常我们都会自定义一个继承自BaseAdapter(已继承ListViewAdapter),ArrayAdapter(继承自BaseAdapter),SimpleAdapter(继承自BaseAdapter)的类,重写getView()方法,实现自己想要的功能。
getView方法详情
View getView (int position, View convertView, ViewGroup parent)
Get a View that displays the data at the specified position in the data set.
You can either create a View manually or inflate it from an XML layout file.
When the View is inflated, the parent View (GridView, ListView...) will apply
default layout parameters unless you useinflate(int, android.view.ViewGroup,boolean)to
specify a root view and to prevent attachment to the root
备注:使用适配器构建布局。
如果布局的内容是属于动态或未预先确定的内容,您可以使用这样一种布局:在运行时通过子类AdapterView用视图填充布局。AdapterView类的子类使用Adapter将数据与其布局绑定。
Adapter充当数据源与AdapterView布局之间的中间人—Adapter(从数组或数据库查询等来源)检索数据,并将每个条目转换为可以添加到AdapterView布局中的视图。
适配器支持的常见布局包括:
使用数据填充适配器视图
您可以通过将AdapterView实例与Adapter绑定来填充AdapterView(如ListView或GridView),此操作会从外部来源检索数据,并创建表示每个数据条目的View。
Android 提供了几个Adapter子类,用于检索不同种类的数据和构建AdapterView的视图。 两种最常见的适配器是:ArrayAdapter和SimpleCursorAdapter。
2.ListView使用步骤
1).在布局的XML文件中,添加如下代码:
<ListView
android:id="@+id/list_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
2)新建list_item的布局文件,确定每一个View的样式。
3).新建一个适配器类。
4).绑定数据到视图。
二、Adapter和AdapterView
根据记录数,加载每个view
ListView在Android开发中十分常见
今天,我将为大家带来ListView与AdapterView全面解析,含其特点、工作原理等,希望你们会喜欢。
目录
示意图
1. 简介
Android中的一种列表视图组件
继承自AdapterView抽象类,类图关系如下
示意图
2. 作用
集合多个 “项”(称为:Item) & 以列表的形式 展示
示意图
3. 工作原理
3.1 本质原理
ListView仅作为容器(列表),用于装载 & 显示数据(即 列表项Item)
而容器内的具体数据(列表项Item)则是由 适配器(Adapter)提供
适配器(Adapter):作为View和 数据之间的桥梁 & 中介,将数据映射到要展示的View中
当需显示数据时,ListView会向Adapter取出数据,从而加载显示,具体如下图
示意图
结论
ListView负责以列表的形式显示Adapter提供的内容
3.2 缓存原理
试想一个场景:若把所有数据集合的信息都加载到ListView上显示,若ListView要为每个数据都创建一个视图,那么会占用非常多的内存
为了节省空间和时间,ListView不会为每一个数据创建一个视图,而是采用了Recycler组件,用于回收 & 复用View
当屏幕需显示x个Item时,那么ListView会创建x+1个视图;当第1个Item离开屏幕时,此Item的View被回收至缓存,入屏的Item的View会优先从该缓存中获取
注:
只有Item完全离开屏幕后才可复用,这也是为什么ListView要创建比屏幕需显示视图多1个的原因:缓冲 显示视图
即:第1个Item离开屏幕是有过程的,会有1个第1个Item的下半部分 & 第8个Item上半部分同时在屏幕中显示的状态,此时仍无法使用缓存的View,只能继续用新创建的视图View
实例演示
设:屏幕只能显示5个Item,那么ListView只会创建(5+1)个Item的视图;当第1个Item完全离开屏幕后才会回收至缓存从而复用(用于显示第7个Item)
三、适配器
初始化控件、获取控件、设置布局
Adapter(适配器的讲解)
适配器就我自己来看,我觉得这是一个非常重要的知识点,Adapter是用来帮助填出数据的中间桥梁,简单点说吧:将各种数据以合适的形式显示在View中给用户看。Adapter有很多的接口、抽象类、子类可以使用,这里就我们常用的几个进行讲解
BaseAdapter,ArrayAdapter,SimpleAdapter,为了配合讲解这几个适配器,这里提前使用一下ListView来展示一下适配器的使用,后面会对ListView进行进一步总结。
一、ArrayAdapter(数组适配器),这个适配器使用有一定的局限性,只能显示一行文本数据
(1)基本使用实例
布局文件:
<?xml version="1.0" encoding="utf-8"?><LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"><ListView
android:id="@+id/ll1" android:layout_width="match_parent" android:layout_height="wrap_content"></ListView></LinearLayout>
Java文件
package com.example.test3;import android.app.Activity;import android.os.Bundle;import android.widget.ArrayAdapter;import android.widget.ListView;publicclassMainActivityextends Activity{// 定义要显示的数据privateString[] datas = {"张三","李四","王五","麻子","小强"};
privateArrayAdapter adapter;
private ListView listView;
@Override
protectedvoid onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.ll1);// 初始化适配器adapter =newArrayAdapter<>(this,android.R.layout.simple_expandable_list_item_1,datas);
listView.setAdapter(adapter);
}
}
效果图:
(2)实现上面还可以先在res\value下创建一个数组资源的xml文件:arrays.xml,然后在listview中使用entries
3、ArrayAdapter也支持泛型,那么集合肯定必须的,还可以如下所写
4、ArrayAdapter的参数说明:
第一个参数:context上下文对象
第二个参数:每一个item的样式,可以使用系统提供,也可以自定义就是一个TextView
第三个参数:数据源,要显示的数据
系统提供的item的样式,可以试一试
simple_list_item1:单独的一行文本框
simple_list_item2:有两个文本框组成
simple_list_item_checked每项都是由一个已选中的列表项
simple_list_item_multiple_choice:都带有一个复选框
simple_list_item_single_choice:都带有一个单选框
四、RecyclerView控件
为RecyclerView准备一个适配器,新建RecyclerViewAdapter类,让适配器继承自RecyclerView.Adapter,并将泛型指定RecyclerViewAdapter.ViewHolder。
RecyclerView 的基本用法
打开 app/build.gradle 文件,在 dependencies 闭包中添加如下内容:
compile'com.android.support:recyclerview-v7:24.2.1'
添加完之后记得要点击一下 Sync Now 来进行同步。然后修改 activity_main.xml 中的代码, 如下所示:
android:layout_width="match_parent"
android:layout_height="match_parent">
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
新建Fruit 类和 fruit_item.xml,代码如下所示:
publicclassFruit{
privateString name;
privateintimageId;
publicFruit(String name,intimageId){
this.name = name;
this.imageId = imageId;
}
publicStringgetName(){
returnname;
}
publicintgetImageId(){
returnimageId;
}
}
Fruit 类中只有两个字段,name 表示水果的名字,imageId 表示水果对应图片的资源 id。
然后需要指定一个我们自定义的布局,在layout目录下新建fruit_item.xml, 代码如下所示:
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:id="@+id/fruit_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
android:id="@+id/fruit_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="10dp"/>
接下来需要为 RecyclerView 准备一个适配器,新建 FruitAdapter 类,让这个适配器继承自 RecyclerView.Adapter,并将泛型指定为 FruitAdapter.ViewHolder。其中,ViewHolder 是我们在 FruitAdapter 中定义的一个内部类,代码如下所示:
publicclassFruitAdapterextendsRecyclerView.Adapter{
privateList mFruitList;
staticclassViewHolderextendsRecyclerView.ViewHolder{
ImageView fruitImage;
TextView fruitName;
publicViewHolder(View view){
super(view);
fruitImage = (ImageView) view.findViewById(R.id.fruit_image);
fruitName = (TextView) view.findViewById(R.id.fruit_name);
}
}
publicFruitAdapter(List<Fruit> fruitList){
mFruitList = fruitList;
}
@Override
publicViewHolderonCreateViewHolder(ViewGroup parent,intviewType){
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.fruit_item, parent,false);
ViewHolder holder =newViewHolder(view);
returnholder;
}
@Override
publicvoidonBindViewHolder(ViewHolder holder,intposition){
Fruit fruit = mFruitList.get(position);
holder.fruitImage.setImageResource(fruit.getImageId());
holder.fruitName.setText(fruit.getName());
}
@Override
publicintgetItemCount(){
returnmFruitList.size();
}
}
这里我们首 先定义了一个内部类 ViewHolder,ViewHolder 要继承自 RecyclerView.ViewHolder。然后 ViewHolder 的构造函数中要传入一个 View 参数,这个参数通常就是 RecyclerView 子项的最外层布局,那么我们就可以通过 findViewById()方法来获取到布局中的 ImageView 和 TextView 的实例了。
接着往下看,FruitAdapter 中也有一个构造函数,这个方法用于把要展示的数据源传进来, 并赋值给一个全局变量 mFruitList,我们后续的操作都将在这个数据源的基础上进行。
继续往下看,由于 FruitAdapter 是继承自 RecyclerView.Adapter 的,那么就必须重写 onCreateViewHolder()、onBindViewHolder()和 getItemCount()这 3 个方法。onCreateViewHolder()方法是用于创建 ViewHolder 实例的,我们在这个方法中将 fruit_item 布局加载 进来,然后创建一个 ViewHolder 实例,并把加载出来的布局传入到构造函数当中,最后将 ViewHolder 的实例返回。onBindViewHolder()方法是用于对 RecyclerView 子项的数据进行赋值 的,会在每个子项被滚动到屏幕内的时候执行,这里我们通过 position 参数得到当前项的 Fruit 实例,然后再将数据设置到 ViewHolder 的 ImageView 和 TextView 当中即可。getItemCount() 方法就非常简单了,它用于告诉 RecyclerView 一共有多少子项,直接返回数据源的长度就可以了。
适配器准备好了之后,我们就可以开始使用 RecyclerView 了,修改 MainActivity 中的代码, 如下所示:
publicclassMainActivityextendsAppCompatActivity{
privateList fruitList =newArrayList<>();
@Override
protectedvoidonCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initFruits();// 初始化水果数据
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
LinearLayoutManager layoutManager =newLinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
FruitAdapter adapter =newFruitAdapter(fruitList);
recyclerView.setAdapter(adapter);
}
privatevoidinitFruits(){
for(inti =0; i <2; i++) {
Fruit apple =newFruit("Apple", R.drawable.apple_pic);
fruitList.add(apple);
Fruit banana =newFruit("Banana", R.drawable.banana_pic);
fruitList.add(banana);
Fruit orange =newFruit("Orange", R.drawable.orange_pic);
fruitList.add(orange);
Fruit watermelon =newFruit("Watermelon", R.drawable.watermelon_pic);
fruitList.add(watermelon);
Fruit pear =newFruit("Pear", R.drawable.pear_pic);
fruitList.add(pear);
Fruit grape =newFruit("Grape", R.drawable.grape_pic);
fruitList.add(grape);
Fruit pineapple =newFruit("Pineapple", R.drawable.pineapple_pic);
fruitList.add(pineapple);
Fruit strawberry =newFruit("Strawberry", R.drawable.strawberry_pic);
fruitList.add(strawberry);
Fruit cherry =newFruit("Cherry", R.drawable.cherry_pic);
fruitList.add(cherry);
Fruit mango =newFruit("Mango", R.drawable.mango_pic);
fruitList.add(mango);
}
}
}
可以看到,这里使用了一个同样的 initFruits()方法,用于初始化所有的水果数据。接着 在 onCreate()方法中我们先获取到 RecyclerView 的实例,然后创建了一个 LinearLayoutManager 对象,并将它设置到 RecyclerView 当中。LayoutManager 用于指定 RecyclerView 的布局 方式,这里使用的 LinearLayoutManager 是线性布局的意思,可以实现和 ListView 类似的效果。 接下来我们创建了 FruitAdapter 的实例,并将水果数据传入到 FruitAdapter 的构造函数中, 最后调用 RecyclerView 的 setAdapter()方法来完成适配器设置,这样 RecyclerView 和数据之间 的关联就建立完成了。