第十七个项目——使用接口回调实现删除ListView列表中的Item数据
实验目的
掌握如何删除ListView列表中的Item;
掌握如何使用接口回调在不同组件进行通信的方式;
实验要求
掌握使用接口回调在不同组件进行通信的方式;
实验内容
在第十六个项目中使用SwipeRefreshLayout为新闻列表页面增加了下拉刷新数据功能。实际工程项目中,在列表页面通常提供了删除某一Item数据的功能,本实验中通过在NewsAdapter中自定义名为OnItemDeleteListener接口,并通过接口回调的方式在MainActivity活动中实现删除指定id的新闻Item。
实现删除指定 id 的新闻 Item 的逻辑主要为:
在NewsAdapter中定义声明OnItemDeleteListener接口;
在NewsAdapter中实例化OnItemDeleteListener接口对象;
通过定义setOnItemDeleteListener()方法将OnItemDeleteListener接口对象给其他组件(本项目中是MainActivity);
在NewsAdapter.getView()方法中设置ImageView控件(id为iv_ delete) OnClick事件侦听器,并重写onClick()方法,在该方法中调用NewsAdapter中实例化的OnItemDeletedListener接口对象中的onDelete()方法;
在MainActivity中实现OnItemDeleteListener接口,并重写onDelete()方法,在该方法中实现删除指定id新闻Item的功能;
步骤一,打开第七个项目或第十六个项目
步骤二,更改list_ item.xml布局文件
在list_ item.xml布局中,需要加入相应用户点击删除操作的ImageView控件(id为iv_delete),代码如下所示。 其中使用layout_ alignParentEnd,layout_ below两个属性将ImageView控件放在布局的右下角。 ImageView控件的图片使用了Vector asset资源,通过右击项目【res】->【Vector Asset】弹出**Vector Asset对话框进行选择,如图1. Vector Asset资源选择对话框所示。
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="8dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
...
<TextView
android:id="@+id/tv_title"
style="@style/TextAppearance.AppCompat.Subhead"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/iv_image"
android:paddingTop="8dp"
android:paddingStart="8dp"
android:paddingBottom="4dp"
android:textColor="@color/colorPrimary"
android:textSize="18sp"
android:textStyle="bold" />
...
<ImageView
android:id="@+id/iv_delete"
android:src="@drawable/ic_close_black_24dp"
android:layout_alignParentEnd="true"
android:layout_below="@id/tv_title"
android:paddingEnd="8dp"
android:paddingBottom="8dp"
android:clickable="true"
android:layout_width="24dp"
android:layout_height="24dp" />
</RelativeLayout>
</android.support.v7.widget.CardView>

