关于kotlin泛型的使用
因为之前一直想用kotlin开发,正好现在要开一个新项目,所以准备用kotlin来做。把我之前用的mvvm框架的java代码自动转成kotlin以后,有很多地方都报了异常,主要都是泛型的部分,由于框架的基础部分应用了很多泛型,导致自动转了以后很多地方都不符合语法,所以努力的查阅了很多资料,终于修改成了kotlin的代码。
网上很多关于kotlin的泛型的教程都讲的很复杂,形变,投影,协变,逆变,看了半天看的很迷惑。所以这块我把自己改好的源码贴出来,底下会放我整个框架的链接,kotlin的部分为了方便直接上传到了之前的mvvm框架练习的代码里面,这样对照java的源码,可以看一下比较复杂的情况,kotlin的代码是应该如何写的。我个人认为比看那些很多专业名词的教程要直观。下面先贴一个比较复杂的一个adapter的基类的java源码和kotlin源码。两个类是一样的只是语法实现不同。不太会用kotlin泛型的人。翻到这篇可以用来参考一下。上面是kotlin代码,下面是java的代码,这是一个recyclerview的适配器积累,包含footer的那种。也就是说会有两种不同的布局。加上我的框架使用了viewbinding。所以这一个文件用了三个泛型,算是比较复杂的。通过对比可以很好的掌握kotlin泛型的写法。文章最底下是整个框架的源码包含java和kotlin的。直接运行的话,是java的代码。kotlin部分也有使用的实例但是布局文件并没有放进来。也是非常的简单,可以根据代码推测出布局文件的样子。主要是比较懒不想单独传一个项目。所以只是在之前的框架的源码建了一个目录把这次改成kotlin的上传了。
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import androidx.viewbinding.ViewBinding
abstract class BaseHaveFooterAdapter<T, B:ViewBinding, F : ViewBinding> :RecyclerView.Adapter<BaseHaveFooterAdapter.ViewHolder<in ViewBinding>>{
var onItemClick: OnItemClick? = null
protected var mDatas:List<T>? = null
protected var context: android.content.Context
fun getmDatas(): List<T>? {
return mDatas
}
fun setmDatas(mDatas:List<T>?) {
this.mDatas = mDatas
}
constructor(context: android.content.Context) {
this.context = context
}
constructor(context: android.content.Context, mDatas: kotlin.collections.List<T>?) {
this.mDatas = mDatas
this.context = context
}
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): ViewHolder<in ViewBinding> {
val inflater = LayoutInflater.from(context)
if (viewType == 0) {
val binding = setBinding(inflater, parent)
val viewHolder = BaseHaveFooterAdapter.ViewHolder<B>(binding!!.root)
viewHolder.binding=binding;
if (onItemClick != null) {
viewHolder.onItemClick = onItemClick
}
return viewHolder as ViewHolder<in ViewBinding>;
} else {
val binding = setFootBinding(inflater, parent)
val viewHolder =
BaseHaveFooterAdapter.ViewHolder<F>(binding!!.root)
viewHolder.binding=binding;
if (onItemClick != null) {
viewHolder.onItemClick = onItemClick
}
return viewHolder as ViewHolder<in ViewBinding>;
}
}
override fun onBindViewHolder(
holder: BaseHaveFooterAdapter.ViewHolder<ViewBinding>,
position: Int
): kotlin.Unit {
if (position == mDatas?.size) {
val myholder =
holder as BaseHaveFooterAdapter.ViewHolder<B>
onBindFooterHolder(myholder, position)
} else {
val myholder =
holder as BaseHaveFooterAdapter.ViewHolder<F>
onBindHolder(myholder, position)
}
}
protected abstract fun onBindHolder(
holder: ViewHolder<F>,
position: Int
): kotlin.Unit
protected abstract fun onBindFooterHolder(
holder: ViewHolder<B>,
position: Int
): kotlin.Unit
override fun getItemViewType(position: Int): Int {
return if (position == mDatas!!.size) 1 else 0
}
override fun getItemId(position: Int): kotlin.Long {
return position.toLong()
}
protected abstract fun setBinding(inflater: LayoutInflater?, parent: ViewGroup?): B
protected abstract fun setFootBinding(inflater: LayoutInflater?, parent: ViewGroup?): F
override fun getItemCount(): Int {
return if (mDatas == null) 1 else mDatas!!.size + 1
}
class ViewHolder<in ViewBinding>(itemView: android.view.View) :
RecyclerView.ViewHolder(itemView), android.view.View.OnClickListener {
var onItemClick: com.dsf.dsfwarehouse.base.BaseHaveFooterAdapter.OnItemClick? =
null
var binding: androidx.viewbinding.ViewBinding? = null
fun setClick(vararg views: android.view.View): kotlin.Unit {
if (onItemClick != null) {
for (view in views) {
view.setOnClickListener(this)
}
}
}
fun setOnFooterClick(vararg views: android.view.View) {
if (onItemClick != null) {
for (view in views) {
view.setOnClickListener { v -> onItemClick?.onFooterClick(v) }
}
}
}
override fun onClick(v: android.view.View){
onItemClick?.onClick(v, getAdapterPosition())
}
}
interface OnItemClick {
fun onClick(view: android.view.View, position: Int)
fun onFooterClick(view: android.view.View)
}
}
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.List;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewbinding.ViewBinding;
/**
* Created by Administrator on 16-7-18.
*/
public abstract class BaseHaveFooterAdapter<T, B extends ViewBinding,F extends ViewBinding> extends RecyclerView.Adapter<BaseHaveFooterAdapter.ViewHolder> {
protected OnItemClick onItemClick;
protected List<T> mDatas;
protected Context context;
public List<T> getmDatas() {
return mDatas;
}
public void setmDatas(List<T> mDatas) {
this.mDatas = mDatas;
}
public BaseHaveFooterAdapter(Context context) {
this.context = context;
}
public BaseHaveFooterAdapter(Context context, List<T> mDatas) {
this.mDatas = mDatas;
this.context = context;
}
public OnItemClick getOnItemClick() {
return onItemClick;
}
public void setOnItemClick(OnItemClick onItemClick) {
this.onItemClick = onItemClick;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
if(viewType==0) {
B binding = setBinding(inflater, parent);
ViewHolder<B> viewHolder = new ViewHolder<B>(binding.getRoot());
viewHolder.setBinding(binding);
if (onItemClick != null) {
viewHolder.setOnItemClick(onItemClick);
}
return viewHolder;
}else{
F binding = setFootBinding(inflater, parent);
ViewHolder<F> viewHolder = new ViewHolder<F>(binding.getRoot());
viewHolder.setBinding(binding);
if (onItemClick != null) {
viewHolder.setOnItemClick(onItemClick);
}
return viewHolder;
}
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
if(position==mDatas.size()){
ViewHolder<F> myholder = (ViewHolder<F>) holder;
onBindFooterHolder(myholder, position);
}else {
ViewHolder<B> myholder = (ViewHolder<B>) holder;
onBindHolder(myholder, position);
}
}
protected abstract void onBindHolder(ViewHolder<B> holder, int position);
protected abstract void onBindFooterHolder(ViewHolder<F> holder, int position);
@Override
public int getItemViewType(int position) {
return position == mDatas.size() ? 1 : 0;
}
@Override
public long getItemId(int position) {
return position;
}
protected abstract B setBinding(LayoutInflater inflater, ViewGroup parent);
protected abstract F setFootBinding(LayoutInflater inflater, ViewGroup parent);
@Override
public int getItemCount() {
return mDatas == null ? 1: mDatas.size() + 1;
}
public static class ViewHolder<B extends ViewBinding> extends RecyclerView.ViewHolder implements View.OnClickListener {
protected OnItemClick onItemClick;
public B binding;
public OnItemClick getOnItemClick() {
return onItemClick;
}
public void setOnItemClick(OnItemClick onItemClick) {
this.onItemClick = onItemClick;
}
public B getBinding() {
return binding;
}
public void setBinding(B binding) {
this.binding = binding;
}
public ViewHolder(View itemView) {
super(itemView);
}
public void setClick(View... views) {
if (onItemClick != null) {
for (View view : views) {
view.setOnClickListener(this);
}
}
}
public void setOnFooterClick(View... views) {
if (onItemClick != null) {
for (View view : views) {
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onItemClick.onFooterClick(v);
}
});
}
}
}
@Override
public void onClick(View v) {
onItemClick.onClick(v, getAdapterPosition());
}
}
public static interface OnItemClick {
void onClick(View view, int position);
void onFooterClick(View view);
}
}
源码已经上传github
上一篇: CSS设计的一些原则
下一篇: Swift泛型的一些理解