android列表分组及字母导航-重构(2)-注解

来源:互联网 发布:软件系统结构图 visio 编辑:程序博客网 时间:2024/06/14 12:52

上篇文章对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<T> 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<T>构造为包装器类型List<RulerListDataWrapper<T>>。添加的标签也是包装器类型(RulerListDataWrapper<T>),泛型化之后,不再依赖具体的Bo.

public class RulerUtil<T> {        /**     * 列表适配�?     */    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<RulerListDataWrapper<T>> genSortedDataAndTagLocation(List<T> myData, HashMap<String, Integer> tagLocation) throws InstantiationException, IllegalAccessException {                   List<RulerListDataWrapper<T>> res = getList(myData);       //首先排序       Collections.sort(res, new Comparator<RulerListDataWrapper<T>>() {           @Override           public int compare(RulerListDataWrapper<T> lhs, RulerListDataWrapper<T> 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<T> temp = res.get(i);           char tempTag = checkAndGetPinyin(temp);           if(Arrays.binarySearch(letters, tempTag) < 0){              tempTag = '#';           }           if (nowTag != tempTag) {              RulerListDataWrapper<T> tagBO = new RulerListDataWrapper<T>();              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<RulerListDataWrapper<T>> getList(List<T> data){       List<RulerListDataWrapper<T>> res = new ArrayList<RulerListDataWrapper<T>>();       for (T  t: data) {           res.add(new RulerListDataWrapper<T>(t));       }       return res;    }


Activity和Adaptor

也都进行泛型化。

1.adaptor

首先是adaptor,其所需要的数据是List<RulerListDataWrapper<T>>,泛型化之后,如下:


public class RulerAdapter<T> extends BaseAdapter{     /**     * 经过处理的数据     */    private List<RulerListDataWrapper<T>> list;       /**     * aa     */    private Context mContext;          /**     *     */    public RulerAdapter() {       super();       // TODO Auto-generated constructor stub    }      /**     * @param list     */    public RulerAdapter(List<RulerListDataWrapper<T>> list) {       super();       this.list = list;    }     /**     *     */    public RulerAdapter(List<RulerListDataWrapper<T>> list, Context mContext) {       super();       this.list = list;       this.mContext = mContext;    }    public List<RulerListDataWrapper<T>> getList() {       return list;    }      public void setList(List<RulerListDataWrapper<T>> 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<T> 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<T> 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<T>       final RulerListDataWrapper<T> 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<T> extends Activity{     protected TextView noDataView;       protected TextView RulerTag;    protected ProgressBarWithText progress;       protected ListView listView;       protected RulerWidget ruler;          private RulerAdapter<T> rulerAdapter;    private List<T> originalList;    private List<RulerListDataWrapper<T>> dealedList;    private HashMap<String, Integer> tagLocation = new HashMap<String, Integer>();       /**      *       */    @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<? extends BoSort>    */    public abstract List<T> getDataList();          /**      * @date 2014-9-3    * @Description:    * @param      * @return void    */    private void handleSuccessData() {       . . .          }       /**     * @Description: 获取触摸字母导航的时候,列表要滚动到的位置。如果触摸的字母,在标签tagLocation 映射中,不存,则向前寻找。     */    private Integer getPosition(final int j) {       . . .    }    class GetDataAsyTask extends AsyncTask<Void, Void, Void> {                          @Override       protected void onPreExecute() {           super.onPreExecute();           progress.setVisibility(View.VISIBLE);       }          @Override       protected Void doInBackground(Void... params) {           originalList = getDataList();           try {              dealedList = new RulerUtil<T>().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<TestAnnotationBo>{    @Override    public List<TestAnnotationBo> getDataList() {       List<TestAnnotationBo> res = new ArrayList<TestAnnotationBo>();       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;    }}



重构完毕。

4 0
原创粉丝点击