Android BaseAdapter应用基础
Android基础类之BaseAdapter
BaseAdapter是实现了ListAdapter和SpinnerAdapter两个接口,当然它也可以直接给ListView和Spinner等UI组件直接提供数据。
说明:上面一行图片是Gallery画廊,每次点击一个Gallery图片时,会同时在下面以大图形式显示出来该图片
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="fill_parent"android:layout_height="fill_parent"> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello"/><Gallery android:id="@+id/gallery1" android:layout_width="match_parent" android:spacing="5px" android:layout_height="wrap_content" ></Gallery> <ImageViewandroid:id="@+id/iv"android:layout_gravity="center_vertical"android:layout_marginTop="20px"android:layout_width="320px"android:layout_height="320px"></ImageView></LinearLayout>
package com.magc.adapter;import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.view.View.OnClickListener; import android.widget.AdapterView; import android.widget.BaseAdapter; import android.widget.Gallery; import android.widget.ImageView; import android.widget.AdapterView.OnItemClickListener;publicclass MainActivity extends Activity {private Gallery gallery;private ImageView imgview;privateint[] imgs = {R.drawable.a6,R.drawable.a1,R.drawable.a2,R.drawable.a3,R.drawable.a4,R.drawable.a5};/** Called when the activity is first created. */@Overridepublicvoid onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);imgview = (ImageView)findViewById(R.id.iv);gallery = (Gallery)findViewById(R.id.gallery1);MyImgAdapter adapter =new MyImgAdapter(this);gallery.setAdapter(adapter);gallery.setOnItemClickListener(new OnItemClickListener() {//用户点击图片时,将该图片的ResourceID设到下面的ImageView中去, @Overridepublicvoid onItemClick(AdapterView<?> arg0, View view, int position,long arg3) {imgview.setImageResource(imgs[position]);}});}class MyImgAdapter extends BaseAdapter { //自定义图片Adapter以内部类形式存在于MainActivity中,方便访问MainActivity中的各个变量,特别是imgs数组private Context context;//用于接收传递过来的Context对象 public MyImgAdapter(Context context) {super();this.context = context;}/* (non-Javadoc)* @see android.widget.Adapter#getCount()*/@Overridepublicint getCount() {return imgs.length;}/* (non-Javadoc)* @see android.widget.Adapter#getItem(int)*/@Overridepublic Object getItem(int position) {return position;}/* (non-Javadoc)* @see android.widget.Adapter#getItemId(int)*/@Overridepubliclong getItemId(int position) {return position;}/* (non-Javadoc)* @see android.widget.Adapter#getView(int, android.view.View, android.view.ViewGroup)*/@Overridepublic View getView(int position, View convertView, ViewGroup parent) {//针对每一个数据(即每一个图片ID)创建一个ImageView实例, ImageView iv =new ImageView(context);//针对外面传递过来的Context变量, iv.setImageResource(imgs[position]);Log.i("magc", String.valueOf(imgs[position]));iv.setLayoutParams(new Gallery.LayoutParams(80, 80));//设置Gallery中每一个图片的大小为80*80。 iv.setScaleType(ImageView.ScaleType.FIT_XY);return iv;}}}
Android ListView使用BaseAdapter与ListView的优化
在ListView的使用中,有时候还需要在里面加入按钮等控件,实现单独的操作。也就是说,这个ListView不再只是展示数据,也不仅仅是这一行要来处理用户的操作,而是里面的控件要获得用户的焦点。读者可以试试用SimpleAdapter添加一个按钮到ListView的条目中,会发现可以添加,但是却无法获得焦点,点击操作被ListView的Item所覆盖。这时候最方便的方法就是使用灵活的适配器BaseAdapter了。
▲图4-35 BaseAdapter中的方法
使用BaseAdapter必须写一个类继承它,同时BaseAdapter是一个抽象类,继承它必须实现它的方法。BaseAdapter的灵活性就在于它要重写很多方法,看一下有哪些方法,如图4-35所示为继承自BaseAdapter的SpeechListAdapter所实现的方法,其中最重要的即为getView()方法。这些方法都有什么作用呢?我们通过分析ListView的原理来为读者解答。
当系统开始绘制ListView的时候,首先调用getCount()方法。得到它的返回值,即ListView的长度。然后系统调用getView()方法,根据这个长度逐一绘制ListView的每一行。也就是说,如果让getCount()返回1,那么只显示一行。而getItem()和getItemId()则在需要处理和取得Adapter中的数据时调用。那么getView如何使用呢?如果有10000行数据,就绘制10000次?这肯定会极大的消耗资源,导致ListView滑动非常的慢,那应该怎么做呢?通过一个例子来讲解如何在使用BaseAdapter的时候优化ListView的显示。例子中将上一节中的ImageView换成Button,并且处理Button的点击事件,其中对ListView的显示做了优化。
布局文件和上一例类同,读者可以在光盘的工程目录中查看,这里只给出Activity类。
001
|
publicclass MyListViewBase extends Activity {
|
002
|
|
003
|
private ListView lv;
|
004
|
//定义一个动态数组
|
005
|
ArrayList<HashMap<String, Object>>listItem; /** Called when the activity is first created. */
|
006
|
|
007
|
@Override
|
008
|
publicvoid onCreate(Bundle savedInstanceState) {
|
009
|
super .onCreate(savedInstanceState);
|
010
|
setContentView(R.layout.main);
|
011
|
012
|
lv = (ListView) findViewById(R.id.lv);
|
013
|
MyAdapter mAdapter = new MyAdapter( this ); //得到一个MyAdapter对象
|
014
|
lv.setAdapter(mAdapter); //为ListView绑定Adapter
|
015
|
/**为ListView添加点击事件*/
|
016
|
lv.setOnItemClickListener( new OnItemClickListener() {
|
017
|
@Override
|
018
|
publicvoid onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
|
019
|
Log.v( "MyListViewBase" , "你点击了ListView条目" + arg2); //在LogCat中输出信息
|
020
|
}
|
021
|
});
|
022
|
}
|
023
|
/**添加一个得到数据的方法,方便使用*/
|
024
|
private ArrayList<HashMap<String, Object>> getDate(){
|
025
|
ArrayList<HashMap<String, Object>> listItem = new ArrayList<HashMap<String,Object>>();
|
026
|
/**为动态数组添加数据*/
|
027
|
for ( int i= 0 ;i< 30 ;i++)
|
028
|
{
|
029
|
HashMap<String, Object> map = new HashMap<String, Object>();
|
030
|
map.put( "ItemTitle" , "第" +i+ "行" );
|
031
|
map.put( "ItemText" , "这是第" +i+ "行" );
|
032
|
listItem.add(map);
|
033
|
}
|
034
|
return listItem;
|
035
|
}
|
036
|
/** 新建一个类继承BaseAdapter,实现视图与数据的绑定
|
037
|
*/
|
038
|
privateclass MyAdapter extends BaseAdapter {
|
039
|
private LayoutInflater mInflater; //得到一个LayoutInfalter对象用来导入布局
|
040
|
|
041
|
/**构造函数*/
|
042
|
public MyAdapter(Context context) {
|
043
|
this .mInflater = LayoutInflater.from(context);
|
044
|
}
|
045
|
046
|
@Override
|
047
|
publicint getCount() {
|
048
|
return getDate().size(); //返回数组的长度
|
049
|
}
|
050
|
051
|
@Override
|
052
|
public Object getItem( int position) {
|
053
|
returnnull;
|
054
|
}
|
055
|
056
|
@Override
|
057
|
publiclong getItemId( int position) {
|
058
|
return 0 ;
|
059
|
}
|
060
|
|
061
|
/**书中详细解释该方法*/
|
062
|
@Override
|
063
|
public View getView(finalint position, View convertView, ViewGroup parent) {
|
064
|
ViewHolder holder;
|
065
|
//观察convertView随ListView滚动情况
|
066
|
Log.v( "MyListViewBase" , "getView " + position + " " + convertView);
|
067
|
if (convertView == null ) {
|
068
|
convertView = mInflater.inflate(R.layout.item, null );
|
069
|
holder = new ViewHolder();
|
070
|
/**得到各个控件的对象*/
|
071
|
holder.title = (TextView) convertView.findViewById(R.id.ItemTitle);
|
072
|
holder.text = (TextView) convertView.findViewById(R.id.ItemText);
|
073
|
holder.bt = (Button) convertView.findViewById(R.id.ItemButton);
|
074
|
convertView.setTag(holder); //绑定ViewHolder对象
|
075
|
}
|
076
|
else {
|
077
|
holder = (ViewHolder)convertView.getTag(); //取出ViewHolder对象
|
078
|
}
|
079
|
/**设置TextView显示的内容,即我们存放在动态数组中的数据*/
|
080
|
holder.title.setText(getDate().get(position).get( "ItemTitle" ).toString());
|
081
|
holder.text.setText(getDate().get(position).get( "ItemText" ).toString());
|
082
|
|
083
|
/**为Button添加点击事件*/
|
084
|
holder.bt.setOnClickListener( new OnClickListener() {
|
085
|
@Override
|
086
|
publicvoid onClick(View v) {
|
087
|
Log.v( "MyListViewBase" , "你点击了按钮" + position); //打印Button的点击信息
|
088
|
}
|
089
|
});
|
090
|
|
091
|
return convertView;
|
092
|
}
|
093
|
|
094
|
}
|
095
|
|
096
|
/**存放控件*/
|
097
|
publicfinalclass ViewHolder{
|
098
|
public TextView title;
|
099
|
public TextView text;
|
100
|
public Button bt;
|
101
|
}
|
102
|
}
|
运行效果如图4-36所示。还需要注意的是,Button会抢夺ListView的焦点,需要将Button设置为没有焦点。设置非常简单,只需要在xml的Button标签下加入一行:android:focusable=“false”代码就可以了。在LogCat观察点击后输出的信息,如图4-37所示。
▲图4-36 使用BaseAdapter的ListVie
w
▲图4-37 点击ListView条目和Button得到的输出
代码中getView()方法不容易理解。其实完全可以不用所谓的convertView和ViewHolder,直接导入布局并且设置控件显示的内容就可以了。但是这意味着有多少行数据就需要绘制多少行ListView,这显然是不可取的。这里采用了一种优化的方法。代码中,在getView()方法中加入了一行log输出convertView的内容。滚动ListView,输出信息如图4-38所示。
从图4-38中可以看出,当启动Activity呈现第一屏ListView的时候,convertView为零。当用户向下滚动ListView时,上面的条目变为不可见,下面出现新的条目。这时候convertView不再为空,而是创建了一系列的convertView的值。当又往下滚一屏的时候,发现第11行的容器用来容纳第22行,第12行的容器用来容纳第23行。也就是说convertView相当于一个缓存,开始为0,当有条目变为不可见,它缓存了它的数据,后面再出来的条目只需要更新数据就可以了,这样大大节省了系统资料的开销。
还可以继续优化。虽然重复利用了已经绘制的view,但是要得到其中的控件,需要在控件的容器中通过findViewById的方法来获得。如果这个容器非常复杂,这显然会增加系统资源的开销。在上面的例子中,引入了Tag的概念。或许不是最好的办法,但是它确实能使ListView变得更流畅。代码中,当convertView为空时,用setTag()方法为每个View绑定一个存放控件的ViewHolder对象。当convertView不为空,重复利用已经创建的view的时候,使用getTag()方法获取绑定的ViewHolder对象,这样就避免了findViewById对控件的层层查询,而是快速定位到控件。
▲图4-38 滚动ListView输出的convertView的值
总结一下,这节介绍了用BaseAdapter来绑定ListView的数据。因为BaseAdapter非常灵活,使用也相对较其他控件麻烦。同时ListView的优化问题也值得读者去研究,一个流畅的ListView会带来更好的用户体验。
http://blog.csdn.net/wangjia55/article/details/7430759
http://www.oschina.net/code/snippet_203635_7475
[图片] 菜2.jpg
[图片] 菜.jpg
[代码] 主类
01
|
package com.android.wei.zidingyib;
|
02
|
03
|
import android.app.Activity;
|
04
|
import android.app.AlertDialog;
|
05
|
import android.os.Bundle;
|
06
|
import android.view.View;
|
07
|
import android.view.View.OnClickListener;
|
08
|
import android.widget.ImageButton;
|
09
|
import android.widget.ListView;
|
10
|
import java.util.*;
|
11
|
12
|
public class MyActivity extends Activity {
|
13
|
|
14
|
private ListView listView;
|
15
|
private ImageButton imageButton;
|
16
|
private ListViewAdapter listViewAdapter;
|
17
|
private List<Map<String,Object>> listItems;
|
18
|
private Integer[] imgeIDs = {
|
19
|
R.drawable.niao,R.drawable.niao,R.drawable.rui,R.drawable.rui,
|
20
|
R.drawable.ning,R.drawable.ning
|
21
|
};
|
22
|
private String[] goodsNames={
|
23
|
"土豆丝" , "土豆块" , "土豆泥" , "红烧土豆" ,
|
24
|
"麻辣土豆" , "清蒸土豆"
|
25
|
};
|
26
|
private String[] goodsDetails={
|
27
|
"土豆丝:便宜又好吃" , "土豆丝:便宜又好吃" , "土豆丝:便宜又好吃" ,
|
28
|
"土豆丝:便宜又好吃" , "土豆丝:便宜又好吃" , "土豆丝:便宜又好吃" ,
|
29
|
};
|
30
|
private int [] money={
|
31
|
2 , 3 , 3 , 10 , 8 , 13
|
32
|
};
|
33
|
|
34
|
public void onCreate(Bundle savedInstanceState) {
|
35
|
super .onCreate(savedInstanceState);
|
36
|
setContentView(R.layout.main);
|
37
|
listView=(ListView) this .findViewById(R.id.listview);
|
38
|
imageButton = (ImageButton) this .findViewById(R.id.imagebutton);
|
39
|
imageButton.setOnClickListener( new ClickEvent());
|
40
|
listItems = getListItems();
|
41
|
listViewAdapter = new ListViewAdapter( this ,listItems);
|
42
|
listView.setAdapter(listViewAdapter);
|
43
|
}
|
44
|
private List<Map<String,Object>> getListItems(){
|
45
|
List<Map<String,Object>> listItems = new ArrayList<Map<String,Object>>();
|
46
|
for ( int i= 0 ;i<goodsNames.length;i++){
|
47
|
Map<String,Object> map = new HashMap<String,Object>();
|
48
|
map.put( "image" , imgeIDs[i]);
|
49
|
map.put( "title" , goodsNames[i]);
|
50
|
map.put( "info" , money[i]+ "元" );
|
51
|
map.put( "detail" , goodsDetails[i]);
|
52
|
listItems.add(map);
|
53
|
}
|
54
|
return listItems;
|
55
|
}
|
56
|
class ClickEvent implements OnClickListener{
|
57
|
public void onClick(View v){
|
58
|
String goodsList= "" ;
|
59
|
int sun= 0 ;
|
60
|
for ( int i= 0 ;i<listItems.size();i++){
|
61
|
goodsList += listViewAdapter.hasChecked(i)?goodsNames[i]+ " " : "" ;
|
62
|
sun +=listViewAdapter.hasChecked(i)?money[i]: 0 ;
|
63
|
|
64
|
}
|
65
|
new AlertDialog.Builder(MyActivity. this )
|
66
|
.setTitle( "点菜清单" )
|
67
|
.setMessage( "你好,你选择的菜:\n" +goodsList+ "\n" + "总消费额为:" +sun+ "元" )
|
68
|
.setPositiveButton( "确定" , null )
|
69
|
.show();
|
70
|
|
71
|
}
|
72
|
}
|
73
|
}
|
[代码] 自定义的类
001
|
package com.android.wei.zidingyib;
|
002
|
003
|
import java.util.List;
|
004
|
import java.util.Map;
|
005
|
006
|
import android.app.AlertDialog;
|
007
|
import android.content.Context;
|
008
|
import android.view.LayoutInflater;
|
009
|
import android.view.View;
|
010
|
import android.view.ViewGroup;
|
011
|
import android.widget.BaseAdapter;
|
012
|
import android.widget.Button;
|
013
|
import android.widget.CheckBox;
|
014
|
import android.widget.CompoundButton;
|
015
|
import android.widget.ImageView;
|
016
|
import android.widget.TextView;
|
017
|
018
|
public class ListViewAdapter extends BaseAdapter{
|
019
|
private Context context;
|
020
|
|
021
|
private List<Map<String,Object>> listItems;
|
022
|
|
023
|
private LayoutInflater listContainer;
|
024
|
|
025
|
private boolean [] hasChecked;
|
026
|
public final class ListItemView{
|
027
|
public ImageView image;
|
028
|
public TextView title;
|
029
|
public TextView info;
|
030
|
public CheckBox check;
|
031
|
public Button detail;
|
032
|
}
|
033
|
|
034
|
public ListViewAdapter(Context context,List<Map<String,Object>> listItems){
|
035
|
this .context = context;
|
036
|
listContainer = LayoutInflater.from(context);
|
037
|
this .listItems = listItems;
|
038
|
hasChecked = new boolean [getCount()];
|
039
|
}
|
040
|
@Override
|
041
|
public int getCount() {
|
042
|
// TODO Auto-generated method stub
|
043
|
return listItems.size();
|
044
|
}
|
045
|
046
|
@Override
|
047
|
public Object getItem( int position) {
|
048
|
// TODO Auto-generated method stub
|
049
|
return null ;
|
050
|
}
|
051
|
052
|
@Override
|
053
|
public long getItemId( int position) {
|
054
|
// TODO Auto-generated method stub
|
055
|
return 0 ;
|
056
|
}
|
057
|
private void checkedChange( int checkedID){
|
058
|
hasChecked[checkedID] = !hasChecked[checkedID];
|
059
|
}
|
060
|
public boolean hasChecked( int checkedID){
|
061
|
return hasChecked[checkedID];
|
062
|
}
|
063
|
private void showDetailInfo( int clickID){
|
064
|
new AlertDialog.Builder(context)
|
065
|
.setTitle( "本菜详情:" +listItems.get(clickID).get( "title" ))
|
066
|
.setMessage(listItems.get(clickID).get( "detail" ).toString())
|
067
|
.setPositiveButton( "确定" , null )
|
068
|
.show();
|
069
|
}
|
070
|
071
|
@Override
|
072
|
public View getView( int position, View convertView, ViewGroup parent) {
|
073
|
final int selectID= position;
|
074
|
ListItemView listItemView = null ;
|
075
|
if (convertView == null ){
|
076
|
listItemView = new ListItemView();
|
077
|
convertView = listContainer.inflate(R.layout.list_item, null );
|
078
|
//获得控件对象
|
079
|
listItemView.image =(ImageView) convertView.findViewById(R.id.imageitem);
|
080
|
listItemView.title =(TextView) convertView.findViewById(R.id.textview);
|
081
|
listItemView.info =(TextView) convertView.findViewById(R.id.textview1);
|
082
|
listItemView.detail=(Button) convertView.findViewById(R.id.button);
|
083
|
listItemView.check = (CheckBox) convertView.findViewById(R.id.checkItem);
|
084
|
//设置空间集到convertView
|
085
|
convertView.setTag(listItemView);
|
086
|
} else {
|
087
|
listItemView = (ListItemView) convertView.getTag();
|
088
|
}
|
089
|
//设置文字图片
|
090
|
listItemView.image.setBackgroundResource((Integer)listItems.get(position).get( "image" ));
|
091
|
listItemView.title.setText((String)listItems.get(position).get( "title" ));
|
092
|
listItemView.info.setText((String) listItems.get(position).get( "info" ));
|
093
|
listItemView.detail.setText( "本菜介绍" );
|
094
|
listItemView.detail.setOnClickListener( new View.OnClickListener() {
|
095
|
|
096
|
@Override
|
097
|
public void onClick(View v) {
|
098
|
// TODO Auto-generated method stub
|
099
|
showDetailInfo(selectID);
|
100
|
}
|
101
|
});
|
102
|
listItemView.check.setOnCheckedChangeListener( new CheckBox.OnCheckedChangeListener(){
|
103
|
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked){
|
104
|
checkedChange(selectID);
|
105
|
}
|
106
|
});
|
107
|
return convertView;
|
108
|
}
|
109
|
110
|
}
|
Android BaseAdapter应用基础相关推荐
- 《Android移动应用基础教程》(Android Studio)(第二版)黑马程序员 课后习题答案
<Android移动应用基础教程>(Android Studio)(第二版)黑马程序员 课后习题答案 目录 第1章 Android基础入门 第2章 Android常见界面布局 第3章 An ...
- 湖南某科技大学 安卓Android移动开发基础期中考试笔记(持续更新)
湖南某科技大学 安卓Android移动开发基础期中考试笔记 前言 建议大家把第三章的三个实战演练和本笔记的所有代码部分都在AS中手打一遍,手打的意思是看懂之后自己写出来,而不是照着抄.这不90分就到手 ...
- 《Android 移动应用基础教程(Android Studio)(第2版)》【课本客观题】+【学习通2023春】【参考答案】
文章目录 超星学习通智能终端软件开发(基于Android Studio环境)章节作业(39) 一 二 三 四 五 六 课本一 课本二 课本三 课本四 课本五 课本六(无) 课本七 课本八 课本九 课本 ...
- android界面数据存储,Android应用开发基础之数据存储和界面展现(二)
Android应用开发基础之数据存储和界面展现(二) 常见布局 相对布局 RelativeLayout 组件默认左对齐.顶部对齐 设置组件在指定组件的右边 android:layout_toRight ...
- Android中的基础控件TextView、Button、ImageView、EditText、ProgressBar
文章目录 1 Android中的基础控件 1.1 控件的通用属性 2 TextView 2.1 TextView的继承关系 2.2 TextView的常用属性 3 EditText 3.1 常用属性 ...
- Android技能树 — 树基础知识小结(一)
前言: 现在安卓面试,对于数据结构的问题也越来越多了,也经常看到别人发的面试题都是问什么红黑树,二叉树查找等,所以我们虽然不会马上就会各种难的面试题,但起码树的基础知识还是要会的,这样才能去进一步学. ...
- 创建android程序时 默认使用布局是,《Android移动应用基础教程》中国铁道出版社课后习题(附答案)...
<Android移动应用基础教程>中国铁道出版社课后习题(附答案) 第2章Android UI开发 一.填空题 1.Android中的布局分为6种,分别是RelativeLayout.Li ...
- Android BaseAdapter与ListView的使用
Android BaseAdapter与ListView的使用 定义:BaseAdapterextends Objectimplements ListAdapter SpinnerAdapter Ba ...
- android 启动服务同时传递数据,Android Studio开发基础之起动Service,并通过从Activity向Service传递数据...
Android Studio开发基础之启动Service,并通过从Activity向Service传递数据 本实例演示启动Service,并通过从Activity向Service传递数据,新建一个Se ...
最新文章
- 自己动手安装ARM交叉编译工具链
- IDEA 在线翻译插件
- centos selinux mysql 5.6_centos 6.4下安装mysql 5.6.11
- matlab 通过矩阵变换使图像旋转平移_opencv图像处理——几何变换
- 成功解决 绘图时行坐标名或列坐标名出现f0、f1、f2、f3、f4、f5(或者Column_0、Column_1、Column_2、Column_3)等命名而不是想要的具体对应字段命名
- python pandas 读取excel 去重某一列_Python中Pandas读取修改excel操作攻略(代码示例)...
- boost::hana::take_front用法的测试程序
- 快速排序(quick sort)
- 使用Junit对Spring进行单元测试实战小结
- 混乱的MVC,.NET非要MVC不可么?
- 安卓开发经常闪退的原因及解决方法
- 《Android群英传:神兵利器》— Android 书籍
- Error running Tomcat8: Address localhost:1099 is already in use
- 非线性动力学_第17届全国非线性振动暨第14届全国非线性动力学 和运动稳定性学术会议在南京召开...
- 使用机器学习预测股价
- Simon‘s writting 全网最全笔记
- 洛谷p4230 连环病原体 题解
- excel中COUNTIFS函数用法
- Java无参构造方法的作用
- 初中数学503个必考知识点_干货丨初中数学必考的21个知识点
热门文章
- 在android中使用opencv,在安卓上使用OpenCV的指南 - kdnuggets
- python歌星大赛评分_2018年机器阅读理解技术竞赛模型,BLEU-4评分排名第6, ROUGE-L评分排名第14...
- 在JavaWeb中,什么是监听器?(建议收藏)
- 实验1-6 输出带框文字 (5 分)
- python入门系列:迭代器和生成器
- 模型驱动开发 - 产品线架构的演进
- 关于vue-axios的使用及跨域问题的解决
- typora工具的使用方法-一款非常适合程序员的工具
- C/C++:copy control (拷贝控制)
- 【求助】如何从 Spark 的 DataFrame 中取出具体某一行?我自己的一些思考