国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統(tǒng) > Android > 正文

淺析Android代碼質(zhì)量管理

2019-10-22 18:10:51
字體:
供稿:網(wǎng)友

模板方法-基類封裝

Activity和Fragment應(yīng)該是Android最常用的組件,對他進(jìn)行簡單的封裝對提高代碼的簡潔性也有很大的幫助。

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;	}		/**	 * 始化參數(shù)	 */	public abstract void init();	/**	 * 查找所有的控件	 */	public abstract void findViews();	/**	 * 初始化頁面數(shù)據(jù)	 */	public abstract void initData();	/**	 * 設(shè)置控件的監(jiān)聽事件	 */	public abstract void setListener();		/**	 * 后續(xù)參數(shù)設(shè)置	 */	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();}

代碼比較簡單,用到了模板設(shè)計模式,一個方法只做一樣事情,初始化的就只做初始化操作,設(shè)置監(jiān)聽的就只設(shè)置監(jiān)聽。不管多少個Activity/Fragment都能很好的統(tǒng)一化編碼風(fēng)格,看起來更清晰不亂。

Fragment簡單管理

下面先看看標(biāo)準(zhǔn)的創(chuàng)建和管理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();  } } 

每次創(chuàng)建一個Fragment都要復(fù)制一邊這個方法,代碼冗余、不利于維護和更新。

下面封裝一下

public class FragmentFactory {   private FragmentActivity mContext;  private static FragmentFactory factory = new FragmentFactory();  //用于存儲已創(chuàng)建的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);  } } 

調(diào)用代碼:

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

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

簡單通用的適配器

ListView是Android最常用的一個組件,優(yōu)化Litsview那就是必不可少的工作了。

用Listview最痛苦的就是寫B(tài)aseAdapter的getView()方法,一遍又一遍的寫,大部分代碼都是重復(fù)冗余,但又不得不寫。下面來抽取冗余的代碼封裝起來。

public abstract class CommonAdapter<T> extends BaseAdapter {  //需要顯示的數(shù)據(jù),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中的控件設(shè)置數(shù)據(jù)  * @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構(gòu)造函數(shù),只有當(dāng)convertView為空的時候才創(chuàng)建  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的子類對象,因為不確定用戶布局有什么組件,相當(dāng)于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;  } } 

調(diào)用代碼:

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("標(biāo)題1", "內(nèi)容1", "時間1", "18300000000");  Bean bean2=new Bean("標(biāo)題2", "內(nèi)容2", "時間2", "18300000000");  data.add(bean);  data.add(bean2);  listView.setAdapter(new MyAdapter(context, data, R.layout.listview_item)); 

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

自定義組合控,布局模塊化

正常的項目開發(fā)中肯定有很多布局冗余例如下面圖紅框中的設(shè)置和導(dǎo)航。

Android,代碼質(zhì)量管理

很多人會把這些布局文件一遍又一遍的復(fù)制,只修改其中的ID、字符串等,其他部分幾乎一模一樣,造成布局文件代碼特別多。

最要命的不是這個,而且把所有的邏輯寫在Activity/Fragment里,造成Activity/Fragment特別的龐大,真正實現(xiàn)一坨X代碼。

我覺得應(yīng)該把公用的布局單獨抽取出來到一個xml里,再用一個GroupView去處理這些邏輯和業(yè)務(wù),減少activity/Fragment的負(fù)擔(dān)。

代碼就不貼了,自己去源碼demo里查看ParamSwitchView,這個View是圖1的一個Item,封裝了布局和所需要的遙控按鍵左右切換數(shù)據(jù)的邏輯。

面向接口編程

面向接口編程的意思是指在面向?qū)ο蟮南到y(tǒng)中所有的類或者模塊之間的交互是由接口完成的。

父類的引用指向子類對象,指向不同的子類對象,產(chǎn)生不同的行為:

父 a =new 子A;

有很多童靴在項目開發(fā)中經(jīng)常更變業(yè)務(wù),例如:定制化系統(tǒng)應(yīng)用,底層的接口在不同型號的TV/手機上都有可能不一樣。
這時候把這些底層接口單獨封裝在一個類進(jìn)行管理,在平臺發(fā)生改變的時候只需要改變實現(xiàn)。

定義接口類統(tǒng)一化管理方法

public interface IManager {   void setBackLight(int value);  void setPictureMode(int mode);  } 

實現(xiàn)類 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);  }  } 

假如現(xiàn)在業(yè)務(wù)需求是華為的定制系統(tǒng),只需要調(diào)用華為的子類

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

如果業(yè)務(wù)需求轉(zhuǎn)變成小米,那么只需要創(chuàng)建一個類進(jìn)行實現(xiàn)

實現(xiàn)類 2

public class XiaoMiManager implements IManager {   @Override  public void setBackLight(int value) {  XiaoMi.savaBackLight(value);  }   @Override  public void setPictureMode(int mode) {  XiaoMi.setPictureMode(mode);  }  } 

調(diào)用代碼里只需要把HuaWeiManager改成XiaoMiManager就能適配其他機型了。

//IManager iManager=new HuaWeiManager(); IManager iManager=new XiaoMiManager(); iManager.setBackLight(100); 

在這里只是灌輸一個編碼思維,實際開發(fā)中突發(fā)情況比較多,并不一定全部適用。

在編碼之前一定要花一點點時間簡單構(gòu)思和組織一下代碼,不要想到什么寫什么。

注重工具類的封裝

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

例如:Toast 、SharePreference、獲取時間、系統(tǒng)版本、網(wǎng)絡(luò)、MD5等等。。。。

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

壞習(xí)慣

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

1. 網(wǎng)絡(luò)、Toast、狀態(tài)、時間等等全部都用一個類去管理,這樣造成的后果就是后期不方便維護和不利于更新,代碼看起來雜亂無章。

2. 把一些公共的方法直接在邏輯層構(gòu)建,其他地方需要就直接復(fù)制一份過去。

或者有其他相同的比較類似的方法沒有進(jìn)行封裝,在其他地方直接復(fù)制過去只修改其他一行的代碼。

好習(xí)慣

1. 把這些tools單獨創(chuàng)建各種各樣的tools去存放這些方法,Toast只存Toast相關(guān)的,網(wǎng)絡(luò)只存網(wǎng)絡(luò)相關(guān)的,避免交雜在一起。也符合設(shè)計原則之一的:單一原則。

2. 類似的方法獨立抽取出來,用傳參flag標(biāo)記去區(qū)分應(yīng)用場景。

源碼里收藏了一些常用的工具類分享給大家。

MVP分層架構(gòu)

改善代碼的方式很多很多,一下子想不完,后面想到了什么再繼續(xù)更新分享。


注:相關(guān)教程知識閱讀請移步到Android開發(fā)頻道。
發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 郓城县| 浙江省| 根河市| 桂林市| 玉溪市| 焉耆| 扎鲁特旗| 尼勒克县| 靖江市| 娱乐| 尉犁县| 汉阴县| 新绛县| 岫岩| 屯门区| 通许县| 柳林县| 台南县| 宾阳县| 建水县| 阿坝县| 建阳市| 会东县| 如皋市| 潮州市| 嘉黎县| 伊金霍洛旗| 岐山县| 板桥市| 论坛| 沅陵县| 巴里| 通渭县| 呼图壁县| 洛宁县| 华亭县| 通榆县| 永善县| 财经| 祁门县| 山东省|