设计模式6:适配器模式:ListView中的适配器模式到底是类适配器还是对象适配器?

几个重要类的源码

以下是Android 6.0版本的源代码。

/frameworks/base/core/java/android/widget/Adapter.java

Adapter.java
public interface Adapter {

	...
	
    int getCount();   
    
    Object getItem(int position);
    
    View getView(int position, View convertView, ViewGroup parent);
    
    boolean isEmpty();
    ...
}
ListAdapter.java

/frameworks/base/core/java/android/widget/ListAdapter.java

public interface ListAdapter extends Adapter {
    public boolean areAllItemsEnabled();
    boolean isEnabled(int position);
}
BaseAdapter.java

/frameworks/base/core/java/android/widget/BaseAdapter.java

public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {
    private final DataSetObservable mDataSetObservable = new DataSetObservable();

	...
    
    public void registerDataSetObserver(DataSetObserver observer) {
        mDataSetObservable.registerObserver(observer);
    }

    public void unregisterDataSetObserver(DataSetObserver observer) {
        mDataSetObservable.unregisterObserver(observer);
    }
    
	
    public void notifyDataSetChanged() {
        mDataSetObservable.notifyChanged();
    }

	...

    public boolean isEnabled(int position) {
        return true;
    }

	...

    public int getViewTypeCount() {
        return 1;
    }
    
    public boolean isEmpty() {
        return getCount() == 0;
    }
}
ArrayAdpater.java

/frameworks/base/core/java/android/widget/ArrayAdapter.java

public class ArrayAdapter<T> extends BaseAdapter implements Filterable, ThemedSpinnerAdapter {
    private List<T> mObjects;
    ...
    public ArrayAdapter(Context context, @LayoutRes int resource, @NonNull List<T> objects) {
        this(context, resource, 0, objects);
    }
    
    public ArrayAdapter(Context context, @LayoutRes int resource, @IdRes int textViewResourceId,
            @NonNull List<T> objects) {
        mContext = context;
        mInflater = LayoutInflater.from(context);
        mResource = mDropDownResource = resource;
        mObjects = objects;
        mFieldId = textViewResourceId;
    }
    
    public int getCount() {
        return mObjects.size();
    }
 
    public T getItem(int position) {
        return mObjects.get(position);
    }
    
    public View getView(int position, View convertView, ViewGroup parent) {
        return createViewFromResource(mInflater, position, convertView, parent, mResource);
    }
    
    private View createViewFromResource(LayoutInflater inflater, int position, View convertView,
            ViewGroup parent, int resource) {
        View view;
        TextView text;

        if (convertView == null) {
            view = inflater.inflate(resource, parent, false);
        } else {
            view = convertView;
        }

        try {
            if (mFieldId == 0) {
                //  If no custom field is assigned, assume the whole resource is a TextView
                text = (TextView) view;
            } else {
                //  Otherwise, find the TextView field within the layout
                text = (TextView) view.findViewById(mFieldId);
            }
        } catch (ClassCastException e) {
            Log.e("ArrayAdapter", "You must supply a resource ID for a TextView");
            throw new IllegalStateException(
                    "ArrayAdapter requires the resource ID to be a TextView", e);
        }

        T item = getItem(position);
        if (item instanceof CharSequence) {
            text.setText((CharSequence)item);
        } else {
            text.setText(item.toString());
        }

        return view;
    }
}
ArrayAdapter的具体使用
import java.util.ArrayList;

import android.app.Activity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;

public class Demo13Activity extends Activity {
    private ListView lv;
    private ArrayList<String> list = new ArrayList<String>();
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        lv = (ListView)findViewById(R.id.listview);
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(
                this,
                android.R.layout.simple_expandable_list_item_1,
                getData());
        lv.setAdapter(adapter);
    }
    
    private ArrayList<String> getData()
    {
        list.add("180平米的房子");
        list.add("一个勤劳漂亮的老婆");
        list.add("一辆宝马");
        list.add("一个强壮且永不生病的身体");
        list.add("一个喜欢的事业");
        return list;
    }
}
ListView.java

/frameworks/base/core/java/android/widget/ListView.java

public class ListView extends AbsListView {
	......
	
    @Override
    public void setAdapter(ListAdapter adapter) { //这里需要的是ListAdapter接口类型的入参
    ...
	}
	......
}

对象适配器模式

类适配器模式的三个角色:

  • 目标接口(dst: destination 目标,目的)
  • 源类(src:source 源)
  • 适配器

ListView做为client,它需要的目标接口(target interface)就是ListAdapter接口。
源类是数据源:ArrayList<String>
适配器是ArrayAdapter

ArrayAdapter在构造器中接受了ArrayList对象,赋值给private List<T> mObjects;。又通过mObject成员变量实现getCount(),getItem(),getView()方法。

所以ListView中的适配器模式是对象适配器模式,并不是类适配器模式。

ArrayAdapter解决了什么问题或者作用是什么?

完成了ArrayList<String>到ListAdapter的转换。
使用的时候给的源数据是ArrayList<String>, ListView需要的是ListAdapter,ArrayAdapter完成了从ArrayList<String>到ListAdapter的转换。

结论:ListView中的适配器模式是对象适配器模式,并不是类适配器模式。

这篇文章:Android设计模式系列-适配器模式 分析的蛮好,但是有误导。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhangjin1120

可靠的文章费时费力,希望支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值