2019-04-23设计模式-适配器模式

2019-04-23  本文已影响0人  猫KK

将现有类型转化成需要的类型

举一个简单的例子:手机充电器就是一个适配器,将交流电(现有类型),转换成手机需要的直流电(需要的类型)。在android中最直观的就是ListView:将后台的数据list(现有类型)通过Adapter转化成ListView展示的view(需要要的类型)。下面通过仿照ListView,来学习Adapter模式

自定一个View,继承自ScrollView,使得可以滑动

    public class MyList extends ScrollView {

    private LinearLayout mContent;

    public MyList(Context context) {
        this(context, null);
    }

    public MyList(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyList(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContent = new LinearLayout(context);
        mContent.setHorizontalGravity(LinearLayout.HORIZONTAL);
        addView(mContent, 0);
    }

    @Override
    public void addView(View child) {
        mContent.addView(child);
    }
}

在 MyList 中增加一个 LinearLayout ,重写 addView 方法,将 childView 增加到 LinearLayout 中。按照一般的逻辑,当后台给我们返回数据,我们需要往 MyList 中增加数据时:

    protected void initView() {
        //模拟后台数据,解析成一个 String 类型的列表
        List<String> date = new ArrayList<>();
        for (int i = 0; i < 100; i++) {
            date.add("" + i);
        }

        MyList myList = findViewById(R.id.my_list);
        //循环列表,在 MyList 中增加数据
        for (String s : date) {
            TextView itemView = (TextView) LayoutInflater.from(this).inflate(R.layout.login_text_view, null);
            itemView.setText(s);
            myList.addView(itemView);
        }
    }

像上面这样写没什么不对,但看起来不好,下面我们仿照ListView的Adapter来改写。定义 Adapter 接口

    
public interface Adapter {
    int getCount();

    View getItem(int position, ViewGroup parent);
}

定义两个方法,分别返回列表数和 MyList 需要了view类型,继续,实现一个真实的Adapter:

    public class MyListAdapter implements Adapter {

    private Context mContext;
    private List<String> mDate;

    public MyListAdapter(Context context, List<String> date) {
        this.mContext = context;
        this.mDate = date;
    }

    @Override
    public int getCount() {
        return mDate.size();
    }

    @Override
    public View getItem(int position, ViewGroup parent) {
        TextView itemView = (TextView) LayoutInflater.from(mContext).inflate(R.layout.login_text_view, parent, false);
        itemView.setText(mDate.get(position));
        return itemView;
    }
}

通过 MyListAdapter 的构造方法将 List<String> 传进来,通过将 getItem 方法,将适配好的view对象传出去,达到将 List<String> 的数据类型转化成 MyList 需要的View数据类型。接下来改写一下 MyList

    public class MyList extends ScrollView {

    private LinearLayout mContent;
    private Adapter mAdapter;

    public MyList(Context context) {
        this(context, null);
    }

    public MyList(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyList(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContent = new LinearLayout(context);
        mContent.setOrientation(LinearLayout.VERTICAL);
        addView(mContent, 0);
    }

    @Override
    public void addView(View child) {
        mContent.addView(child);
    }

    public void setAdapter(Adapter adapter) {
        this.mAdapter = adapter;
        if (mAdapter == null) {
            return;
        }
        int count = mAdapter.getCount();
        for (int i = 0; i < count; i++) {
            addView(mAdapter.getItem(i, mContent));
        }
    }
}

仿照ListView,增加一个 setAdapter 方法,通过 Adapter.getItem 获取对应的View添加到 LinearLayout 中。在Activity中使用:

    protected void initView() {

        List<String> date = new ArrayList<>();
        for (int i = 0; i < 100; i++) {
            date.add("" + i);
        }

        MyList myList = findViewById(R.id.my_list);
        MyListAdapter adapter = new MyListAdapter(this, date);
        myList.setAdapter(adapter);
    }

通过 Adapter 将 List<String> 类型的数据类型转化成 MyList 需要的View数据类型

上一篇下一篇

猜你喜欢

热点阅读