首页 > 代码库 > android列表分组及字母导航-重构(2)-注解

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

上篇文章对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 = http://www.mamicode.com/data;>

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



重构完毕。

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