編輯:關於Android編程
上篇文章對listView 分組和字母索引導航進行了重構,重構之後,使新的實現只依賴於接口,而不是具體的Bo.但是還是要求原始的數據Bo實現接口或者繼承抽象類。能不能把這一步也簡化呢,只需要原始的數據Bolist? 答案是可以的,可以使用注解,也就是annnotion。
Java注解又叫java標注,java提供了一套機制,使得我們可以對方法、類、參數、包、域以及變量等添加標准(即附上某些信息)。且在以後某個時段通過反射將標注的信息提取出來以供使用。
分組listView 在上次重構後,最需要的信息就是“使用哪個字段進行分組導航”,故我們只要使用注解把這個信息標志出來即可。
另外還需要保存一些拼音等的緩存,那麼可以把原始的Bo包裝一下,利用泛型。下面一步步的來。
注解只要標記按照bo的哪個字段分組排序即可,且注解信息保留在運行時:
@Target(ElementType.TYPE) @Documented @Retention(RetentionPolicy.RUNTIME) public @interface RulerSortStr { String sortField(); }
對Bo利用泛型對Bo進行包裝,包裝類實現之前的接口BoSort或者繼承抽象類DefaultBoSortImp,實現方法getSortStr時利用Bo的注解信息。
public class RulerListDataWrapperextends 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 ""; } } }
此工具類也重構為泛型,此類把原始數據bo列表List
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; }
也都進行泛型化。
首先是adaptor,其所需要的數據是List
public class RulerAdapterextends 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; }
Activity也泛型化,主要是對RulerUtil的調用和 獲取數據時泛型化,其基本代碼如下:
public abstract class RulerActivityextends 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 extends BoSort> */ 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使用注解即可:
如下:
使用注解,@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; } }
只需要繼承以上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; } }
重構完畢。
首篇作為開始,先講講簡單的反編譯。反編譯通常有幾種目的:互相學習、借來用用、嘿嘿(干你,又分為小干干類似微信紅包,和大干干改別人的apk幫他上架)。因為沒帶kvm回來,m
安裝cygwin:由於NDK編譯代碼時必須要用到make和gcc,所以你必須先搭建一個linux環境, cygwin是一個在windows平台上運行的unix模擬環境,它
Android 的 Handler 機制(也有人叫消息機制)目的是為了跨線程通信,也就是多線程通信。之所以需要跨線程通信是因為在 Android 中主線程通常只負責 UI
效果 android 4.4之後,系統是支持自定義狀態欄和導航欄的,舉個最典型的例子就是bilibili客戶端了(iOS版本和android版本能用兩套完全不一樣符合各