Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android SimpleAdapter源碼詳解

Android SimpleAdapter源碼詳解

編輯:關於Android編程

[java]
<SPAN style="FONT-FAMILY: SimHei; FONT-SIZE: 18px"></SPAN> 

一直沒認真看過android的源碼,也不太敢看,稀裡糊塗也敲了一年的代碼,現在想好好學習了,就把常用的源碼都看了一下,小伙伴們來漲姿勢吧,有錯誤的地方,直接指出,我臉厚不怕丟人。來吧。

剛開始學android的時候我經常使用SimpleAdapter,但是後來經常用到的對象實體,SimpleAdapter也就不符合要求了,一直自己繼承BaseAdapter,但是有的地方用SimpleAdapter還是比較方便的,一句話就搞定了,也不用寫Adapter,所以來悄悄源碼吧。
SimpleAdapter的初始化:
[java] 
<SPAN style="FONT-FAMILY: SimHei; FONT-SIZE: 18px"></SPAN> 

[java] 
<SPAN style="FONT-FAMILY: SimHei; FONT-SIZE: 18px"></SPAN><PRE class=java name="code">SimpleAdapter sAdapter=new SimpleAdapter(this, mList, R.layout.activity_main,new String[]{"name","pwd"},new int[]{R.id.tv_name,R.id.tv_pwd});</PRE> 
<PRE></PRE> 
<PRE class=java name="code"><SPAN style="FONT-FAMILY: SimHei; FONT-SIZE: 18px">下面是android的源碼,加了詳細的注釋,不用再多說:</SPAN></PRE><PRE class=java name="code" sizcache="1" sizset="7"><SPAN style="FONT-FAMILY: SimHei; FONT-SIZE: 18px"></SPAN><PRE class=java name="code">public class SimpleAdapter extends BaseAdapter implements Filterable { 
    private int[] mTo; // 指向布局裡面控件的id 比如:R.id.btn  
    private String[] mFrom; // 數據來源,來自Map裡面的key  
    private ViewBinder mViewBinder;// 接口類型,裡面有個setViewValue方法,用於出現特殊類型控件比如:drawable的時候在外部初始化接口,實現具體方法  
 
    private List<? extends Map<String, ?>> mData;// 用List打包的Map數據源  
 
    private int mResource;// 布局  
    private int mDropDownResource;// 不知道干嘛用的,但是估計也是留給外部調用的  
    private LayoutInflater mInflater;// 這個大家都知道,LayoutInflater用來載入界面  
 
    private SimpleFilter mFilter;// 過濾器,一般用不到  
    private ArrayList<Map<String, ?>> mUnfilteredData; 
 
    // SimpleAdapter初始化,將傳進了的參數都賦給本地的對應變量  
    public SimpleAdapter(Context context, List<? extends Map<String, ?>> data, 
            int resource, String[] from, int[] to) { 
        mData = data; 
        mResource = mDropDownResource = resource; 
        mFrom = from; 
        mTo = to; 
        mInflater = (LayoutInflater) context 
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
    } 
 
    /*
     * ListView 針對每個item,要求 adapter “返回一個視圖” (getView),
     * 也就是說ListView在開始繪制的時候,系統首先調用getCount()函數,根據他的返回值得到ListView的長度,
     * 然後根據這個長度,調用getView()一行一行的繪制ListView的每一項。如果你的getCount()返回值是0的話,
     * 列表一行都不會顯示,如果返回1,就只顯示一行。返回幾則顯示幾行。如果我們有幾千幾萬甚至更多的item要顯示怎麼辦?
     * 為每個Item創建一個新的View?不可能!!!實際上Android早已經緩存了這些視圖,大家可以看下下面這個截圖來理解下,
     * 這個圖是解釋ListView工作原理的最經典的圖了大家可以收藏下,不懂的時候拿來看看,加深理解,
     * 其實Android中有個叫做Recycler的構件
     */ 
    public int getCount() { 
        return mData.size(); 
    } 
 
    public Object getItem(int position) { 
        return mData.get(position); 
    } 
 
    public long getItemId(int position) { 
        return position; 
    } 
 
    public View getView(int position, View convertView, ViewGroup parent) { 
        // 調用createViewFromResource來優化內存  
        return createViewFromResource(position, convertView, parent, mResource); 
    } 
 
    /*
     * ListView的機制在這裡再說一下,當第一個數據來getView的時候convertView肯定是null,
     * 那麼就用mInflater.inflate(resource, parent,
     * false)給它初始化一個View,但是當一屏滑到底了,第一個item,滑出了屏幕,那麼它將
     * 從底部出來,那時候convertView就不為null,這個方法的好處就是當convertView不為null
     * 的時候不用加載布局,直接使用convertView, 節省了一步,這也是所說的優化ListView的第一個步驟。
     */ 
    private View createViewFromResource(int position, View convertView, 
            ViewGroup parent, int resource) { 
        View v; 
        if (convertView == null) { 
            v = mInflater.inflate(resource, parent, false); 
        } else { 
            v = convertView; 
        } 
        // 這個方法是核心  
        bindView(position, v); 
 
        return v; 
    } 
 
    public void setDropDownViewResource(int resource) { 
        this.mDropDownResource = resource; 
    } 
 
    @Override 
    public View getDropDownView(int position, View convertView, ViewGroup parent) { 
        return createViewFromResource(position, convertView, parent, 
                mDropDownResource); 
    } 
 
    // 這個方法的主要功能就是按照 to數組裡面控件的順序挨個賦值,比如new int[]{R.id.tv_name,R.id.tv_pwd}。  
    private void bindView(int position, View view) { 
        final Map dataSet = mData.get(position);// 找到對應的position位置的map數據  
        // 如果沒找到跳出  
        if (dataSet == null) { 
            return; 
        } 
        /*
         * 將外部實現的ViewBinder,賦值給本地,SimpleAdapter能夠實現:
         * checkBox,CheckedTextView,TextView
         * ,ImageView,數據類型也就是Boolean,Integer,Stirng, 所以特殊數據類型的時候才用到ViewBinder
         * ,如果沒用到就不需要外部實現ViewBinder接口和裡面的方法
         */ 
        final ViewBinder binder = mViewBinder; 
        final String[] from = mFrom; 
        final int[] to = mTo; 
        final int count = to.length; 
//view.findViewById(to[i]),循環找控件  
        for (int i = 0; i < count; i++) { 
            final View v = view.findViewById(to[i]); 
            //如果v不為空的話,找到對應的數據,Object類型的data轉換為String,因為boolean在map裡面純的也是true或者false  
            if (v != null) { 
                final Object data = dataSet.get(from[i]); 
                String text = data == null ? "" : data.toString(); 
                if (text == null) { 
                    text = ""; 
                } 
//標志變量bound,判斷外部有沒有實現ViewBinder,如果實現了,就執行binder.setViewValue(v, data, text),如果符合特殊條件,就返回true  
                boolean bound = false; 
                if (binder != null) { 
                    bound = binder.setViewValue(v, data, text); 
                } 
//如果滿足if (!bound)那麼bound就還是false,說明是普通數據  
                if (!bound) { 
                    //查看v是不是Checkable的實例化類型,滿足的情況可能是CheckBox,CheckedTextView  
                    if (v instanceof Checkable) { 
                        //如果數據類型是boolean,那麼就是CheckBox  
                        if (data instanceof Boolean) { 
                            ((Checkable) v).setChecked((Boolean) data); 
                            //如果不是CheckBox,那麼判斷是不是繼承TextView的CheckedTextView,是的話賦值,不是就拋出異常  
                        } else if (v instanceof TextView) { 
                            setViewText((TextView) v, text); 
                        } else { 
                            throw new IllegalStateException(v.getClass() 
                                    .getName() 
                                    + " should be bound to a Boolean, not a " 
                                    + (data == null ? "<unknown type>" 
                                            : data.getClass())); 
                        } 
                        //如果不是Checkable的實例化類型,判斷是不是TextView的實例化類型  
                    } else if (v instanceof TextView) { 
                        setViewText((TextView) v, text); 
                        //都不是以上情況,就判斷一下是不是ImageView的實例化類型  
                    } else if (v instanceof ImageView) { 
                        //這裡只滿足數據類型為int也就是R.drawable.ic,和String類型的url,如果想實現直接用drawbale,就要實現ViewBinder  
                        if (data instanceof Integer) { 
                            setViewImage((ImageView) v, (Integer) data); 
                        } else { 
                            setViewImage((ImageView) v, text); 
                        } 
                    } else { 
                        throw new IllegalStateException( 
                                v.getClass().getName() 
                                        + " is not a " 
                                        + " view that can be bounds by this SimpleAdapter"); 
                    } 
                } 
            } 
        } 
    } 
 
    public ViewBinder getViewBinder() { 
        return mViewBinder; 
    } 
 
    public void setViewBinder(ViewBinder viewBinder) { 
        mViewBinder = viewBinder; 
    } 
 
    public void setViewImage(ImageView v, int value) { 
        v.setImageResource(value); 
    } 
 
    public void setViewImage(ImageView v, String value) { 
        try { 
            v.setImageResource(Integer.parseInt(value)); 
        } catch (NumberFormatException nfe) { 
            v.setImageURI(Uri.parse(value)); 
        } 
    } 
 
    public void setViewText(TextView v, String text) { 
        v.setText(text); 
    } 
 
    public Filter getFilter() { 
        if (mFilter == null) { 
            mFilter = new SimpleFilter(); 
        } 
        return mFilter; 
    } 
 
    public static interface ViewBinder { 
        boolean setViewValue(View view, Object data, String textRepresentation); 
    } 
//這個不知道干嘛用的,也沒用過,好像是過濾數據的  
    private class SimpleFilter extends Filter { 
 
        @Override 
        protected FilterResults performFiltering(CharSequence prefix) { 
            FilterResults results = new FilterResults(); 
 
            if (mUnfilteredData == null) { 
                mUnfilteredData = new ArrayList<Map<String, ?>>(mData); 
            } 
 
            if (prefix == null || prefix.length() == 0) { 
                ArrayList<Map<String, ?>> list = mUnfilteredData; 
                results.values = list; 
                results.count = list.size(); 
            } else { 
                String prefixString = prefix.toString().toLowerCase(); 
 
                ArrayList<Map<String, ?>> unfilteredValues = mUnfilteredData; 
                int count = unfilteredValues.size(); 
 
                ArrayList<Map<String, ?>> newValues = new ArrayList<Map<String, ?>>( 
                        count); 
 
                for (int i = 0; i < count; i++) { 
                    Map<String, ?> h = unfilteredValues.get(i); 
                    if (h != null) { 
 
                        int len = mTo.length; 
 
                        for (int j = 0; j < len; j++) { 
                            String str = (String) h.get(mFrom[j]); 
 
                            String[] words = str.split(" "); 
                            int wordCount = words.length; 
 
                            for (int k = 0; k < wordCount; k++) { 
                                String word = words[k]; 
 
                                if (word.toLowerCase().startsWith(prefixString)) { 
                                    newValues.add(h); 
                                    break; 
                                } 
                            } 
                        } 
                    } 
                } 
 
                results.values = newValues; 
                results.count = newValues.size(); 
            } 
 
            return results; 
        } 
 
        @Override 
        protected void publishResults(CharSequence constraint, 
                FilterResults results) { 
            // noinspection unchecked  
            mData = (List<Map<String, ?>>) results.values; 
            if (results.count > 0) { 
                notifyDataSetChanged(); 
            } else { 
                notifyDataSetInvalidated(); 
            } 
        } 
    } 
}</PRE><BR> 
<STRONG><BR> 
最近在公司漲了很多姿勢,大部分是Java的繼承,接口,多態,抽象這些學過但是理解很膚淺的東西,以前自己寫軟件沒什麼規范,也沒怎麼去抽象,所以代碼很不上檔次,老鳥看到我的代碼就笑話我,現在我准備好好學一下,希望自己有一天也能寫出很正規的代碼。</STRONG><PRE class=java name="code"></PRE><PRE class=java name="code"></PRE> 
<PRE></PRE> 
<PRE></PRE> 
 
</PRE> 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved