因为之前一直想用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
地址:https://github.com/roofroot/test_view_binding