Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android列表分組及字母導航-重構(2)-注解

android列表分組及字母導航-重構(2)-注解

編輯:關於Android編程

上篇文章對listView 分組和字母索引導航進行了重構,重構之後,使新的實現只依賴於接口,而不是具體的Bo.但是還是要求原始的數據Bo實現接口或者繼承抽象類。能不能把這一步也簡化呢,只需要原始的數據Bolist? 答案是可以的,可以使用注解,也就是annnotion。

想法和思路

Java注解又叫java標注,java提供了一套機制,使得我們可以對方法、類、參數、包、域以及變量等添加標准(即附上某些信息)。且在以後某個時段通過反射將標注的信息提取出來以供使用。

分組listView 在上次重構後,最需要的信息就是“使用哪個字段進行分組導航”,故我們只要使用注解把這個信息標志出來即可。

另外還需要保存一些拼音等的緩存,那麼可以把原始的Bo包裝一下,利用泛型。下面一步步的來。

注解和Bo包裝

注解只要標記按照bo的哪個字段分組排序即可,且注解信息保留在運行時:

@Target(ElementType.TYPE)
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface RulerSortStr   {
    String sortField();
}


對Bo利用泛型對Bo進行包裝,包裝類實現之前的接口BoSort或者繼承抽象類DefaultBoSortImp,實現方法getSortStr時利用Bo的注解信息。

public class RulerListDataWrapper extends DefaultBoSortImp{
 
    private T data;
   
    public RulerListDataWrapper() {
       super();
    }
   
 
    public RulerListDataWrapper(T data) {
       super();
       this.data = data;
    }
 
 
    public T getData() {
       return data;
    }
 
 
 
    public void setData(T data) {
       this.data = data;
    }
 
 
 
/**  
    *    利用 T的注解信息實現此方法
    */
    @Override
    public String getSortStr() {
       Class temp = data.getClass();
       RulerSortStr anno = temp.getAnnotation(RulerSortStr.class);
       if (anno==null) {
           return "";
       }
       String sortField = anno.sortField();
       Field f;
       try {
           f = temp.getDeclaredField(sortField);
           f.setAccessible(true);
           return (String) f.get(data);
       } catch (Exception e) {
           e.printStackTrace();
           return "";
       }
    }
   
}


RulerUtil重構

此工具類也重構為泛型,此類把原始數據bo列表List構造為包裝器類型List>。添加的標簽也是包裝器類型(RulerListDataWrapper),泛型化之後,不再依賴具體的Bo.

public class RulerUtil {
 
   
    /**
     * 列表適配??
     */
    public static final String[] indexStr = { "#", "A", "B", "C", "D", "E", "F", "G", "H", 
            "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", 
            "V", "W", "X", "Y", "Z" };
    public static final char[] letters = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 
            'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 
            'V', 'W', 'X', 'Y', 'Z' };
   
    /**
     * @throws IllegalAccessException
     * @throws InstantiationException
     * @date 2014-7-28
     * @return返回處理後的數據
     * @Description:處理數據,排序,添加標簽
     */
    public   List> genSortedDataAndTagLocation(List myData, HashMap tagLocation) throws InstantiationException, IllegalAccessException {
      
      
       List> res = getList(myData);
       //首先排序
       Collections.sort(res, new Comparator>() {
           @Override
           public int compare(RulerListDataWrapper lhs, RulerListDataWrapper rhs) {
              char firChar = checkAndGetPinyin(lhs);
              char secChar = checkAndGetPinyin(rhs);
              if (firChar < secChar) {
                  return -1;
              } else if (firChar > secChar) {
                  return 1;
              } else
                  return 0;
           }
       });
 
       int size = res.size();
       int i = 0;
       char nowTag = '\0';
      
       for (i = 0; i < size; i++) {
           RulerListDataWrapper temp = res.get(i);
           char tempTag = checkAndGetPinyin(temp);
           if(Arrays.binarySearch(letters, tempTag) < 0){
              tempTag = '#';
           }
           if (nowTag != tempTag) {
              RulerListDataWrapper tagBO = new RulerListDataWrapper();
              tagBO.setTag(tempTag+"");
              res.add(i, tagBO);
              tagLocation.put(tempTag + "", i);
              i++;
              size++;
              nowTag = tempTag;
           }
       }
       tagLocation.put("#", 0);
       return res;
    }
   
    private  char checkAndGetPinyin(BoSort bo){
       String pinyinStr = bo.getSortStrPinyin();
       if (pinyinStr==null) {
           bo.setSortStrPinYin(HanziToPinyin.getPinYin(bo.getSortStr()).toUpperCase());
           pinyinStr = bo.getSortStrPinyin();
       }
       if(pinyinStr!=null&&pinyinStr.length()>=1){
           return pinyinStr.charAt(0);
       }
       return '\0';
    }
   
   
 
    public  List> getList(List data){
       List> res = new ArrayList>();
       for (T  t: data) {
           res.add(new RulerListDataWrapper(t));
       }
       return res;
    }


