- 适配器可以使两个接口兼容, 也就是通过一个接口实现另外一个接口的方法
- 比如现在有一个接口叫 AnimalRobot, 并且有两个方法: cry() 和 move. 还有一个接口叫 Dog, 也有两个方法叫 run() 和 bark(). 现在需要使用Dog实现AnimalRobot接口, 但是两个接口完全不兼容. 此时可以使用适配器实现接口兼容
- 适配器模式主要由三部分组成
- Target: 目标接口 (上面的AnimalRobit)
- Source: 被适配接口. (上面的Dog接口)
- Adapter: 对Adaptee接口与Target进行适配
- 假设现在有下面两个接口需要适配
Source 接口及实现类
public interface IAC220 {
void output220V();
}
public class AC220 implements IAC220 {
public int output220V(){
int output = 220;
return output;
}
}
Target目标接口
public interface DC5 {
int output5V();
}
- 适配器与适配者之间是继承(或实现)关系
- 适配器继承被适配类, 实现目标接口
- 适配器在重写目标接口的方法里使用父类方法实现适配
- 缺点: 因为java单继承的缘故,target类必须是接口,以便于Adapter去继承Source并实现target,完成适配的功能,但这样就导致了Adapter里暴露了Source类的方法,使用起来的成本就增加了
public class PowerAdapter extends AC220 implements DC5 {
@Override
public int output5V() {
int output = output220V();
return (output / 44);
}
}
- 对于同样的逻辑,我们在以对象适配器模式实现。我们保留AC220和DC5两个基本类,我们让Adapter持有source类的实例,然后再实现DC5,以这种持有对象的方式来实现适配器功能
public class PowerAdapter implements DC5{
private AC220 mAC220;
public PowerAdapter(AC220 ac220){
this.mAC220 = ac220;
}
@Override
public int output5V() {
int output = 0;
if (mAC220 != null) {
output = mAC220.output220V() / 44;
}
return output;
}
}
- 对于接口适配器模式,我们就不用担着眼于220->5,我们的接口可以有更多的抽象方法
- android开发中用的很多
public interface DCOutput {
int output5V();
int output9V();
int output12V();
int output24V();
}
设置一个中间适配器,用于实现默认的接口方法
/**
* Created by italkbb on 2018/1/24.
* 这里抽象类其实就写了空方法,等着子类去实现需要的方法。
*/
public abstract class PowerAdapter implements DCOutput{
protected AC220 mAC220;
public PowerAdapter(AC220 ac220){
this.mAC220 = ac220;
}
@Override
public int output5V() {
return mAC220.output220V();
}
@Override
public int output9V() {
return mAC220.output220V();
}
@Override
public int output12V() {
return mAC220.output220V();
}
@Override
public int output24V() {
return mAC220.output220V();
}
}
这样一来我们就只需要重写父类我们关心的方法了
private void initinterfaceAdapter() {
// 使用匿名类重写需要重写的方法
interfaceadapter.PowerAdapter powerAdapter = new PowerAdapter(new AC220()) {
@Override
public int output5V() {
int output = 0;
if (mAC220 != null) {
output = mAC220.output220V() / 44;
}
return output;
}
};
powerAdapter.output5V();
}
- 使用适配器完成自定义cardview
- 需要将restaurantCardArrayList (也就是ArrayList) 适配RecyclerView
- 使用对象适配器, source: ArrayList , target: RecyclerView,
- 使用ArrayList实现target中的
onBindViewHolder, onCreateViewHolder
等方法
public class RestaurantAdapter extends RecyclerView.Adapter<RestaurantAdapter.Viewholder> implements View.OnClickListener{
private Context context;
private ArrayList<RestaurantCard> restaurantCardArrayList;
private static final String TOKEN = "RO1Oxxrhr0ZE2nvxEvJ0ViejBTWKcLLhPQ7wg6GGPlGiHvjwaLPU2eWlt4myH3BC1CP4RSzIQ7UCFjZ-FBaF_4ToUYHfs6FF6FwipyMuz47xVvlpEr6gDv-2YRQUYnYx";
private RecyclerViewOnItemClickListener onItemClickListener;
public class Viewholder extends RecyclerView.ViewHolder {
private ImageView restaurantImage, starSymbol;
private TextView restaurantTitle, restaurantContent, restaurantRating;
private View root;
public Viewholder(@NonNull View root) {
super(root);
this.root = root;
restaurantImage = root.findViewById(R.id.restaurant_image);
restaurantTitle = root.findViewById(R.id.restaurant_title);
restaurantContent = root.findViewById(R.id.restaurant_content);
restaurantRating = root.findViewById(R.id.rating);
starSymbol = root.findViewById(R.id.star);
}
}
// Constructor
public RestaurantAdapter(Context context, ArrayList<RestaurantCard> restaurantCardArrayList) {
this.context = context;
this.restaurantCardArrayList = restaurantCardArrayList;
}
@NonNull
@Override
public RestaurantAdapter.Viewholder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View root = LayoutInflater.from(parent.getContext()).inflate(R.layout.restaurant_cardview_item, parent, false);
Viewholder vh = new Viewholder(root);
root.setOnClickListener(this);
return new RestaurantAdapter.Viewholder(root);
}
@Override
public void onBindViewHolder(@NonNull RestaurantAdapter.Viewholder holder, int position) {
RestaurantCard model = restaurantCardArrayList.get(position);
holder.restaurantContent.setText(model.getContent());
if (model.getTitle().length() > 24){
model.setTitle(model.getTitle().substring(0, 24) + "...");
}
holder.restaurantTitle.setText(model.getTitle());
holder.starSymbol.setImageResource(R.drawable.ic_baseline_star_24);
holder.restaurantRating.setText(Float.toString(model.getRating()));
Log.d("From RestaurentAdapter onBindViewHolder", "glide next");
if (model.getRestaurantImageUrl().toString().length() != 0) {
GlideUrl glideUrl = new GlideUrl(model.getRestaurantImageUrl(), new LazyHeaders.Builder()
.addHeader("Authorization", " Bearer " + TOKEN)
.build());
Glide.with(this.context).load(glideUrl).into(holder.restaurantImage);
}
else {
Log.d("From RestaurentAdapter onBindViewHolder", "getRestaurantImageUrl() is empty");
}
holder.root.setTag(position);
}
@Override
public int getItemCount() {
return restaurantCardArrayList.size();
}
@Override
public void onClick(View view) {
if (onItemClickListener != null) {
// Use getTag() to get data
onItemClickListener.onItemClickListener(view, (Integer) view.getTag());
}
}
public void setRecyclerViewOnItemClickListener(RecyclerViewOnItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
public interface RecyclerViewOnItemClickListener {
void onItemClickListener(View view, int position);
}
}
将Adapter传入recyclerView使用
RestaurantAdapter restaurantAdapter = new RestaurantAdapter(getActivity(), restaurantCardArrayList);
recyclerView.setAdapter(restaurantAdapter);
- 接口适配器模式
- ArrayAdapter有很多包含很多方法, 比如下面的方法
@Override
public int getCount() {
return mObjects.size();
}
@Override
public @Nullable T getItem(int position) {
return mObjects.get(position);
}
/**
* Returns the position of the specified item in the array.
*
* @param item The item to retrieve the position of.
*
* @return The position of the specified item.
*/
public int getPosition(@Nullable T item) {
return mObjects.indexOf(item);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public @NonNull View getView(int position, @Nullable View convertView,
@NonNull ViewGroup parent) {
return createViewFromResource(mInflater, position, convertView, parent, mResource);
}
使用内部匿名类实现其中需要的方法
listview.setAdapter(new ArrayAdapter<String>(this, R.layout.list_item, list) {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = super.getView(position, convertView, parent);
TextView textView = (view.findViewById(R.id.listItem));
textView.setMinHeight(0);
textView.setMinimumHeight(0);
textView.setHeight(height/ items.length);
return view;
}
});