一:匿名内部类
- 一个Test类,里面
1)1个属性
2)1个方法
a.该方法传递的参数是一个接口对象,目的是在这个方法中可以通过这个对象来调用接口方法 - 接口对象的接口TestInterFace内部有一个方法test(供其他的对象/类调用)
- Main函数中,先创建一个Test的对象,并实现这个方法,那我们知道参数内部是一个接口对象,但是呢,这个对象的作用只在这里有用,仅仅起到一个中转站的作用,那我们就可以免去命名,使用匿名内部类({
直接复写功能就好了
})
class Test {
var v = "成员属性"
fun setInterFace(test: TestInterFace) {
test.test()//写法规范,实现时直接复写fun test()就好
}
}
/**
* 定义接口
*/
interface TestInterFace {
fun test()
}
fun main(args: Array<String>) {
var test = Test()
/**
* 采用对象表达式来创建接口对象,即匿名内部类的实例。
*/
test.setInterFace(object : TestInterFace {
override fun test() {
println("对象表达式创建匿名内部类的实例")
}
})
}
二.Lambda基础这位作者的返回值写的也很清楚
() -> Unit//表示无参数无返回值的Lambda表达式类型
(T) -> Unit//表示接收一个T类型参数,无返回值的Lambda表达式类型
(T) -> R//表示接收一个T类型参数,返回一个R类型值的Lambda表达式类型
(T, P) -> R//表示接收一个T类型和P类型的参数,返回一个R类型值的Lambda表达式类型
(T, (P,Q) -> S) ->
R//表示接收一个T类型参数和一个接收P、Q类型两个参数并返回一个S类型的值的Lambda表达式类型参数,返回一个R类型值的Lambda表达式类型
三.lambda表达式/匿名函数 1参1返回样例
当然也可以println这个参数测试
1.这段是RecyleView中的一个方法,listener不知道是啥类型,那就写一个lambeda表达式定义函数类型变量
(1参)->Unit,既然是无返回值,那怎么做到类型赋值呢,就类似set方法,函数类型this赋值
2.我们观察发现这个函数对象是没有名字的
//kotlin方法
//直接定义函数类型的变量 传入参数,所需的数据类型,无返回值
var listener:((itembean:ITEMBEAN)->Unit)?=null
//写个方法定义函数
fun setMyListener(listener:(itemBean:ITEMBEAN)->Unit){
this.listener=listener
}
四.Lambda进阶使用
-
如果需要参数(没有参数可以写()),就在小括号里写明参数类型,参数名可以省略,然后小括号后面加上->{},
-
->后面如果没有返回值就写Unit(见我们的样例3)
-
然后在大括号{}里面写上具体的方法实现
-
作为参数传递给高阶函数的时候,只需要写大括号{}方法体
五.来点夜里猛,lambda表达式结合点击传参【RecycleView点击事件】
刚开始adapter调用,进行lanmbda一参赋值
这边进行初始化,并且设定了listener这个函数型变量
我们点击后,先打印了4444,其次我们listener是赋值了一参的函数,并且这个函数体->println也会一起执行,那就打印了111111,
最后打印33333
六.补充说明
1. java设置点击事件(RecycleView)
1)《第一行代码》中介绍了RV没有setonItemClickListener(),我们可以自己根据需求对子项进行监听即抛去子项点击监听,点击事件右具体的View注册
a. onCreateViewHolder中定义的holder对象,可以setonClickListener监听其内部的任意属性(例如文字或图片)
b. 监听内部复写onClick方法即可
package com.example.recyclerviewtest;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.List;
public class FruitAdapter extends RecyclerView.Adapter<FruitAdapter.ViewHolder>{
private List<Fruit> mFruitList;
static class ViewHolder extends RecyclerView.ViewHolder {
View fruitView;
ImageView fruitImage;
TextView fruitName;
public ViewHolder(View view) {
super(view);
fruitView = view;
fruitImage = (ImageView) view.findViewById(R.id.fruit_image);
fruitName = (TextView) view.findViewById(R.id.fruit_name);
}
}
public FruitAdapter(List<Fruit> fruitList) {
mFruitList = fruitList;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit_item, parent, false);
final ViewHolder holder = new ViewHolder(view);
holder.fruitView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int position = holder.getAdapterPosition();
Fruit fruit = mFruitList.get(position);
Toast.makeText(v.getContext(), "you clicked view " + fruit.getName(), Toast.LENGTH_SHORT).show();
}
});
holder.fruitImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int position = holder.getAdapterPosition();
Fruit fruit = mFruitList.get(position);
Toast.makeText(v.getContext(), "you clicked image " + fruit.getName(), Toast.LENGTH_SHORT).show();
}
});
return holder;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
Fruit fruit = mFruitList.get(position);
holder.fruitImage.setImageResource(fruit.getImageId());
holder.fruitName.setText(fruit.getName());
}
@Override
public int getItemCount() {
return mFruitList.size();
}
}
2.Faraway当中holder只有一个view属性监听方式
1)实现
a. 来到BaseListFragment 里面有个getSpecialAdapter(),我们发现,所有显示条目的fragment,其adapter都是这个的子类
b.进入BaseListAdapter中,进入onBindView可以直接获取每个条目的View,(这里的holder只有一个属性view)那就给这里的itemView进行监听设置,setonClickListener()方法,我们发现其内部实际要传一个匿名类
**public void setOnClickListener(@Nullable OnClickListener l) 我们点开这个匿名内部类,发现他还是个只有一个待实现方法的接口,于是我们可以直接打开这个最深层接口,实现条目点击事件**
3.代码展示
详细说明 条目点击事件
-
java传递数据做法(定义一个接口,用于和主界面的调用,但耦合高)
1)定义LIstener接口,内部一个方法实现data数据的监听,并制定泛型是传入的泛型,
2)定义setMyListener供主界面交互(拿数据)
3)在itemview的监听中,调用click(data)方法设定数据 -
kotlin方法(目的是存入,拿到数据,具体见五)
a.定义listener对象是一个传入ITEMBEAN的无返回类型函数对象,
b.同样一个setMylistener取数据
c.监听,比较严格+空校验
c1)?.let
listener?.let { it(data) } 这里的it就是指当前的listener
c2)?.invokelistener?.invoke(data) 就是调用看1参函数进行赋值
d.内部it就代表了listener,传入data(c2好理解)
//所有下拉刷新和上拉加载更多列表界面adapter基类 再添加一个泛型
abstract class BaseListAdapter<ITEMBEAN,ITEMVIEW:View> : RecyclerView.Adapter<BaseListAdapter.BaseListHolder>(){
//直接复制会报错,因为原HomeHolde这里引用变成HomeAdapter.HomeHolder
//add 1.更新数据的操作 刷新操作建立List集合 接收数据
private var list=ArrayList<ITEMBEAN>()//用里面的list匿名内部类
//在集合中先清空 再添加
fun updateList(list: List<ITEMBEAN>?){//传入一个对应集合 到时候侧试一下传原lei还是内部类
/*封装后可空判断
if (list==null) return */
list?.let {
this.list.clear()
this.list.addAll(list)//牛逼
notifyDataSetChanged()//刷新一下
}
}
//上拉加载更多 在集合中添加即可
fun loadMore(list: List<ITEMBEAN>?){
list?.let {
this.list.addAll(list)
notifyDataSetChanged()
}
}
//调用HomeItemView进行home页面的填充 创建了条目view
//1.需要一个HomeHolder
class BaseListHolder(itemView: View): RecyclerView.ViewHolder(itemView){
}
//2.复写三个次级构造方法
//2.1 条目初始化进行数据绑定
override fun onBindViewHolder(holder: BaseListAdapter.BaseListHolder, position: Int) {
//如果是最后一条就不刷新view
if(position==list.size)
return
//拿到条目数据
val data=list.get(position)
//拿到条目View
val itemView=holder.itemView as ITEMVIEW
//条目刷新
//和之前一样 用泛型不知道该类型有没有这个方法 setDate
// itemView.setDate(data)
//定义一个方法
refreshItemView(itemView,data)
//条目点击事件
//设置点击事件 点开发现()是一个接口,并且只有一个方法 直接打开就行
itemView.setOnClickListener {
// listener.let(data) 空异常
listener?.let {
it(data)
}
//或者
/*
listener?.invoke(data)
* */
//java 做法,定义一个接口,回调给主界面
/* 3.回调 java式传参
if (listener!=null)
listener?.onClick(data)*/
}
}
//kotlin方法
//直接定义函数类型的变量 传入参数,所需的数据类型,无返回值
var listener:((itembean:ITEMBEAN)->Unit)?=null
//写个方法定义函数
fun setMyListener(listener:(itemBean:ITEMBEAN)->Unit){
this.listener=listener
}
/*2.定义listener接口对象 SOClick中利用其接口实现监听data的click方法
var listener:Listener<ITEMBEAN>? = null
//1.javaj接口 click和ITEMBean耦合高
interface Listener<ITEMBEAN>{//定义接口 监听条目data
fun onClick(data:ITEMBEAN)
}
2.传递listener 赋值
fun setMyListener(listener:Listener<ITEMBEAN>){
this.listener=listener
}
*/
//2.2返回条目数量-指的是产生fragment条目
override fun getItemCount(): Int {
/*在抓取类中限定size 最后的+1的空间放一个进度条,实现上拉加载更多的条目
* 进度条可以提取一个单独的view显示*/
return list.size+1 //用1.add建立的列表就可以调用list了
//最后一条显示进度条
}
//2.3 拿到homeView
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseListHolder {
if(viewType==1){
//最后一条
return BaseListHolder(LoadMoreView(parent?.context))
}
else{
//其他条目
return BaseListHolder(getItemView(parent.context))
}
}
//2.4根据位置返回type值 绝对界面或刷新框
override fun getItemViewType(position: Int): Int {
if(position==list.size)
return 1
else
return 0
}
// 通过Holder将view保存下来 要将当前类变为抽象类
abstract fun refreshItemView(itemView: ITEMVIEW,data:ITEMBEAN)
//获取条目View(泛型)
abstract fun getItemView(context: Context?): ITEMVIEW
}