您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關Android代碼質量管理的示例分析,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。
模板方法-基類封裝
Activity和Fragment應該是Android最常用的組件,對他進行簡單的封裝對提高代碼的簡潔性也有很大的幫助。
BaseActivity :
public abstract class BaseActivity extends FragmentActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); init(); findViews(); initData(); setListener(); setting(); } /** * 獲得上下文 * @return Context */ public Context getContext(){ return this; } /** * 始化參數 */ public abstract void init(); /** * 查找所有的控件 */ public abstract void findViews(); /** * 初始化頁面數據 */ public abstract void initData(); /** * 設置控件的監聽事件 */ public abstract void setListener(); /** * 后續參數設置 */ public abstract void setting(); }
BaseFragment :
public abstract class BaseFragment extends Fragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override public void onStart() { super.onStart(); init(); findViews(); initData(); setListener(); setting(); } public Context getContext() { return getActivity(); } public abstract void init(); public abstract void findViews(); public abstract void initData(); public abstract void setListener(); public abstract void setting(); }
代碼比較簡單,用到了模板設計模式,一個方法只做一樣事情,初始化的就只做初始化操作,設置監聽的就只設置監聽。不管多少個Activity\Fragment都能很好的統一化編碼風格,看起來更清晰不亂。
Fragment簡單管理
下面先看看標準的創建和管理Fragment
private void showFragment(){ FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); hideFragment(fragmentTransaction); if (mFragment1== null) { mFragment1 = new MyFragment1(context); fragmentTransaction.add(R.id.content, mFragment1); fragmentTransaction.commit(); } else { fragmentTransaction.show(mFragment1); fragmentTransaction.commit(); } }
每次創建一個Fragment都要復制一邊這個方法,代碼冗余、不利于維護和更新。
下面封裝一下
public class FragmentFactory { private FragmentActivity mContext; private static FragmentFactory factory = new FragmentFactory(); //用于存儲已創建的Fragment對象 private Map<String, Fragment> mFragmentMap=new HashMap<>(); private int mLayoutId; private FragmentFactory() { } public static FragmentFactory getInstance() { return factory; } //layoutId 傳入布局文件的id public FragmentFactory init(FragmentActivity context,int layoutId) { this.mContext = context; this.mLayoutId=layoutId; return factory; } public Activity getParentActivity() { return mContext; } private <T extends Fragment> Fragment createFragment(Class<T> clazz) { Fragment fragment = null; try { fragment = getFragment(clazz.getName()); FragmentTransaction fragmentTransaction = mContext.getSupportFragmentManager().beginTransaction(); hideFragment(fragmentTransaction); if (fragment == null) { fragment = (Fragment) clazz.newInstance(); setFragment(fragment); fragmentTransaction.add(mLayoutId, fragment); fragmentTransaction.commit(); } else { fragmentTransaction.show(fragment); fragmentTransaction.commit(); } } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } return fragment; } private <T extends Fragment> Fragment getFragment(String className) { Fragment fragment = mFragmentMap.get(className); return fragment; } private <T extends Fragment> void setFragment(Fragment fragment) throws InstantiationException, IllegalAccessException { String className = fragment.getClass().getName(); mFragmentMap.put(className, fragment); } private void hideFragment(FragmentTransaction fragmentTransaction) { Set<String> keySet = mFragmentMap.keySet(); for (String key : keySet) { Fragment fragment = mFragmentMap.get(key); fragmentTransaction.hide(fragment); } } public <T extends Fragment> T showFragment(Class<T> clazz) { return (T) createFragment(clazz); } }
調用代碼:
FragmentFactory mFragmentFactory = FragmentFactory.getInstance().init(this, R.id.fl_content); mFragmentFactory.showFragment(MyFragment1.class); mFragmentFactory.showFragment(MyFragment2.class);
上面的封裝用到了泛型、工廠、單例等知識。只需要在Activity初始化一次對象就可以一行代碼管理Fragment了,想顯示哪個頁面就傳入對應的Fragment的class。
簡單通用的適配器
ListView是Android最常用的一個組件,優化Litsview那就是必不可少的工作了。
用Listview最痛苦的就是寫BaseAdapter的getView()方法,一遍又一遍的寫,大部分代碼都是重復冗余,但又不得不寫。下面來抽取冗余的代碼封裝起來。
public abstract class CommonAdapter<T> extends BaseAdapter { //需要顯示的數據,List中的類型為泛型,因為不知道用戶的封裝Bean private List<T> mDatas; private Context mContext; //布局文件Id private int mLayoutId; public CommonAdapter(Context context,List<T> data,int layoutId) { mDatas = data; mContext = context; mLayoutId = layoutId; } @Override public int getCount() { return mDatas.size(); } @Override public Object getItem(int position) { return mDatas.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = ViewHolder.getHolder(mContext,convertView, parent, mLayoutId); setDatas(holder,getItem(position)); return holder.getConvertView(); } /** * 為各個item中的控件設置數據 * @param holder ViewHolder * @param object 從集合中所取的一個對象 */ public abstract void setDatas(ViewHolder holder, Object object); }
public class ViewHolder { private View mConvertView; //用來存布局中的各個組件,以鍵值對形式 private HashMap<Integer,View> mViews = new HashMap<>(); //ViewHolder構造函數,只有當convertView為空的時候才創建 public ViewHolder(Context context,View convertView, ViewGroup parent, int layouId) { convertView = LayoutInflater.from(context).inflate(layouId,parent,false); convertView.setTag(this); //將其setTag() mConvertView = convertView; } //返回一個ViewHolder對象 public static ViewHolder getHolder(Context context, View convertView, ViewGroup parent, int layoutId) { if (convertView == null) { return new ViewHolder(context,convertView,parent,layoutId); }else { return (ViewHolder) convertView.getTag(); } } //返回一個View的子類對象,因為不確定用戶布局有什么組件,相當于findViewById //這里返回一個泛型,也可以返回一個View或Object public <T extends View>T getView(int resId) { View view = mViews.get(resId); //從集合中取出這個組件 if (view == null) { //如果為空,說明為第一屏 view = mConvertView.findViewById(resId); //從convertView中找 mViews.put(resId,view); } return (T) view; } public View getConvertView() { return mConvertView; } }
調用代碼:
public class MyAdapter extends CommonAdapter<Bean> { public MyAdapter(Context context, List<Bean> data, int layoutId) { super(context, data, layoutId); } @Override public void setDatas(ViewHolder holder, Object object) { Bean bean = (Bean) object; ((TextView)holder.getView(R.id.title_Tv)).setText(bean.getTitle()); ((TextView)holder.getView(R.id.desc_Tv)).setText(bean.getDesc()); ((TextView)holder.getView(R.id.time_Tv)).setText(bean.getTime()); ((TextView)holder.getView(R.id.phone_Tv)).setText(bean.getPhone()); } }
List<Bean> data=new ArrayList<>(); Bean bean=new Bean("標題1", "內容1", "時間1", "18300000000"); Bean bean2=new Bean("標題2", "內容2", "時間2", "18300000000"); data.add(bean); data.add(bean2); 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\手機上都有可能不一樣。
這時候把這些底層接口單獨封裝在一個類進行管理,在平臺發生改變的時候只需要改變實現。
定義接口類統一化管理方法
public interface IManager { void setBackLight(int value); void setPictureMode(int mode); }
實現類 1
public class HuaWeiManager implements IManager { @Override public void setBackLight(int value) { <strong>HuaWei</strong>.savaBackLight(value); } @Override public void setPictureMode(int mode) { <strong>HuaWei</strong>.setPictureMode(mode); } }
假如現在業務需求是華為的定制系統,只需要調用華為的子類
IManager iManager=new HuaWeiManager(); iManager.setBackLight(100);
如果業務需求轉變成小米,那么只需要創建一個類進行實現
實現類 2
public class XiaoMiManager implements IManager { @Override public void setBackLight(int value) { XiaoMi.savaBackLight(value); } @Override public void setPictureMode(int mode) { XiaoMi.setPictureMode(mode); } }
調用代碼里只需要把HuaWeiManager改成XiaoMiManager就能適配其他機型了。
//IManager iManager=new HuaWeiManager(); IManager iManager=new XiaoMiManager(); iManager.setBackLight(100);
在這里只是灌輸一個編碼思維,實際開發中突發情況比較多,并不一定全部適用。
在編碼之前一定要花一點點時間簡單構思和組織一下代碼,不要想到什么寫什么。
注重工具類的封裝
我們正常的開發中經常用到很多不需要在邏輯層編寫的方法,我們就可以單獨的把他抽取出來放在單獨的類里面去單獨管理。
例如:Toast 、SharePreference、獲取時間、系統版本、網絡、MD5等等。。。。
這些東西都可以單獨的封裝和管理,減少邏輯層的代碼,并且也可以讓其他邏輯層調用。
壞習慣
有些人喜歡把定義個Tools這樣的工具類,里面存放著所有的工具方法。
1. 網絡、Toast、狀態、時間等等全部都用一個類去管理,這樣造成的后果就是后期不方便維護和不利于更新,代碼看起來雜亂無章。
2. 把一些公共的方法直接在邏輯層構建,其他地方需要就直接復制一份過去。
或者有其他相同的比較類似的方法沒有進行封裝,在其他地方直接復制過去只修改其他一行的代碼。
好習慣
1. 把這些tools單獨創建各種各樣的tools去存放這些方法,Toast只存Toast相關的,網絡只存網絡相關的,避免交雜在一起。也符合設計原則之一的:單一原則。
2. 類似的方法獨立抽取出來,用傳參flag標記去區分應用場景。
關于“Android代碼質量管理的示例分析”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。