android-ViewList的通用ViewHold

在寫ViewList的時候要寫Adapter的時候,常常大量的代碼都是差很少的。java

1 ViewHoldandroid

2 if(convertView ==null ){}else{}數據結構

3 setTagapp

4 FIndElement 和 Set 等等ide

 

因此我想能不能寫一個通用的ViewHold的和通用的Adapter呢?函數

咱們來試試吧。測試

直接上代碼,而後再進行分析。 this

<?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數據結構 spa

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;
    }
}

通用的ViewHoldcode

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)); }
相關文章
相關標籤/搜索