步骤三,更改NewsAdapter文件
1. 定义OnItemDeleteListener接口
在NewsAdapter类内定义OnItemDeleteListener接口类型,接口中声明一个onDelete(int id)抽象方法,其他组件实现接口时必须重写该方法。
2. 实现setOnItemDeleteListener()方法
NewsAdapter需要为其他组件提供设置OnItemDeleteListener接口对象的方法,在NewsAdapter中定义setOnItemDeleteListener()方法,该方法的参数为OnItemDeleteListener接口类型,这从其他组件实例化后传递进来的接口对象。
上述两步的代码如下所示。
public class NewsAdapter extends ArrayAdapter<News> {
...
private OnItemDeleteListener listener = null;
...
public interface OnItemDeleteListener {
public void onDelete(int id);
}
public void setOnItemDeleteListener (
OnItemDeleteListener listener) {
this.listener = listener;
}
...
}
3. 更新ViewHolder类声明
如果在第十六个项目的基础上进行实验,则需要更新ViewHolder类声明,添加一个名为ivDelete的ImageView控件对象,用于绑定list_ item.xml布局中的iv_ delete控件,具体代码如下所示。
public class NewsAdapter extends ArrayAdapter<News> {
...
class ViewHolder {
TextView tvTitle;
TextView tvAuthor;
ImageView ivImage;
ImageView ivDelete;
}
}
4. 更新getView()方法
在NewsAdapter.getView()方法中,首先绑定iv_ delete控件至ViewHolder的 ivDelete成员变量。并通过viewHolder.ivDelete.setTag(position)方法将当前Item的索引值保存起来,以便在该ivDelete控件对象OnClick事件触发时取出。
最后通过viewHolder.ivDelete.setOnClickListener()方法设置ivDelete控件对象的OnClick事件侦听器,在onClick方法中,首先判断listener对象(为OnItemDeleteListener接口对象)是否为空,如果不为空则直接调用其onDelete()方法。当其他组件通过调用NewsAdapter.setOnItemDeleteListener()方法设置了OnItemDelete侦听器时,相应的侦听器对象的onDelete()方法将被执行,从而实现删除指定id新闻Item的操作,具体代码如下所示。
public class NewsAdapter extends ArrayAdapter<News> {
@Override
public View getView(final int position, View convertView,
ViewGroup parent) {
...
if (convertView == null) {
view = LayoutInflater.from(getContext())
.inflate(resourceId, parent, false);
...
viewHolder.ivDelete = view.findViewById(R.id.iv_delete);
view.setTag(viewHolder);
} else {
view = convertView;
viewHolder = (ViewHolder) view.getTag();
}
...
viewHolder.ivDelete.setTag(position);
viewHolder.ivDelete.setOnClickListener(
new View.OnClickListener(){
@Override
public void onClick(View view) {
/*最简单的删除方式*/
/*
int i = (int) view.getTag();
mNewsData.remove(i);
notifyDataSetChanged();
*/
/*使用interface接口回调进行删除*/
if (listener != null) {
int id = (int) view.getTag();
listener.onDelete(id);
}
}
});
return view;
}
}
步骤四,在MainActivity中设置NewsAdapter的OnItemDelete事件侦听器
1. 设置NewsAdapter对象的OnItemDelete事件侦听器
在MainActivity活动的onCreate()方法中,实例化NewsAdapter对象后,通过setOnItemDeleteListener()方法设置OnItemDelete事件侦听器,传递的参数为匿名类接口。在重写匿名类接口的onDelete(int id)方法时,调用MainActivity类定义的私有方法removeData(int id),实际删除功能由该方法实现。
2. 定义removeData()方法实现删除指定 id 新闻Item
在本次实验中,删除指定id新闻的Item功能放在removeDta()方法中。在该方法中,通过调用newsList.remove(int id)方法删除指定id下标的数据,并调用NewsAdapter的notifyDataSetChanged()方法通知绑定适配器的ListView控件刷新数据,从而完成删除指定id新闻Item操作。
上述两步的代码具体如下所示。
public class MainActivity extends AppCompatActivity {
...
private List<News> newsList = new ArrayList<>();
private NewsAdapter newsAdapter = null;
private ListView lvNewsList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...
lvNewsList = findViewById(R.id.lv_news_list);
initData();
newsAdapter.setOnItemDeletedListener(
new NewsAdapter.OnItemDeleteListener() {
@Override
public void onDelete(int id) {
removeData(id);
}
});
lvNewsList.setAdapter(newsAdapter);
...
}
private void removeData(int id) {
newsList.remove(id);
newsAdapter.notifyDataSetChanged();
}
...
}
步骤五,编译并运行App
编译本项目,成功后在AVD上或物理机上运行App,初始化时,ListView显示近20条新闻列表,你可通过下拉刷新新增新闻(该功能在第十六个项目中实现),通过点击每条新闻右下方的删除图标可删除当前新闻Item,运行效果如图2. 在ListView中删除新闻Item所示。


实验小结
通过本次实验,你应该掌握了如下知识内容:
使用接口回调实现组件间通信;
使用接口回调实现删除ListView指定id新闻Item;
Last updated
Was this helpful?