Activity和Adaptor

也都進行泛型化。

1.adaptor

首先是adaptor,其所需要的數據是List>,泛型化之後,如下:


public class RulerAdapter extends BaseAdapter{
 
    /**
     * 經過處理的數據
     */
    private List> list;
   
    /**
     * aa
     */
    private Context mContext;
   
   
    /**
     *
     */
    public RulerAdapter() {
       super();
       // TODO Auto-generated constructor stub
    }
 
 
    /**
     * @param list
     */
    public RulerAdapter(List> list) {
       super();
       this.list = list;
    }
 
    /**
     *
     */
    public RulerAdapter(List> list, Context mContext) {
       super();
       this.list = list;
       this.mContext = mContext;
    }
    public List> getList() {
       return list;
    }
 
 
    public void setList(List> list) {
       this.list = list;
    }
 
 
    public Context getmContext() {
       return mContext;
    }
 
 
    public void setmContext(Context mContext) {
       this.mContext = mContext;
    }
 
 
 
    @Override
    public int getCount() {
       return list.size();
    }
 
   
   
    @Override
    public RulerListDataWrapper getItem(int arg0) {
       // TODO Auto-generated method stub
       return list.get(arg0);
    }
 
   
   
    @Override
    public long getItemId(int position) {
       return 0;
    }
 
   
    /**  
    * @date 2014-9-3
    * @Description: 需要的時候覆蓋此方法,提供自己的自定義非標簽視圖
    * @param  
    * @return View
    */
    public View getContentView(int position,RulerListDataWrapper bo){
       return null;
    }
   
   
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
       ViewHolder holder;
 
       if (convertView == null) {
           convertView = LayoutInflater.from(mContext).inflate(R.layout.g_ruler_list_item, null);
           holder = new ViewHolder();
           holder.tag = (TextView) convertView.findViewById(R.id.g_ruler_list_item_tag);
           holder.content = (LinearLayout) convertView.findViewById(R.id.g_ruler_list_item);
           convertView.setTag(holder);
       } else {
           holder = (ViewHolder) convertView.getTag();
       }
// 依賴於RulerListDataWrapper
       final RulerListDataWrapper bo =  getItem(position);
      
       String tag = bo.getTag();
       if(tag!=null){//是標簽
           holder.tag.setVisibility(View.VISIBLE);
           holder.content.setVisibility(View.GONE);
 
           holder.tag.setText(tag);
       }else{//是內容
           //首先取自定義視圖,如果沒的話就自定義一個TextView add 到content中
           holder.content.removeAllViews();
           holder.tag.setVisibility(View.GONE);
           holder.content.setVisibility(View.VISIBLE);
           View contentView  = getContentView(position, bo);
           if(contentView==null){
              TextView textV = new TextView(mContext);
              textV.setText(bo.getSortStr());
              textV.setTextColor(Color.BLACK);
              textV.setGravity(Gravity.CENTER_VERTICAL);
              textV.setTextSize(16);
              contentView = textV;
           }
           holder.content.addView(contentView, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
       }
 
       return convertView;
    }
 
