• android-ViewList的通用ViewHold


    在写ViewList的时候要写Adapter的时候,经常大量的代码都是差不多的。

    1 ViewHold

    2 if(convertView ==null ){}else{}

    3 setTag

    4 FIndElement 和 Set 等等

    所以我想能不能写一个通用的ViewHold的和通用的Adapter呢?

    我们来试试吧。

    直接上代码,然后再进行分析。 

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        >
    
        <TextView
            android:id="@+id/title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="20pt"
            />
        <TextView
            android:id="@+id/context"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="15pt"/>
    
    </LinearLayout>

    Bean数据结构 

    public class Bean {
        String context;
        String title;
    
        public String getTitle() {
            return title;
        }
    
        public void setTitle(String title) {
            this.title = title;
        }
    
        public String getContext() {
            return context;
        }
    
        public void setContext(String context) {
            this.context = context;
        }
    }

    通用的ViewHold

    import android.content.Context;
    import android.util.SparseArray;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    
    /**
     * Created by sunfan on 15-4-19.
     * 通用的ViewHold类
     */
    public class CommonViewHold {
        private View mView;//当前页面
        private SparseArray<View> elements = new SparseArray<View>();//控件元素
    
        /**
         * 构造函数,当传入的convertView为null时对mView进行初始化,并设置tag
         * @param context
         * @param parent
         * @param resource
         */
        private CommonViewHold(Context context, ViewGroup parent, int resource) {
            mView = LayoutInflater.from(context).inflate(resource,parent,false);
            mView.setTag(this);
        }
    
        /**
         * 获取 CommonViewHold对象,包含 mView和layout里已经添加elements的容器
         * @param context
         * @param convertView
         * @param parent
         * @param resource
         * @return
         */
        public static CommonViewHold getViewHold(Context context ,View convertView,ViewGroup parent,int resource){
            if (convertView==null){
                return new CommonViewHold(context,parent,resource);
            }else{
                CommonViewHold viewHold = (CommonViewHold) convertView.getTag();
                return viewHold;
            }
        }
    
        public View getView() {
            return mView;
        }
    
        /**
         * 维护一个element的容器,如果容器里存在此控件则直接读取,如果不存在则通过findAndSetElement找到元素后
         * 写入容器中
         * @param viewId
         * @param <T>
         * @return
         */
        public <T extends View> T getElement(int viewId){
           View view = elements.get(viewId);
           if(view == null){
               view = mView.findViewById(viewId);
               elements.put(viewId,view);
           }
            return (T)view;
        }
    }

    通用的adapter

    import android.content.Context;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ArrayAdapter;
    
    import java.util.List;
    
    /**
     * Created by sunfan on 15-4-18.
     */
    public abstract class CommonArrayAdapter<T> extends ArrayAdapter{
        protected Context mContext;//当前上下文
        protected int mResource;//item
        protected int mPosition;//当前位置
        protected  CommonViewHold viewHold;//ViewHold的引用
    
        /**
         * 初始化
         * @param context
         * @param resource
         * @param objects
         */
        public CommonArrayAdapter(Context context, int resource, List objects) {
            super(context, resource, objects);
            this.mContext = context;
            this.mResource = resource;
        }
    
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            this.mPosition = position;
            viewHold = CommonViewHold.getViewHold(mContext,convertView,parent,mResource);
            findAndSetElement();
            return viewHold.getView();
        }
    
        /**
         * 需要实现控件的获取与赋值过程
         * 这里建议调用内部的viewhold对象里的获取控件的方法
         * 例如
         *   TextView title = super.viewHold.getElement(R.id.title);
             title.setText(bean.getTitle());
         */
        public abstract void findAndSetElement();
    
    }

    客户端

    import android.app.Activity;
    import android.content.Context;
    import android.os.Bundle;
    import android.view.Window;
    import android.widget.ListView;
    import android.widget.TextView;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class MainActivity extends Activity {
    
        ListView listView;
        List<Bean> beans = new ArrayList<Bean>();
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            requestWindowFeature(Window.FEATURE_NO_TITLE);
            setContentView(R.layout.activity_main);
            init();
            listView = (ListView) findViewById(R.id.list_view);
            listView.setAdapter(new MyAdapter(this, R.layout.list_item, beans));
    
        }
    
        /**
         * 实现CommonArrayAdapter的findAndSetElement方法
         */
        class MyAdapter extends CommonArrayAdapter<Bean> {
            public MyAdapter(Context context, int resource, List objects) {
                super(context, resource, objects);
            }
    
            @Override
            public void findAndSetElement() {
                TextView title = super.viewHold.getElement(R.id.title);
                TextView context = super.viewHold.getElement(R.id.context);
                Bean bean = beans.get(super.mPosition);
                title.setText(bean.getTitle());
                context.setText(bean.getContext());
            }
        }
    
        /*
        初始化测试数据
         */
        private void init() {
            Bean b1 = new Bean();
            b1.setTitle("title1");
            b1.setContext("content1content1content1content1content1content1content1content1content1content1content1content1");
            Bean b2 = new Bean();
            b2.setTitle("title2");
            b2.setContext("content2content2content2content2content2content2content2content2content2");
            Bean b3 = new Bean();
            b3.setTitle("title3");
            b3.setContext("content3content3content3content3content3content3content3content3");
            Bean b4 = new Bean();
            b4.setTitle("title4");
            b4.setContext("content4content4content4content4content4content4content4content4");
            Bean b5 = new Bean();
            b5.setTitle("title5");
            b5.setContext("content5content5content5content5content5content5content5content5content5content5content5");
            Bean b6 = new Bean();
            b6.setTitle("title6");
            b6.setContext("content6content6content6content6content6content6content6content6");
            Bean b7 = new Bean();
            b7.setTitle("title7");
            b7.setContext("content7content7content7content7content7content7content7content7");
    
            beans.add(b1);
            beans.add(b2);
            beans.add(b3);
            beans.add(b4);
            beans.add(b5);
            beans.add(b6);
            beans.add(b7);
        }
    }

    --------------以上为全部代码----------------------

    代码分析

    整个代码的流程和结构

    CommonViewHold 相比传统的Viewhold,他采用容器的方式存储元素,并且封装了客户端用来判断covertview为空的初始化操作

    提供了一个存放元素的容器

    private SparseArray<View> elements = new SparseArray<View>();//控件元素

    当然他提供有获取容器的方法

    /**
         * 维护一个element的容器,如果容器里存在此控件则直接读取,如果不存在则通过findAndSetElement找到元素后
         * 写入容器中
         * @param viewId
         * @param <T>
         * @return
         */
        public <T extends View> T getElement(int viewId){
           View view = elements.get(viewId);
           if(view == null){
               view = mView.findViewById(viewId);
               elements.put(viewId,view);
           }
            return (T)view;
        }

    然后就是做初始化的动作了。

    convertView==null的时候的判断,这一段逻辑其实很简单,如果不为空就直接返回,为空就初始化。
    private CommonViewHold(Context context, ViewGroup parent, int resource) {
            mView = LayoutInflater.from(context).inflate(resource,parent,false);
            mView.setTag(this);
        }
    
        /**
         * 获取 CommonViewHold对象,包含 mView和layout里已经添加elements的容器
         * @param context
         * @param convertView
         * @param parent
         * @param resource
         * @return
         */
        public static CommonViewHold getViewHold(Context context ,View convertView,ViewGroup parent,int resource){
            if (convertView==null){
                return new CommonViewHold(context,parent,resource);
            }else{
                CommonViewHold viewHold = (CommonViewHold) convertView.getTag();
                return viewHold;
            }
        }

    通用的commonAdapter是一个模板类

    public abstract class CommonArrayAdapter<T> extends ArrayAdapter

    关键属性,当用户实现findAndSet的时候需要使用这个引用来获取控件

      protected  CommonViewHold viewHold;//ViewHold的引用

    核心模板方法

     @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            this.mPosition = position;
            viewHold = CommonViewHold.getViewHold(mContext,convertView,parent,mResource);
            findAndSetElement();
            return viewHold.getView();
        }

    需要用户去实现的方法

        /**
         * 需要实现控件的获取与赋值过程
         * 这里建议调用内部的viewhold对象里的获取控件的方法
         * 例如
         *   TextView title = super.viewHold.getElement(R.id.title);
             title.setText(bean.getTitle());
         */
        public abstract void findAndSetElement();

    直接从客户端可以看到,代码是十分便捷的,只需要一个内部类重写commonAdapter的findAndSet方法即可。

     class MyAdapter extends CommonArrayAdapter<Bean> {
            public MyAdapter(Context context, int resource, List objects) {
                super(context, resource, objects);
            }
    
            @Override
            public void findAndSetElement() {
                TextView title = super.viewHold.getElement(R.id.title);
                TextView context = super.viewHold.getElement(R.id.context);
                Bean bean = beans.get(super.mPosition);
                title.setText(bean.getTitle());
                context.setText(bean.getContext());
            }
        }

    调用也变得很轻松

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            requestWindowFeature(Window.FEATURE_NO_TITLE);
            setContentView(R.layout.activity_main);
            init();
            listView = (ListView) findViewById(R.id.list_view);
            listView.setAdapter(new MyAdapter(this, R.layout.list_item, beans));
    
        }
  • 相关阅读:
    可以自己设计和定的报表工具!
    金山词霸取词冲突
    SSRS 2008 Domain User Issue
    第一次用AX2009正式版!
    顶级会议及期刊
    Python基础常识
    Ubuntu系统下查看安装的CUDA和CUDNN的版本
    js内字符串转数组的基本方法
    JavaScript之逻辑分支
    JS入门
  • 原文地址:https://www.cnblogs.com/sunfan1988/p/4441182.html
Copyright © 2020-2023  润新知