经过前面几期的学习,关于ListView的一些基本用法大概学的差不多了,但是你可能发现了,所有ListView里面要填充的数据都是静态的,但在实际开发中,这些数据往往都是动态变化的,比如数据内容发生改变、增加几行、或者删除几行,这就涉及到ListView数据的更新问题。
接下来通过一个简单的示例程序来学习ListView的数据更新。
继续使用WidgetSample工程,在app/main/res/layout/目录下创建updatedata_layout.xml文件,在其中填充如下代码片段:
<?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" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:gravity="center_horizontal"> <Button android:id="@+id/add_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="添加"/> <Button android:id="@+id/update_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="更新"/> <Button android:id="@+id/delete_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="删除"/> <Button android:id="@+id/clear_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="清空"/> </LinearLayout> <TextView android:id="@+id/empty_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:padding="15dp" android:textSize="15sp" android:text="暂无数据"/> <ListView android:id="@+id/listview" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout>
由于当ListView没有数据时,整个页面一片白,非常难看,所以加了一个文本框,当列表没有数据时提示用户。然后添加了4个按钮来动态更新列表数据。
接着在res/layout/目录下新建一个updatedata_item.xml的列表项布局文件,其代码如下:
<?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:gravity="center_vertical" android:orientation="horizontal"> <ImageView android:id="@+id/icon_img" android:layout_width="48dp" android:layout_height="48dp" android:padding="5dp"/> <TextView android:id="@+id/content_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="18sp" /> </LinearLayout>
然后创建数据实体类UpdateData.java,主要用于显示在列表数据的实体,这里比较简单,包括一个图标ID和文本内容,代码如下:
package com.jinyu.cqkxzsxy.android.listviewsample.entity; /** * @创建者 鑫鱻 * @描述 Android零基础入门到精通系列教程,欢迎关注微信公众号ShareExpert */ public class UpdateData { private int imgId; private String content; public UpdateData() {} public UpdateData(int imgId, String content) { this.imgId = imgId; this.content = content; } public int getImgId() { return imgId; } public String getContent() { return content; } public void setImgId(int imgId) { this.imgId = imgId; } public void setContent(String content) { this.content = content; } }
再创建MyUpdateAdapter类,继承BaseAdapter,再另外添加几个方法,便于操作ListView。
package com.jinyu.cqkxzsxy.android.listviewsample.adapter; 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 com.jinyu.cqkxzsxy.android.listviewsample.R; import com.jinyu.cqkxzsxy.android.listviewsample.entity.UpdateData; import java.util.LinkedList; import java.util.List; /** * @创建者 鑫鱻 * @描述 Android零基础入门到精通系列教程,欢迎关注微信公众号ShareExpert */ public class MyUpdateAdapter extends BaseAdapter { private Context mContext; private List<UpdateData> mUpdateData; public MyUpdateAdapter() {} public MyUpdateAdapter( Context context, List<UpdateData> UpdateDatas) { this.mUpdateData = UpdateDatas; this.mContext = context; } /** * 添加列表项 * @param position * @param UpdateData */ public void add(int position, UpdateData UpdateData){ if (null == mUpdateData) { mUpdateData = new LinkedList<>(); } mUpdateData.add(position,UpdateData); notifyDataSetChanged(); } /** * 更新列表内容 * @param UpdateDatas */ public void update(List<UpdateData> UpdateDatas){ if (null == mUpdateData) { mUpdateData = new LinkedList<>(); } mUpdateData.clear(); mUpdateData.addAll(UpdateDatas); notifyDataSetChanged(); } /** * 更新列表项 * @param position * @param UpdateData */ public void update(int position,UpdateData UpdateData){ if(mUpdateData != null && position < mUpdateData.size()) { mUpdateData.set(position, UpdateData); } notifyDataSetChanged(); } /** * 移除指定列表项 * @param position */ public void remove(int position) { if(mUpdateData != null && 0 != getCount()) { mUpdateData.remove(position); } notifyDataSetChanged(); } /** * 清空列表数据 */ public void clear() { if(mUpdateData != null) { mUpdateData.clear(); } notifyDataSetChanged(); } @Override public int getCount() { return mUpdateData.size(); } @Override public UpdateData getItem(int position) { return mUpdateData.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; if(null == convertView){ convertView = LayoutInflater.from(mContext).inflate(R.layout.updatedata_item, null); holder = new ViewHolder(); holder.img_icon = (ImageView) convertView.findViewById(R.id.icon_img); holder.txt_content = (TextView) convertView.findViewById(R.id.content_tv); convertView.setTag(holder); }else{ holder = (ViewHolder) convertView.getTag(); } UpdateData UpdateData = getItem(position); holder.img_icon.setImageResource(UpdateData.getImgId()); holder.txt_content.setText(UpdateData.getContent()); return convertView; } private class ViewHolder{ ImageView img_icon; TextView txt_content; } }
接下来为ListView提供Adapter,使用自定义的BaseAdapter决定ListView所要显示的列表项,然后为4个按钮设置监听监听器。新建UpdateDataActivity.java文件,加载上面新建的布局文件,具体代码如下:
package com.jinyu.cqkxzsxy.android.listviewsample; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Button; import android.widget.ListView; import com.jinyu.cqkxzsxy.android.listviewsample.adapter.MyUpdateAdapter; import com.jinyu.cqkxzsxy.android.listviewsample.entity.UpdateData; import java.util.LinkedList; import java.util.List; public class UpdateDataActivity extends AppCompatActivity implements View.OnClickListener { private ListView mListView = null; // 列表 private Button mAddBtn = null; // 添加列表项按钮 private Button mUpdateBtn = null; // 更新列表按钮 private Button mDeleteBtn = null; // 删除列表项按钮 private Button mClearBtn = null; // 清空列表数据 private MyUpdateAdapter mAdapter = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.updatedata_layout); // 获取界面组件 mListView = (ListView) findViewById(R.id.listview); mAddBtn = (Button) findViewById(R.id.add_btn); mUpdateBtn = (Button) findViewById(R.id.update_btn); mDeleteBtn = (Button) findViewById(R.id.delete_btn); mClearBtn = (Button) findViewById(R.id.clear_btn); // 添加列表控内容视图 View emptyView = findViewById(R.id.empty_tv); mListView.setEmptyView(emptyView); // 初始化列表 List<UpdateData> datas = new LinkedList<UpdateData>(); mAdapter = new MyUpdateAdapter(this, datas); mListView.setAdapter(mAdapter); // 设置按钮点击事件监听器 mAddBtn.setOnClickListener(this); mUpdateBtn.setOnClickListener(this); mDeleteBtn.setOnClickListener(this); mClearBtn.setOnClickListener(this); } @Override public void onClick(View view) { switch (view.getId()){ case R.id.add_btn: addItem(); break; case R.id.update_btn: updateData(); break; case R.id.delete_btn: deleteItem(); break; case R.id.clear_btn: clearData(); break; default: break; } } /** * 添加列表项 */ private void addItem() { int position = getRandomPosition(); mAdapter.add(position, new UpdateData(R.mipmap.ic_launcher, "随机添加" + position)); } /** * 更新列表内容 */ private void updateData() { int position = getRandomPosition(); mAdapter.update(position, new UpdateData(R.mipmap.ic_launcher, "更新" + getRandomNumber())); } /** * 删除列表项 */ private void deleteItem() { int position = getRandomPosition(); mAdapter.remove(position); } /** * 清空列表数据 */ private void clearData(){ mAdapter.clear(); } /** * 获取列表随机位置 * @return */ private int getRandomPosition() { int count = mAdapter.getCount(); return (int) (Math.random() * count); } /** * 获取100以内的随机数 * @return */ private double getRandomNumber(){ return Math.random() * 100; } }
修改启动的Activity,运行程序,可以看到下面左图所示界面效果。
然后点击添加按钮,在列表中随机添加一些列表项,可以看到列表数据动态更新,如上图右侧所示。
然后再点击更新按钮,可以随机更新列表数据,如下图左侧所示。
再点击删除按钮,可以看到将会从列表中删除随机列表项,如上图右侧所示。
点击清空按钮,可以将列表所有数据全部清空,显示启动时的页面。
从以上几个操作,可以看到动态更新时离不开每次调用notifyDataSetChanged()方法,这个方法的主要作用就是当适配器里面的内容发生改变时需要强制调用getView()方法来刷新每个Item的内容。
今天就先到这里,如果有问题欢迎留言一起探讨,也欢迎加入Android零基础入门技术讨论微信群,共同成长!
此文章版权为微信公众号分享达人秀(ShareExpert)——鑫鱻所有,若需转载请联系作者授权,特此声明!
往期总结分享:
Android零基础入门第1节:Android的前世今生
Android零基础入门第2节:Android 系统架构和应用组件那些事
Android零基础入门第3节:带你一起来聊一聊Android开发环境
Android零基础入门第4节:正确安装和配置JDK, 高富帅养成第一招
Android零基础入门第5节:善用ADT Bundle, 轻松邂逅女神
Android零基础入门第6节:配置优化SDK Manager, 正式约会女神
Android零基础入门第7节:搞定Android模拟器,开启甜蜜之旅
Android零基础入门第8节:HelloWorld,我的第一趟旅程出发点
Android零基础入门第9节:Android应用实战,不懂代码也可以开发
Android零基础入门第10节:开发IDE大升级,终于迎来了Android Studio
Android零基础入门第11节:简单几步带你飞,运行Android Studio工程
Android零基础入门第12节:熟悉Android Studio界面,开始装逼卖萌
Android零基础入门第13节:Android Studio配置优化,打造开发利器
Android零基础入门第14节:使用高速Genymotion,跨入火箭时代
Android零基础入门第15节:掌握Android Studio项目结构,扬帆起航
Android零基础入门第16节:Android用户界面开发概述
Android零基础入门第17节:TextView属性和方法大全
Android零基础入门第18节:EditText的属性和使用方法
Android零基础入门第19节:Button使用详解
Android零基础入门第20节:CheckBox和RadioButton使用大全
Android零基础入门第21节:ToggleButton和Switch使用大全
Android零基础入门第22节:ImageView的属性和方法大全
Android零基础入门第23节:ImageButton和ZoomButton使用大全
Android零基础入门第24节:自定义View简单使用,打造属于你的控件
Android零基础入门第25节:简单且最常用的LinearLayout线性布局
Android零基础入门第26节:两种对齐方式,layout_gravity和gravity大不同
Android零基础入门第27节:正确使用padding和margin
Android零基础入门第28节:轻松掌握RelativeLayout相对布局
Android零基础入门第29节:善用TableLayout表格布局
Android零基础入门第30节:两分钟掌握FrameLayout帧布局
Android零基础入门第31节:少用的AbsoluteLayout绝对布局
Android零基础入门第32节:新推出的GridLayout网格布局
Android零基础入门第33节:Android事件处理概述
Android零基础入门第34节:Android中基于监听的事件处理
Android零基础入门第35节:Android中基于回调的事件处理
Android零基础入门第36节:Android系统事件的处理
Android零基础入门第37节:初识ListView
Android零基础入门第38节:初识Adapter
Android零基础入门第39节:ListActivity和自定义列表项
Android零基础入门第40节:自定义ArrayAdapter
Android零基础入门第41节:使用SimpleAdapter
Android零基础入门第42节:自定义BaseAdapter
Android零基础入门第43节:ListView优化和列表首尾使用