    static class ViewHolder{
       TextView tag;
       LinearLayout content;
    }

2.Activity

Activity也泛型化,主要是對RulerUtil的調用和 獲取數據時泛型化,其基本代碼如下:

public abstract class RulerActivity extends Activity{
 
    protected TextView noDataView;
   
    protected TextView RulerTag;
    protected ProgressBarWithText progress;
   
    protected ListView listView;
   
    protected RulerWidget ruler;
   
   
    private RulerAdapter rulerAdapter;
    private List originalList;
    private List> dealedList;
    private HashMap tagLocation = new HashMap();
   
    /**  
    *   
    */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.g_ruler);
       findView();
       initView();
       initData();
    }
 
   
 
    private void findView() {
       . . .
    }
    private void initView() {
       . . .
    }
    private void initData() {
       new GetDataAsyTask().execute();
    }
   
   
    /**  
    * @date 2014-9-4
    * @Description: 需要實現這個獲取數據的方法
    * @param  
    * @return List
    */
    public abstract List getDataList();
   
   
    /**  
    * @date 2014-9-3
    * @Description:
    * @param  
    * @return void
    */
    private void handleSuccessData() {
       . . .
      
    }
   
    /**
     * @Description: 獲取觸摸字母導航的時候,列表要滾動到的位置。如果觸摸的字母,在標簽tagLocation 映射中,不存,則向前尋找。
     */
    private Integer getPosition(final int j) {
       . . .
    }
    class GetDataAsyTask extends AsyncTask {
 
      
      
      
       @Override
       protected void onPreExecute() {
           super.onPreExecute();
           progress.setVisibility(View.VISIBLE);
       }
   
       @Override
       protected Void doInBackground(Void... params) {
           originalList = getDataList();
           try {
              dealedList = new RulerUtil().genSortedDataAndTagLocation(originalList, tagLocation);
           } catch (Exception e) {
              e.printStackTrace();
              if (dealedList!=null) {
                  dealedList.clear();
                  dealedList = null;
              }
             
              if (originalList!=null) {
                  originalList.clear();
                  originalList = null;
              }
              if (tagLocation!=null) {
                  tagLocation.clear();
                  tagLocation = null;
              }
           }
           return null;
       }
   
       @Override
       protected void onPostExecute(Void result) {
           progress.setVisibility(View.GONE);
           super.onPostExecute(result);
           if(dealedList==null){
              noDataView.setVisibility(View.VISIBLE);
              return;
           }
           handleSuccessData();
       }
    }
   
}

測試使用

測試使用只要繼承意思activity和對Bo使用注解即可:

如下:

1. Bo

使用注解,@RulerSortStr(sortField="testtr"),表名使用分組索引的字段為testtr。

@RulerSortStr(sortField="testtr")
public class TestAnnotationBo {
 
    private String testtr;
    private String test2;
 
   
    /**
     *
     */
    public TestAnnotationBo() {
       super();
       // TODO Auto-generated constructor stub
    }
 
    public TestAnnotationBo(String testtr, String test2) {
       super();
       this.testtr = testtr;
       this.test2 = test2;
    }
 
 
    public String getTesttr() {
       return testtr;
    }
 
    public void setTesttr(String testtr) {
       this.testtr = testtr;
    }
 
    public String getTest2() {
       return test2;
    }
 
    public void setTest2(String test2) {
       this.test2 = test2;
    }
   
}

2. activity

只需要繼承以上activity和實現獲取數據的方法接口

public class TestRulerAnnoActivity extends RulerActivity{
    @Override
    public List getDataList() {
       List res = new ArrayList();
       TestAnnotationBo a = new TestAnnotationBo("aa","sdds");
       TestAnnotationBo a1 = new TestAnnotationBo("阿姨","sdds");
       TestAnnotationBo b = new TestAnnotationBo("bb","sdds");
       TestAnnotationBo b1 = new TestAnnotationBo("爸爸","sdds");
       res.add(b1);
       res.add(a);
       res.add(a1);
       res.add(b);
       return res;
    }
}



重構完畢。

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