Fragment中Adapter使用Picasso:无Context实现及构造器错误排查
其实Picasso本身就有很灵活的使用方式,完全不用在Adapter里持有Context引用,既避免内存泄漏,也适配Fragment场景,具体可以这么做:
利用ImageView自带的Context:Picasso在加载图片到
ImageView时,会自动从View本身获取关联的Context,所以你根本不需要手动传Context给Picasso。直接在onBindViewHolder里这么写就行:@Override public void onBindViewHolder(MyViewHolder holder, int position) { ListItem item = mListItems.get(position); // 直接加载,Picasso会自动从holder.imageView获取Context Picasso.get().load(item.getImageUrl()).into(holder.imageView); }用Application级别的Context初始化Picasso(可选):如果需要自定义Picasso的配置(比如缓存策略、日志),可以在你的Application类里初始化全局的Picasso实例,这样整个App都用同一个实例,而且用的是Application Context,不会和Fragment/Activity的生命周期绑定:
public class MyApp extends Application { @Override public void onCreate() { super.onCreate(); Picasso picasso = new Picasso.Builder(this) .loggingEnabled(true) .build(); Picasso.setSingletonInstance(picasso); } }之后在Adapter里直接用
Picasso.get()调用就好,完全不需要依赖任何Fragment/Activity的Context。
这样一来,你的Adapter不需要在构造器里接收Context,代码更简洁,还能避免因为持有Fragment/Activity Context导致的内存泄漏问题。
你遇到的constructor Adapter cannot be applied to given types错误,本质是调用Adapter时传入的参数和你定义的构造器参数不匹配,咱们一步步排查:
检查参数的数量、顺序和类型
你的Adapter构造器是public MyAdapter(Context context, List<ListItem> listItems, OnItemClickListener callback),那在Fragment里调用的时候,必须严格按照「Context → List→ OnItemClickListener」的顺序传参,且每个参数的类型完全一致。
比如正确的调用应该是:// 在Fragment的onCreateView或者onViewCreated里 List<ListItem> myList = ...; // 你的数据列表 MyAdapter adapter = new MyAdapter(getContext(), myList, this);这里要注意:
getContext()或者getActivity()返回的是有效的Context(Fragment attached的时候才不为null,别在onCreate里过早调用)myList必须是List<ListItem>类型,不能是其他泛型的List(比如List<Object>)this必须实现了OnItemClickListener接口,且接口的方法签名和Adapter里定义的完全一致
检查接口定义是否一致
确保你在Adapter里定义的OnItemClickListener接口,和Fragment实现的是同一个:// Adapter里的接口定义 public interface OnItemClickListener { void onItemClick(ListItem item); // 方法签名要完全匹配 }如果Fragment里实现的接口方法参数不对(比如写成
void onItemClick(int position)),也会导致编译器认为你传的Listener类型不匹配。检查是否import了错误的Adapter类
有时候会不小心import系统的android.widget.Adapter或者其他同名的Adapter类,而不是你自己写的MyAdapter。检查Fragment里的import语句,确保是你的自定义Adapter。检查构造器的访问修饰符
确保你的MyAdapter构造器是public的,如果写成了private或者protected,Fragment里无法访问,也会出现类似的错误(不过编译器提示可能会不一样,但也值得排查)。
如果以上都检查过还是有问题,可以把你在Fragment里调用Adapter的代码贴出来,就能更精准定位了。
内容的提问来源于stack exchange,提问作者RiM

