zoukankan      html  css  js  c++  java
  • Android开发进阶 -- 通用适配器 CommonAdapter

          在Android开发中,我们经常会用到ListView 这个组件,为了将ListView 的内容展示出来,我们会去实现一个Adapter来适配,将Layout中的布局以列表的形式展现到组件中。

        比如,像 GGTalk 安卓版的查找用户功能,会把符合条件的用户都列在下面:

          

          为了达到这个效果,我们需要实现一个自定义的Adapter,而其它地方的ListView也要实现一个Adapter,这些Adapter会有很多重复的代码,非常繁琐,现在我就将重复代码封装到了一个通用的适配器CommonAdapter中,这样,在使用时只要继承CommonAdapter就可以了,如此就避免了大段代码的重复,让代码更简洁易懂。我们先来看看CommonAdapter的定义。  

    一.CommonAdapter 实现

    public abstract class CommonAdapter<T> extends BaseAdapter {
    
        private List<T> dataList;
        protected Context context;
        protected int item_layoutId=0;
        protected HashMap<Integer,Integer> layoutIdMap; //多种itemView时用到。 第一个int对应type类型,第二个int对应 itemlayoutId
    
        /**
         * 设置单个子模版VIew,
         * @param context
         * @param datas 绑定的对象集合
         * @param item_layoutId 被绑定的视图layoutID
        * */
        public CommonAdapter(Context context, List<T> datas, int item_layoutId)
        {
            this.context=context;
            this.dataList=datas;
            this.item_layoutId=item_layoutId;
        }
    
        /**
         *设置多个子模版VIew, 并配合重写 getItemViewType(int position)来确定是设置哪个模版
         * @param context
         * @param datas 绑定的对象集合
         * @param layoutIdMap 多种itemViewID Map 第一个int对应type类型,第二个int对应 itemlayoutId
        */
        public CommonAdapter(Context context, List<T> datas, HashMap<Integer,Integer> layoutIdMap)
        {
            this.context=context;
            this.dataList=datas;
            this.layoutIdMap=layoutIdMap;
        }
    
        @Override
        public int getViewTypeCount() {
            if(this.layoutIdMap==null)
            {
                return 1;
            }
            return this.layoutIdMap.size();
        }
    
    
        @Override
        public int getCount() {
            return this.dataList.size();
        }
    
        @Override
        public Object getItem(int position) {
            return this.dataList.get(position);
        }
    
        @Override
        public long getItemId(int position) {
            return position;
        }
    
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            int type = getItemViewType(position);
            return getConvertView(position,convertView,type);
        }
    
        private View getConvertView(int position,View convertView,int itemViewType)
        {
            if(convertView==null)
            {
                int layoutId =0;
                if(this.item_layoutId!=0)
                {
                    layoutId=this.item_layoutId;
                }
                if (this.layoutIdMap != null) {
                    layoutId = this.layoutIdMap.get(itemViewType);
                }
                convertView = LayoutInflater.from(context).inflate(layoutId, null);
            }
            T t = this.dataList.get(position);
            this.setConvertView(convertView,t,itemViewType);
            return convertView;
        }
    
        /**
         * 局部更新数据,调用一次getView()方法;Google推荐的做法
         *
         * @param parent  要更新的listview
         * @param position 要更新的位置
         */
        public void onOneItemChanged(ListView parent, int position) {
            /**第一个可见的位置**/
            int firstVisiblePosition = parent.getFirstVisiblePosition();
            /**最后一个可见的位置**/
            int lastVisiblePosition = parent.getLastVisiblePosition();
    
            /**在看见范围内才更新,不可见的滑动后自动会调用getView方法更新**/
            if ((position >= firstVisiblePosition && position <= lastVisiblePosition)) {
    
                /**获取指定位置view对象**/
                View view = parent.getChildAt(position - firstVisiblePosition);
                getView(position, view, parent);
            }
        }
    
        /**
         * 需要去实现的对item中的view的设置操作
         *
         * @param convertView 转换后的试图
         * @param t Model对象
         * @param itemViewType 试图类型。对应layoutIdMap中的key
         */
        protected abstract void setConvertView(View convertView, T t,int itemViewType);
    }

     说明如下:

    (1)泛型参数<T>就是我们要绑定数据Model对象的class类型。

    (2)getViewTypeCount()方法会根据HashMap是否为空来识别是传入的单一模版还是多模版.

    (3)CommonAdapter还重写了getCount(),getItem(int position),getView,getConvertView等BaseAdapter 的方法,这些方法的代码都基本每个Adapter都是一样的,我们只需关心 setConvertView 这个抽象方法,在子类中重写它,将具体的逻辑和数据的绑定在此即可。

    二.使用CommonAdapter

    1. 先建一个类继承CommonAdapter,在构造函数中调用父类的构造方法以初始化数据。实现 setConvertView 方法,将对象的数据绑定到模版上 即可
      public class SearchFriendAdapter extends CommonAdapter<OrayUser> {
            /**
           * 设置单个子模版VIew,
           * @param context
           * @param datas 绑定的对象集合
           * @param item_layoutId 被绑定的视图layoutID
          * */
         public SearchFriendAdapter(Context context,List<OrayUser> datas,int item_layoutId)
         {
             super(context,datas,item_layoutId);
         }
        @Override
        protected void setConvertView(View view, OrayUser orayUser,int itemViewType)
        {
          ...具体将对象的数据绑定到模版上
        }
      } 
    2. Activity中使用时new 一个Adapter,然后将adapter绑定到 ListView
      adapter = new SearchFriendAdapter(this,this.userList,R.layout.friend_child);
      listView.setAdapter(adapter);
    3. 更新数据源中的数据同步到View
      //有2种方式将数据源同步到View
      adapter.notifyDataSetChanged();//全部刷新
      adapter.onOneItemChanged(ListView parent, int position);//刷新指定位置的数据 

    三. 让CommonAdapter支持多模板

          当然CommonAdapter还支持多模版的应用,我们只需将第一步中的Adapter实现稍稍做改动即可

    public class ListViewAdapter extends CommonAdapter<ListViewItemModel> {
        /**
         *设置多个子模版VIew, 并配合重写 getItemViewType(int position)来确定是设置哪个模版
         * @param context
         * @param datas 绑定的对象集合
         * @param layoutIdMap 多种itemViewID Map 第一个int对应type类型,第二个int对应 itemlayoutId
        */
        public ListViewAdapter(Context context, List<ListViewItemModel> datas, HashMap<Integer,Integer> layoutIdMap)
        {
            super(context,datas,layoutIdMap);
        }
        @Override
        public int getItemViewType(int position)
        {
            ListViewItemModel model=  (ListViewItemModel)super.getItem(position);
            if(model.floatRight)
            {
                return 1;
            }
            return 0;
        }
        @Override
        protected void setConvertView(View view, ListViewItemModel listViewItemModel,int itemViewType) {
        //根据itemViewType 的值来识别是哪个模版,以对应给模版绑定数据       
        }
    }

    如上图我们将构造函数的最后一个参数从单一的layoutID 换成了 模版集合的HashMap,再就是多加了 getItemViewType(int position) 方法来返回 具体Model对应的是哪一个模版类型(即hashMap 中的key值),使用时更新数据源中的数据同步到View和上面的单一模版一样使用。(同上2种更新方法)

            HashMap<Integer,Integer> layoutMap=new HashMap<>();
            layoutMap.put(0,R.layout.listview_item);//key值最好从0开始向上递增,否则可能会找不到key的BUG
            layoutMap.put(1,R.layout.listview_right_item);
            adapter=new ListViewAdapter(this,models,layoutMap);
            listView.setAdapter(adapter);

     四.综合实例

          最后我们还是以本文开头的查找用户的例子,来更全面地说明CommonAdapter的使用。页面截图如下:

          

     1.模版布局

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/layout"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/selector_item"
        android:descendantFocusability="blocksDescendants"
        android:gravity="center_vertical"
        android:orientation="horizontal"
        android:padding="4dp">
    
        <ImageView
            android:id="@+id/ct_photo"
            android:layout_width="@dimen/headImageSize"
            android:layout_height="@dimen/headImageSize"
            android:layout_margin="5dp"
            android:src="@drawable/plus"
            />
    
        <ImageView
            android:id="@+id/ct_status"
            android:layout_width="11dip"
            android:layout_height="11dip"
            android:layout_marginLeft="@dimen/headImageSize"
            android:layout_marginTop="@dimen/headImageSize"
            android:src='@drawable/status_2' />
    
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center_vertical"
            android:layout_alignTop="@id/ct_photo"
            android:layout_toRightOf="@id/ct_photo"
            >
    
            <TextView
                android:id="@+id/ct_name"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:paddingLeft="5dp"
                android:paddingRight="5dp"
                android:paddingBottom="5dp"
                android:paddingTop="0dp"
                android:text="name"
                android:textColor="@color/dimgrey"
                android:textSize="16sp"
                android:textStyle="bold" />
    
            <TextView
                android:id="@+id/ct_describe"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="10dp"
                android:layout_toRightOf="@id/ct_name"
                android:paddingLeft="5dp"
                android:paddingRight="5dp"
                android:paddingBottom="5dp"
                android:paddingTop="0dp"
                android:text="describe"
                android:textColor="@color/dimgrey"
                android:textSize="14sp"
                android:visibility="gone" />
        </LinearLayout>
        <TextView
            android:id="@+id/ct_sign"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignBottom="@id/ct_photo"
            android:layout_toRightOf="@id/ct_photo"
            android:paddingLeft="5dp"
            android:text="sign"
            android:singleLine="true"
            android:ellipsize="start"
            android:textColor="@color/dimgrey"
            android:textSize="12sp" />
    
    </RelativeLayout>
    

    2.具体继承CommonAdapter实现子类

    public class SearchFriendAdapter extends CommonAdapter<OrayUser> {
       public SearchFriendAdapter(Context context,List<OrayUser> datas,int item_layoutId)
       {
           super(context,datas,item_layoutId);
       }
    
        @Override
        protected void setConvertView(View view, OrayUser orayUser,int itemViewType) {
            try{
                SearchFriendAdapter.ViewHolder holder;
                if(view.getTag()==null)
                {
                    holder = new SearchFriendAdapter.ViewHolder(view);
                    view.setTag(holder);
                }
                else {
                    holder = (SearchFriendAdapter.ViewHolder) view.getTag();
                }
                HeadImgHelper.setUserHeadImg(holder.headImg,orayUser);
                if(orayUser.getName().equals(orayUser.getCommentName()))
                {
                    holder.userName.setText(orayUser.getName());
                }
                else {
                    holder.userName.setText(orayUser.getCommentName()+"("+ orayUser.getName()+")");
                }
                String catalogName= ClientGlobalCache.getInstance().getCurrentUser().getCatalogNameByFriend(orayUser.getUserID());
                if(!StringHelper.isNullOrEmpty(catalogName))
                {
                    holder.describe.setText("[ "+ catalogName+" ]");
                    holder.describe.setVisibility(View.VISIBLE);
                }
                else
                {
                    holder.describe.setText("");
                    holder.describe.setVisibility(View.GONE);
                }
                holder.orgName.setText(orayUser.getUserID());
            }catch (Exception ex){ex.printStackTrace();}
        }
    
        private class ViewHolder
        {
            public ImageView headImg;
            public TextView userName;
            public TextView describe;
            public TextView orgName;
    
            public ViewHolder(View view)
            {
                this.headImg = (ImageView) view.findViewById(R.id.ct_photo);
                ImageView statusImg=(ImageView) view.findViewById(R.id.ct_status);
                statusImg.setVisibility(View.GONE);
                this.userName=(TextView) view.findViewById(R.id.ct_name);
                this.orgName=(TextView) view.findViewById(R.id.ct_sign);
                this.describe=(TextView) view.findViewById(R.id.ct_describe);
            }
        }
    }

    3. Activity类 核心代码

    public class SearchFriendActivity extends Activity implements TextView.OnEditorActionListener{
        private DrawableEditText input;
        private ListView listView;
        private TextView search_resultStr;
        private List<OrayUser> userList=new ArrayList<OrayUser>() ;
        private SearchFriendAdapter adapter;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_search_friend);
            this.initView();
        }
    
        private void initView()
        {
            TextView pageTitle=(TextView)findViewById(R.id.headerText);
            pageTitle.setText("查找用户");
            search_resultStr =(TextView) findViewById(R.id.search_resultStr);
            listView=(ListView)findViewById(R.id.listview_user);
            listView.setOnItemClickListener(this);
            adapter = new SearchFriendAdapter(this,this.userList,R.layout.friend_child);
            listView.setAdapter(adapter);       
    
        }   /**
         * 执行点击搜索指令
         * */
        private void action_search(String idOrName)
        {
            List<OrayUser> temp_users=Manager.getInstance().doSearchUser(idOrName);
            search_resultStr.setText("没有找到符合条件的用户或群组");
            this.setSearchResult(temp_users);
        }
    
        private void setSearchResult(List<OrayUser> temp_users)
        {
            this.userList.clear();
            if(temp_users==null||temp_users.size()==0)
            {
                search_resultStr.setVisibility(View.VISIBLE);
            }
            else
            {
                for (OrayUser orayUser :temp_users) {
                    if(orayUser.getUserID().equals(ClientGlobalCache.getInstance().getCurrentUser().getUserID()))
                    {
                        temp_users.remove(orayUser);
                        break;
                    }
                }
                this.userList.addAll(temp_users) ;
                search_resultStr.setVisibility(View.GONE);
            }
            this.adapter.notifyDataSetChanged();
        }
    }
  • 相关阅读:
    将PHP文件生成静态文件源码
    Entity Framework Code First 学习日记(6)一对多关系
    Entity Framework Code First 学习日记(5)
    Entity Framework Code First 学习日记(3)
    Entity Framework Code First 学习日记(7)多对多关系
    Entity Framework Code First学习日记(2)
    Entity Framework Code First 学习日记(8)一对一关系
    Entity Framework Code First 学习日记(9)映射继承关系
    Entity Framework Code First 学习日记(10)兼容遗留数据库
    Entity Framework Code First 学习日记(4)
  • 原文地址:https://www.cnblogs.com/justnow/p/12096752.html
Copyright © 2011-2022 走看看