天天看點

Android 代碼品質管理(代碼篇)模闆方法-基類封裝Fragment簡單管理簡單通用的擴充卡自定義組合控,布局子產品化面向接口程式設計注重工具類的封裝

Android 代碼品質管理(代碼篇)

模闆方法-基類封裝

Activity和Fragment應該是Android最常用的元件,對他進行簡單的封裝對提高代碼的簡潔性也有很大的幫助。

  • BaseActivity :
[java]

view plain copy

  1. public abstract class BaseActivity extends FragmentActivity {
  2.     @Override
  3.     protected void onCreate(Bundle savedInstanceState) {
  4.         super.onCreate(savedInstanceState);
  5.         init();
  6.         findViews();
  7.         initData();
  8.         setListener();
  9.         setting();
  10.     }
  11.     /**
  12.      * 獲得上下文
  13.      * @return Context
  14.      */
  15.     public Context getContext(){
  16.         return this;
  17.      * 始化參數
  18.     public abstract void init();
  19.      * 查找所有的控件
  20.     public abstract void findViews();
  21.      * 初始化頁面資料
  22.     public abstract void initData();
  23.      * 設定控件的監聽事件
  24.     public abstract void setListener();
  25.      * 後續參數設定
  26.     public abstract void setting();
  27. }
  • BaseFragment :
  1. public abstract class BaseFragment extends Fragment {
  2.     public void onCreate(Bundle savedInstanceState) {
  3.     public void onStart() {
  4.         super.onStart();
  5.     public Context getContext() {
  6.         return getActivity();

代碼比較簡單,用到了模闆設計模式,一個方法隻做一樣事情,初始化的就隻做初始化操作,設定監聽的就隻設定監聽。不管多少個Activity\Fragment都能很好的統一化編碼風格,看起來更清晰不亂。

Fragment簡單管理

下面先看看标準的建立和管理Fragment。

  1. private void showFragment(){
  2.     FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
  3.     hideFragment(fragmentTransaction);
  4.     if (mFragment1== null) {
  5.         mFragment1 = new MyFragment1(context);
  6.         fragmentTransaction.add(R.id.content, mFragment1);
  7.         fragmentTransaction.commit();
  8.     } else {
  9.         fragmentTransaction.show(mFragment1);

每次建立一個Fragment都要複制一邊這個方法,代碼備援、不利于維護和更新。

下面封裝一下

  1. public class FragmentFactory {
  2.     private FragmentActivity mContext;
  3.     private static FragmentFactory factory = new FragmentFactory();
  4.     //用于存儲已建立的Fragment對象
  5.     private Map<String, Fragment> mFragmentMap=new HashMap<>();
  6.     private int mLayoutId;
  7.     private FragmentFactory() {
  8.     public static FragmentFactory getInstance() {
  9.         return factory;
  10.     //layoutId 傳入布局檔案的id
  11.     public FragmentFactory init(FragmentActivity context,int layoutId) {
  12.         this.mContext = context;
  13.         this.mLayoutId=layoutId;
  14.     public Activity getParentActivity() {
  15.         return mContext;
  16.     private <T extends Fragment> Fragment createFragment(Class<T> clazz) {
  17.         Fragment fragment = null;
  18.         try {
  19.             fragment = getFragment(clazz.getName());
  20.             FragmentTransaction fragmentTransaction = mContext.getSupportFragmentManager().beginTransaction();
  21.             hideFragment(fragmentTransaction);
  22.             if (fragment == null) {
  23.                 fragment = (Fragment) clazz.newInstance();
  24.                 setFragment(fragment);
  25.                 fragmentTransaction.add(mLayoutId, fragment);
  26.                 fragmentTransaction.commit();
  27.             } else {
  28.                 fragmentTransaction.show(fragment);
  29.             }
  30.         } catch (InstantiationException e) {
  31.             e.printStackTrace();
  32.         } catch (IllegalAccessException e) {
  33.         }
  34.         return fragment;
  35.     private <T extends Fragment> Fragment getFragment(String className) {
  36.         Fragment fragment = mFragmentMap.get(className);
  37.     private <T extends Fragment> void setFragment(Fragment fragment) throws InstantiationException, IllegalAccessException {
  38.         String className = fragment.getClass().getName();
  39.         mFragmentMap.put(className, fragment);
  40.     private void hideFragment(FragmentTransaction fragmentTransaction) {
  41.         Set<String> keySet = mFragmentMap.keySet();
  42.         for (String key : keySet) {
  43.             Fragment fragment = mFragmentMap.get(key);
  44.             fragmentTransaction.hide(fragment);
  45.     public <T extends Fragment> T showFragment(Class<T> clazz) {
  46.         return (T) createFragment(clazz);

調用代碼:

  1. FragmentFactory mFragmentFactory = FragmentFactory.getInstance().init(this, R.id.fl_content);
  2. mFragmentFactory.showFragment(MyFragment1.class);
  3. mFragmentFactory.showFragment(MyFragment2.class);

上面的封裝用到了泛型、工廠、單例等知識。隻需要在Activity初始化一次對象就可以一行代碼管理Fragment了,想顯示哪個頁面就傳入對應的Fragment的class。

簡單通用的擴充卡

ListView是Android最常用的一個元件,優化Litsview那就是必不可少的工作了。

用Listview最痛苦的就是寫BaseAdapter的getView()方法,一遍又一遍的寫,大部分代碼都是重複備援,但又不得不寫。下面來抽取備援的代碼封裝起來。

[html]
  1. public abstract class CommonAdapter<T> extends BaseAdapter {
  2.     //需要顯示的資料,List中的類型為泛型,因為不知道使用者的封裝Bean
  3.     private List<T> mDatas;
  4.     private Context mContext;
  5.     //布局檔案Id
  6.     public CommonAdapter(Context context,List<T> data,int layoutId) {
  7.         mDatas = data;
  8.         mContext = context;
  9.         mLayoutId = layoutId;
  10.     public int getCount() {
  11.         return mDatas.size();
  12.     public Object getItem(int position) {
  13.         return mDatas.get(position);
  14.     public long getItemId(int position) {
  15.         return position;
  16.     public View getView(int position, View convertView, ViewGroup parent) {
  17.         ViewHolder holder = ViewHolder.getHolder(mContext,convertView, parent, mLayoutId);
  18.         setDatas(holder,getItem(position));
  19.         return holder.getConvertView();
  20.      * 為各個item中的控件設定資料
  21.      * @param holder   ViewHolder
  22.      * @param object  從集合中所取的一個對象
  23.     public abstract void setDatas(ViewHolder holder, Object object);
  1. public class ViewHolder {
  2.     private View mConvertView;
  3.     //用來存布局中的各個元件,以鍵值對形式
  4.     private HashMap<Integer,View> mViews = new HashMap<>();
  5.     //ViewHolder構造函數,隻有當convertView為空的時候才建立
  6.     public ViewHolder(Context context,View convertView, ViewGroup parent, int layouId) {
  7.         convertView = LayoutInflater.from(context).inflate(layouId,parent,false);
  8.         convertView.setTag(this);       //将其setTag()
  9.         mConvertView = convertView;
  10.     //傳回一個ViewHolder對象
  11.     public static ViewHolder getHolder(Context context, View convertView, ViewGroup parent, int layoutId) {
  12.         if (convertView == null) {
  13.             return new ViewHolder(context,convertView,parent,layoutId);
  14.         }else {
  15.             return (ViewHolder) convertView.getTag();
  16.     //傳回一個View的子類對象,因為不确定使用者布局有什麼元件,相當于findViewById
  17.     //這裡傳回一個泛型,也可以傳回一個View或Object
  18.     public <T extends View>T getView(int resId) {
  19.         View view = mViews.get(resId);  //從集合中取出這個元件
  20.         if (view == null) {         //如果為空,說明為第一屏
  21.             view = mConvertView.findViewById(resId);    //從convertView中找
  22.             mViews.put(resId,view);
  23.         return (T) view;
  24.     public View getConvertView() {
  25.         return mConvertView;
  1. public class MyAdapter extends CommonAdapter<Bean> {
  2.     public MyAdapter(Context context, List<Bean> data, int layoutId) {
  3.         super(context, data, layoutId);
  4.     public void setDatas(ViewHolder holder, Object object) {
  5.         Bean bean = (Bean) object;
  6.         ((TextView)holder.getView(R.id.title_Tv)).setText(bean.getTitle());
  7.         ((TextView)holder.getView(R.id.desc_Tv)).setText(bean.getDesc());
  8.         ((TextView)holder.getView(R.id.time_Tv)).setText(bean.getTime());
  9.         ((TextView)holder.getView(R.id.phone_Tv)).setText(bean.getPhone());
  1.     List<Bean> data=new ArrayList<>();
  2.     Bean bean=new Bean("标題1", "内容1", "時間1", "18300000000");
  3.     Bean bean2=new Bean("标題2", "内容2", "時間2", "18300000000");
  4.     data.add(bean);
  5.     data.add(bean2);
  6.     listView.setAdapter(new MyAdapter(context, data, R.layout.listview_item));

注釋寫的很清楚了,就不多說了。

自定義組合控,布局子產品化

正常的項目開發中肯定有很多布局備援例如下面圖紅框中的設定和導航。

很多人會把這些布局檔案一遍又一遍的複制,隻修改其中的ID、字元串等,其他部分幾乎一模一樣,造成布局檔案代碼特别多。

最要命的不是這個,而且把所有的邏輯寫在Activity\Fragment裡,造成Activity\Fragment特别的龐大,真正實作一坨X代碼。

我覺得應該把公用的布局單獨抽取出來到一個xml裡,再用一個GroupView去處理這些邏輯和業務,減少activity\Fragment的負擔。

代碼就不貼了,自己去源碼demo裡檢視ParamSwitchView,這個View是圖1的一個Item,封裝了布局和所需要的遙控按鍵左右切換資料的邏輯。

面向接口程式設計

面向接口程式設計的意思是指在面向對象的系統中所有的類或者子產品之間的互動是由接口完成的。

父類的引用指向子類對象,指向不同的子類對象,産生不同的行為:

父 a =new 子A;

有很多童靴在項目開發中經常更變業務,例如:定制化系統應用,底層的接口在不同型号的TV\手機上都有可能不一樣。

這時候把這些底層接口單獨封裝在一個類進行管理,在平台發生改變的時候隻需要改變實作。

定義接口類統一化管理方法

  1. public interface IManager {
  2.     void setBackLight(int value);
  3.     void setPictureMode(int mode);

實作類 1

  1. public class HuaWeiManager implements IManager {
  2.     public void setBackLight(int value) {
  3.         <strong>HuaWei</strong>.savaBackLight(value);
  4.     public void setPictureMode(int mode) {
  5.         <strong>HuaWei</strong>.setPictureMode(mode);

假如現在業務需求是華為的定制系統,隻需要調用華為的子類

  1. IManager iManager=new HuaWeiManager();
  2. iManager.setBackLight(100);

如果業務需求轉變成小米,那麼隻需要建立一個類進行實作

實作類 2

  1. public class XiaoMiManager implements IManager {
  2.         XiaoMi.savaBackLight(value);
  3.         XiaoMi.setPictureMode(mode);

調用代碼裡隻需要把HuaWeiManager改成XiaoMiManager就能适配其他機型了。

  1. //IManager iManager=new HuaWeiManager();
  2. IManager iManager=new XiaoMiManager();

在這裡隻是灌輸一個編碼思維,實際開發中突發情況比較多,并不一定全部适用。

在編碼之前一定要花一點點時間簡單構思群組織一下代碼,不要想到什麼寫什麼。

注重工具類的封裝

我們正常的開發中經常用到很多不需要在邏輯層編寫的方法,我們就可以單獨的把他抽取出來放在單獨的類裡面去單獨管理。

例如:Toast 、SharePreference、擷取時間、系統版本、網絡、MD5等等。。。。

這些東西都可以單獨的封裝和管理,減少邏輯層的代碼,并且也可以讓其他邏輯層調用。

壞習慣

有些人喜歡把定義個Tools這樣的工具類,裡面存放着所有的工具方法。

1. 網絡、Toast、狀态、時間等等全部都用一個類去管理,這樣造成的後果就是後期不友善維護和不利于更新,代碼看起來雜亂無章。

2. 把一些公共的方法直接在邏輯層建構,其他地方需要就直接複制一份過去。

或者有其他相同的比較類似的方法沒有進行封裝,在其他地方直接複制過去隻修改其他一行的代碼。

好習慣

    1. 把這些tools單獨建立各種各樣的tools去存放這些方法,Toast隻存Toast相關的,網絡隻存網絡相關的,避免交雜在一起。也符合設計原則之一的:單一原則。

2. 類似的方法獨立抽取出來,用傳參flag标記去區分應用場景。

原文位址

http://www.bieryun.com/3622.html

繼續閱讀