2020阿里巴巴 Android 開發(fā)手冊(cè)_第1頁
2020阿里巴巴 Android 開發(fā)手冊(cè)_第2頁
2020阿里巴巴 Android 開發(fā)手冊(cè)_第3頁
2020阿里巴巴 Android 開發(fā)手冊(cè)_第4頁
2020阿里巴巴 Android 開發(fā)手冊(cè)_第5頁
已閱讀5頁,還剩62頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

阿里巴巴Android開發(fā)手冊(cè)--目錄前言 2一、Java語言規(guī)范 3二、Android資源文命名與使用 4三、Android基本組件 7四、UI與布局 22五、進(jìn)程、線程與消息通信 30六、文件與數(shù)據(jù)庫 34七、Bitmap、Drawable與動(dòng)畫 44八、安全 54九、其他 65附錄-認(rèn)證考試 66前言前言Android創(chuàng)新的開始?!詫毤夹g(shù)負(fù)責(zé)人莊卓然AndroidAndroidAppAndroidApp《阿里巴巴Android開發(fā)手冊(cè)》作為阿里巴巴開發(fā)規(guī)約重要的一環(huán),我們的目標(biāo)是:防患未然,提升質(zhì)量意識(shí),降低故障率和維護(hù)成本;標(biāo)準(zhǔn)統(tǒng)一,提升協(xié)作效率;追求卓越的工匠精神,打磨精品代碼。本手冊(cè)以開發(fā)者為中心視角分為Jaa(JavaAndroidDrawable【強(qiáng)制】必須遵守,違反本約定或?qū)?huì)引起嚴(yán)重的后果;【推薦】盡量遵守,長(zhǎng)期遵守有助于系統(tǒng)穩(wěn)定性和合作效率的提升;向。什么樣的編碼和實(shí)現(xiàn)方式;“反例”說明需要提防的雷區(qū),以及錯(cuò)誤案例。另外,「阿里巴巴Android開發(fā)規(guī)范」認(rèn)證考試同步上線,詳情請(qǐng)?jiān)L問:/certification/cldt04Android(淘寶技術(shù)部、(智能場(chǎng)景事業(yè)部(淘寶技術(shù)部(淘寶技術(shù)部(術(shù)部(感謝,感謝孤盡(Java開發(fā)手冊(cè)》主要作者)對(duì)手冊(cè)的指導(dǎo)。阿里巴巴Android開發(fā)手冊(cè)一、Java開發(fā)手冊(cè)》二、Android資源文件命名與使用二、Android資源文件命名與使用【推薦】layoutActivityActivity的layout以module_activity開頭Fragment的layout以module_fragmentDialog的layout以module_dialog開頭include的layout以module_include開頭ListViewlayout以module_list_item開頭RecyclerView的itemlayout以module_recycle_item開頭GridViewlayout以module_grid_item開頭【推薦】drawable資源名稱以小寫單詞+drawable目錄下,建議只使用一套,drawable-xhdpi。采用規(guī)則如下:模塊_務(wù)能述件描_件態(tài)定詞 如:module_login_btn_pressed,module_tabs_icon_home_normal【推薦】anim+下劃線的方式命名,采用以下規(guī)則:_輯稱_[向號(hào)] tween動(dòng)畫資源:盡可能以通用的動(dòng)畫名稱命名,如module_fade_in,module_fade_out,module_push_down_in(動(dòng)畫+方向);frame動(dòng)畫資源:盡可能以模塊+功能命名+序號(hào)。如:module_loading_grey_001【推薦】color#AARRGGBB格式,寫入module_colors.xml文件中,命名格式采用以下規(guī)則:輯稱_顏色 如:阿里巴巴Android開發(fā)手冊(cè)dimen+module_dimens.xml文件中,采用以下規(guī)則:模塊_述息 如:style+module_styles.xml文件中,采用以下規(guī)則:父style稱.前style稱 如:<stylename="ParentTheme.ThisActivityTheme"><stylename="ParentTheme.ThisActivityTheme">…</style>string資源文件或者文本用到字符需要全部寫入module_strings.xml文件中,字符串以小寫單詞+下劃線的方式命名,采用以下規(guī)則:模塊_輯稱 如:moudule_login_tips,module_homepage_notice_desc【推薦】IdViewidView的縮寫作為前綴。常用縮寫表如下:控件縮寫LinearLayoutllRelativeLayoutrlConstraintLayoutclListViewlvScollViewsvTextViewtvButtonbtnImageViewivCheckBoxcbRadioButtonrbEditTextet二、Android資源文件命名與使用其它控件的縮寫推薦使用小寫字母并用下劃線進(jìn)行分割,例如:ProgressBar對(duì)應(yīng)的縮寫為progress_barDatePicker對(duì)應(yīng)的縮寫為date_picker(xxhdpi目錄下管理,否則將導(dǎo)致占用內(nèi)存成倍數(shù)增加。說明:Android(在下面詳述)包括低中、高xxhdpi(超超高)和xxxhdpi(超超超高。例如,高密度屏幕的位圖應(yīng)使用drawable-hdpi/。源浪費(fèi),沒有必要在低端機(jī)使用大圖。正例:144*144PNGdrawable-xxhdpi目錄反例:將144*144的應(yīng)用圖標(biāo)PNG文件放在drawable-mhdpi目錄擴(kuò)展參考:/guide/practices/screens_support.html?hl=zh-cn三、Android基本組件

阿里巴巴Android開發(fā)手冊(cè)Android基本組件指Activity、Fragment、Service、BroadcastReceiver、ContentProvider等等。ActivityIntentParcelableEventBusTransactionTooLargeException。Activity#onSaveInstanceState()ActivityActivityUI狀態(tài)的,只能用于保存臨UIActivity#onPause()/onStop()中實(shí)行。Activity間通過隱式IntentIntentresolveActivity檢查,避免找不到合適的調(diào)用組件,造成ActivityNotFoundException的異常。正例:publicvoidviewUrl(Stringurl,StringmimeType){Intentintent=newIntent(Intent.ACTION_VIEW);intent.setDataAndType(Uri.parse(url),mimeType);publicvoidviewUrl(Stringurl,StringmimeType){Intentintent=newIntent(Intent.ACTION_VIEW);intent.setDataAndType(Uri.parse(url),mimeType);if(getPackageManager().resolveActivity(intent,PackageManager.MATCH_DEFAULT_ONLY)!=null){try{startActivity(intent);}catch(ActivityNotFoundExceptione){if(Config.LOGD){Log.d(LOGTAG,"activitynotfoundfor"+mimeType+"over"+Uri.parse(url).getScheme(),e);}}}}三、Android基本組件反例:Intentintent=newIntent();Intentintent=newIntent();intent.setAction("com.great.activity_intent.Intent_Demo1_Result3");Service#onStartCommand()/onBind()IntentService或采用其他異步機(jī)制完成。正例:publicclassMainActivityextendsActivitypublicclassMainActivityextendsActivity{@OverridepublicvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.main);}publicvoidstartIntentService(Viewsource){Intentintent=newIntent(this,MyIntentService.class);startService(intent);}}publicclassMyIntentServiceextendsIntentService{publicMyIntentService(){super("MyIntentService");}阿里巴巴Android開發(fā)手冊(cè)@Override@OverrideprotectedvoidonHandleIntent(Intentintent){synchronized(this){try{}catch(Exceptione){}}}}BroadcastReceiver#onReceive()IntentService完成,而不應(yīng)該在BroadcastReceiver內(nèi)創(chuàng)建子線程去做。說明:由于該方法是在主線程執(zhí)行,如果執(zhí)行耗時(shí)操作會(huì)導(dǎo)致UI不流暢??梢允褂肐ntentService、創(chuàng)建HandlerThread或者調(diào)用Context#registerReceiver(BroadcastReceiver,IntentFilter,String,Handler)方法等方式,在其他Wroker線程執(zhí)行onReceive方法。BroadcastReceiver#onReceive()方法耗時(shí)超過10秒鐘,可能會(huì)被系統(tǒng)殺死。正例:IntentFilterfilter=newIntentFilter();filter.addAction(LOGIN_SUCCESS);this.registerReceiver(mBroadcastReceiver,filter);mBroadcastReceiver=newBroadcastReceiver(){IntentFilterfilter=newIntentFilter();filter.addAction(LOGIN_SUCCESS);this.registerReceiver(mBroadcastReceiver,filter);mBroadcastReceiver=newBroadcastReceiver(){@OverridepublicvoidonReceive(Contextcontext,Intentintent){IntentuserHomeIntent=newIntent();userHomeIntent.setClass(this,UseHomeActivity.class);三、Android基本組件this.startActivity(userHomeIntent);this.startActivity(userHomeIntent);}};反例:mBroadcastReceiver=newBroadcastReceiver(){@OverridemBroadcastReceiver=newBroadcastReceiver(){@OverridepublicvoidonReceive(Contextcontext,Intentintent){MyDatabaseHelpermyDB=newMyDatabaseHelper(context);myDB.initData();//havemoredatabaseoperationhere}};擴(kuò)展參考:/reference/android/content/BroadcastReceiver.html#onReceive(android.content.Context,android.content.Intent)【強(qiáng)制】避免使用隱式Intent廣播敏感信息,信息可能被其他注冊(cè)了對(duì)應(yīng)BroadcastReceiver的App接收。說明:Context#sendBroadcast()receiverreceiverIntentContext#sendOrderedBroadcast()方法發(fā)送的有序廣播,優(yōu)先級(jí)較高的惡意receiver或者向廣播結(jié)果塞入惡意數(shù)據(jù)。如果廣播僅限于應(yīng)用內(nèi),則可以使用LocalBroadcastManager#sendBroadcast()實(shí)現(xiàn),避免敏感信息外泄和Intent攔截的風(fēng)險(xiǎn)。正例:Intentintent=newIntent("my-sensitive-event");Intentintent=newIntent("my-sensitive-event");intent.putExtra("event","thisisatestevent");AndroidLocalBroadcastManager.getInstance(this).sendBroadcast(intent); 反例:Intentintent=newIntent();v1.setAction("com.sample.action.server_running");v1.putExtra("local_ip",v0.h);Intentintent=newIntent();v1.setAction("com.sample.action.server_running");v1.putExtra("local_ip",v0.h);v1.putExtra("port",v0.i);v1.putExtra("code",v0.g);v1.putExtra("connected",v0.s);v1.putExtra("pwd_predefined",v0.r);if(!TextUtils.isEmpty(v0.t)){v1.putExtra("connected_usr",v0.t);}context.sendBroadcast(v1);以上廣播可能被其他應(yīng)用的如下receiver接收導(dǎo)致敏感信息泄漏finalclassMyReceiverextendsBroadcastReceiver{finalclassMyReceiverextendsBroadcastReceiver{publicfinalvoidonReceive(Contextcontext,Intentintent){if(intent!=null&&intent.getAction()!=null){Strings=intent.getAction();if(s.equals("com.sample.action.server_running"){Stringip=intent.getStringExtra("local_ip");Stringpwd=intent.getStringExtra("code");Stringport=intent.getIntExtra("port",8888);booleanstatus=intent.getBooleanExtra("connected",false);}}}}三、Android基本組件擴(kuò)展參考:cast+sensitive+information+using+an+implicit+intent/data/definitions/927.html 【推薦】添加Fragment時(shí),確保FragmentTransaction#commit()在Activity#onPostResume()或者FragmentActivity#onResumeFragments()內(nèi)調(diào)用。不要隨意使用FragmentTransaction#commitAllowingStateLoss()來代替,任何commitAllowingStateLoss()codereview,確保無負(fù)面影響。說明:Activity可能因?yàn)楦鞣N原因被銷毀,Android支持頁面被銷毀前通過Activity#onSaveInstanceState()保存自己的狀態(tài)。但如果FragmentTmit()發(fā)生在ActivityActivity重建、恢復(fù)狀態(tài)時(shí)無法還原頁面狀態(tài),從而可能出錯(cuò)。為了避免給用戶造成不好的體驗(yàn),系統(tǒng)會(huì)拋出IllegalStateExceptionStateLoss異常。推薦的做法是在Activity的onPostResume()或onResumeFragments()(對(duì)FragmentActivity)onCreate()或者直接使用try-catch避免crashActivity重建、恢復(fù)狀態(tài)時(shí),commit正例:publicclassMainActivityextendsFragmentActivity{FragmentManagerfragmentManager;@OverridepublicclassMainActivityextendsFragmentActivity{FragmentManagerfragmentManager;@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main2);fragmentManager=getSupportFragmentManager();FragmentTransactionft=fragmentManager.beginTransaction();MyFragmentfragment=newMyFragment();ft.replace(R.id.fragment_container,fragment);阿里巴巴Android開發(fā)手冊(cè)mit();mit();}}反例:publicclassMainActivityextendsFragmentActivity{FragmentManagerfragmentManager;publicclassMainActivityextendsFragmentActivity{FragmentManagerfragmentManager;@OverridepublicvoidonSaveInstanceState(BundleoutState,PersistableBundleoutPersistentState){super.onSaveInstanceState(outState,outPersistentState);fragmentManager=getSupportFragmentManager();FragmentTransactionft=fragmentManager.beginTransaction();MyFragmentfragment=newMyFragment();ft.replace(R.id.fragment_container,fragment);mit();}}擴(kuò)展參考:t-state-loss.htmlml#commit())【推薦】不要在Activity#onDestroy()內(nèi)執(zhí)行釋放資源的工作,例如一些工作線程的銷毀和停止,因?yàn)閛nDestroy執(zhí)行的時(shí)機(jī)可能較晚。可根據(jù)實(shí)際需要,在Activity#onPause()/onStop()isFinishing()的判斷來執(zhí)行?!就扑]】Fragment。說明:嵌套Fragment是在AndroidAPI17添加到SDK以及Support庫中的功能,F(xiàn)ragment嵌套使用會(huì)有一些坑,容易出現(xiàn)bug,比較常見的問題有如下幾種:三、Android基本組件onActivityResult()FragmentFragment進(jìn)行轉(zhuǎn)發(fā)處理;突變動(dòng)畫效果;被繼承的setRetainInstance(),導(dǎo)致在FragmentFragmentManagerfragmentManager=getFragmentManager();Fragmentfragment=if(null==fragment){FragmentBfragmentB=newFragmentB();FragmentManagerfragmentManager=getFragmentManager();Fragmentfragment=if(null==fragment){FragmentBfragmentB=newFragmentB();FragmentTransactionfragmentTransaction=fragmentManager.beginTransaction();fragmentTransaction.add(R.id.fragment_container,fragmentB,FragmentB.TAG).commit();}反例:FragmentvideoFragment=newVideoPlayerFragment();FragmentvideoFragment=newVideoPlayerFragment();FragmentTransactiontransaction=currentFragment.getChildFragmentManager().beginTransaction();transaction.add(R.id.video_fragment,videoFragment).commit();

擴(kuò)展參考:library-v23.2/en/megatronkings/article/details/51417510IntntSereIntntFite,ServiceIntentFilterIntentIntent#setPackage()方法設(shè)置Intent阿里巴巴Android開發(fā)手冊(cè)Service需要以多線程來并發(fā)處理多個(gè)啟動(dòng)請(qǐng)求,建議使用IntentService,可避免各種復(fù)雜的設(shè)置。說明:Service組件一般運(yùn)行主線程,應(yīng)當(dāng)避免耗時(shí)操作,如果有耗時(shí)操作應(yīng)該在Worker線程執(zhí)行??梢允褂肐ntentService正例:publicclassSingleIntentServiceextendsIntentService{publicSingleIntentService(){publicclassSingleIntentServiceextendsIntentService{publicSingleIntentService(){super("single-servicethread");}@OverrideprotectedvoidonHandleIntent(Intentintent){try{}catch(InterruptedExceptione){e.printStackTrace();}}}反例:publicclassHelloServiceextendsService{publicclassHelloServiceextendsService{...@OverridepublicintonStartCommand(Intentintent,intflags,intstartId){Toast.makeText(this,"servicestarting",Toast.LENGTH_SHORT).show();newThread(newRunnable(){@Override三、Android基本組件publicvoidrun(){publicvoidrun(){//操作語句}}).start();...}}擴(kuò)展參考:/training/run-background-service/index.html【推薦】LocalBroadcastManager來進(jìn)行注冊(cè)和發(fā)送,LocalBroadcastManager安全性更好,同時(shí)擁有更高的運(yùn)行效率。說明:Context#sendBroadcast()LocalBroadcastManager來避免廣播泄漏以及廣播被攔截等安全問題,同時(shí)相對(duì)全局廣播本地廣播的更高效。正例:publicclassMainActivityextendsActionBarActivity{privateMyReceiverreceiver;publicclassMainActivityextendsActionBarActivity{privateMyReceiverreceiver;privateIntentFilterfilter;privateContextcontext;privatestaticfinalStringMY_BROADCAST_TAG="com.example.localbroadcast";@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);receiver=newMyReceiver();filter=newIntentFilter();filter.addAction(MY_BROADCAST_TAG);阿里巴巴Android開發(fā)手冊(cè)Buttonbutton=(Button)findViewById(R.id.button);button.setOnClickListener(newView.OnClickListener(){@OverridepublicvoidonClick(Viewview){Intentintent=newIntent();intent.setAction(MY_BROADCAST_TAG);LocalBroadcastManager.getInstance(context).sendBroadcast(intent);}});}@OverrideprotectedvoidonResume(){super.onResume();LocalBroadcastManager.getInstance(context).registerReceiver(receiver,filter);}@OverrideprotectedvoidonPause(){super.onPause();LocalBroadcastManager.getInstance(context).unregisterReceiver(receiver);}classMyReceiverextendsBroadcastReceiver{@OverridepublicvoidonReceive(Contextarg0,Intentarg1){//messagereceived}}}反例:三、Android基本組件所有廣播都使用全局廣播//Inactivity,sendingbroadcast//Inactivity,sendingbroadcastIntentintent=newIntent("com.example.broadcastreceiver.SOME_ACTION");sendBroadcast(intent);

當(dāng)前Activity的onPause方法執(zhí)行結(jié)束后才會(huì)執(zhí)行下一個(gè)Activity的onCreateonPause【強(qiáng)制】AndroidApplicationIntentSharedPreferences反例:classMyApplicationextendsApplication{Stringusername;classMyApplicationextendsApplication{Stringusername;StringgetUsername(){returnusername;}voidsetUsername(Stringusername){this.username=username;}}classSetUsernameActivityextendsActivity{voidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.set_username);MyApplicationapp=(MyApplication)getApplication();app.setUsername("tester1");startActivity(newIntent(this,GetUsernameActivity.class));}}阿里巴巴Android開發(fā)手冊(cè)classGetUsernameActivityextendsActivity{TextViewtv;classGetUsernameActivityextendsActivity{TextViewtv;voidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.get_username);tv=(TextView)findViewById(R.id.username);}voidonResume(){super.onResume();MyApplicationapp=(MyApplication)getApplication();tv.setText("Welcomeback!"+app.getUsername().toUpperCase());}}【推薦】使用時(shí),建議定義一個(gè)全局的時(shí)不能取消上一次消息的情況如果你有連續(xù)彈出的情況,避免?!緩?qiáng)制】使用Adapter的時(shí)候,如果你使用了ViewHolder做緩存,在getView()的方法中無論這項(xiàng)convertView的每個(gè)子控件是否需要設(shè)置屬性(比如某個(gè)設(shè)置的文本可能為null,某個(gè)按鈕的背景色為透明,某控件的顏色為透明等)要為其顯式設(shè)置屬性adapteritem正例:@Override@OverridepublicViewgetView(intposition,ViewconvertView,ViewGroupparent){ViewHoldermyViews;if(convertView==null){myViews=newViewHolder();convertView=mInflater.inflate(R.layout.list_item,null);-20-20-三、Android基本組件myViews.mUsername=(TextView)convertView.findViewById(R.id.username);convertView.setTag(myViews);myViews.mUsername=(TextView)convertView.findViewById(R.id.username);convertView.setTag(myViews);}else{myViews=(ViewHolder)convertView.getTag();}Infop=infoList.get(position);Stringdn=p.getDisplayName;myViews.mUsername.setText(StringUtils.isEmpty(dn)?"":dn);returnconvertView;}staticclassViewHolder{privateTextViewmUsername;}

Actiy或者Fament中動(dòng)態(tài)注冊(cè)BroadtReceerreereceer()unregisterReceiver()要成對(duì)出現(xiàn)。說明:registerReceiver()unregisterReceiver()SystemService負(fù)擔(dān)。部分華為的機(jī)型會(huì)對(duì)receiver進(jìn)行資源管控,單個(gè)應(yīng)用注冊(cè)過多receiver會(huì)觸發(fā)管控模塊拋出異常,應(yīng)用直接崩潰。正例:publicclassMainActivityextendsAppCompatActivity{publicclassMainActivityextendsAppCompatActivity{privatestaticMyReceivermyReceiver=newMyReceiver();...@OverrideprotectedvoidonResume(){super.onResume();--阿里巴巴Android開發(fā)手冊(cè)IntentFilterfilter=newIntentFilter("com.example.myservice");registerReceiver(myReceiver,filter);IntentFilterfilter=newIntentFilter("com.example.myservice");registerReceiver(myReceiver,filter);}@OverrideprotectedvoidonPause(){super.onPause();unregisterReceiver(myReceiver);}...}反例:publicclassMainActivityextendsAppCompatActivity{privatestaticMyReceivermyReceiver;@OverridepublicclassMainActivityextendsAppCompatActivity{privatestaticMyReceivermyReceiver;@OverrideprotectedvoidonResume(){super.onResume();myReceiver=newMyReceiver();IntentFilterfilter=newIntentFilter("com.example.myservice");registerReceiver(myReceiver,filter);}@OverrideprotectedvoidonDestroy(){super.onDestroy();unregisterReceiver(myReceiver);}}Activity的生命周期不對(duì)應(yīng),可能出現(xiàn)多次onResume造成receiver注冊(cè)多個(gè),但最終只注銷一個(gè),其余receiver產(chǎn)生內(nèi)存泄漏。四、UI與布局四、UI與布局【強(qiáng)制】ViewGroup多重嵌套時(shí),不要使用LinearLayout嵌套,RelativeLayout,可以有效降低嵌套數(shù)。說明:Android應(yīng)用頁面上任何一個(gè)View都需要經(jīng)過measure、layoutdraw三個(gè)步驟xmllayoutmeasure,每個(gè)子節(jié)點(diǎn)都需要向自己的父節(jié)點(diǎn)提供自己的尺寸來決定展示的位置,在此過程中可能還會(huì)重新measure(由此可能導(dǎo)致measure的時(shí)間消耗為原來的2-3倍measureView結(jié)構(gòu)會(huì)性能更好。ViewlayoutdrawView16msUI的流暢。要找到那些多余的(增加渲染延遲的ie,可以用AndroidStudoonorHierarachyViewerview。正例:<?xmlversion="1.0"encoding="utf-8"?><?xmlversion="1.0"encoding="utf-8"?><android.support.constraint.ConstraintLayout><RelativeLayout><TextView/>...<ImageView/></RelativeLayout></android.support.constraint.ConstraintLayout>反例:<?xmlversion="1.0"encoding="utf-8"?> 阿里巴巴Android開發(fā)手冊(cè)<LinearLayout><LinearLayout><LinearLayout><RelativeLayout><TextView/>...<ImageView/></RelativeLayout></LinearLayout></LinearLayout>多重嵌套導(dǎo)致measure以及l(fā)ayout等步驟耗時(shí)過多。擴(kuò)展參考:/studio/profile/hierarchy-viewer.html/android/2016/01/11/android-performance-ui81491913994/ch04.html#figure-story_tree【推薦】在Activity中顯示對(duì)話框或彈出浮層時(shí),盡量使用DialogFragment,而非a/AagActiy生命周期管理對(duì)話框/彈出浮層的生命周期。正例:publicvoidshowPromptDialog(Stringtext){DialogFragmentpromptDialog=newDialogFragment()publicvoidshowPromptDialog(Stringtext){DialogFragmentpromptDialog=newDialogFragment(){@OverridepublicViewonCreateView(LayoutInflaterViewGroupBundlesavedInstanceState){Viewview=inflater.inflate(R.layout.fragment_prompt,container);returnview;}};四、UI與布局promptDialog.show(getFragmentManager(),text);promptDialog.show(getFragmentManager(),text);}【推薦】UTF-8【強(qiáng)制】uiview相關(guān)操作?!就扑]】文本大小使用單位dp,view大小使用單位dp。對(duì)于字大小確定的情況下推薦使用wrap_content布局避免出現(xiàn)文字顯示不全的適配問題?!緩?qiáng)制】禁止在設(shè)計(jì)布局時(shí)多次設(shè)置子view和父view中為同樣的背景造成頁面過度繪制,推薦將不需要顯示的布局進(jìn)行及時(shí)隱藏。正例:<?xmlversion="1.0"encoding="utf-8"?><?xmlversion="1.0"encoding="utf-8"?><LinearLayoutxmlns:android="http:///apk/res/android"android:layout_width="fill_parent"android:layout_height="fill_parent"android:orientation="vertical"><TextViewandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:text="@string/hello"/><Buttonandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:text="clickit!"android:id="@+id/btn_mybuttom"/><ImageViewandroid:id="@+id/img"android:layout_width="fill_parent"android:layout_height="wrap_content"阿里巴巴Android開發(fā)手冊(cè)android:visibility="gone"android:src="@drawable/youtube"/>android:visibility="gone"android:src="@drawable/youtube"/><TextViewandroid:text="itisanexample!"android:layout_width="fill_parent"android:layout_height="wrap_content"/></LinearLayout>反例:@Override@OverrideprotectedvoidonDraw(Canvascanvas){super.onDraw(canvas);intwidth=getWidth();intheight=getHeight();mPaint.setColor(Color.GRAY);canvas.drawRect(0,0,width,height,mPaint);mPaint.setColor(Color.CYAN);canvas.drawRect(0,height/4,width,height,mPaint);canvas.drawRect(0,height/3,width,height,mPaint);canvas.drawRect(0,height/2,width,height,mPaint);}【推薦】靈活使用布局,推薦Merge、ViewStub來優(yōu)化布局,盡可能多的減少UI布局層級(jí),推薦使用FrameLayout,LinearLayout、RelativeLayout次之。layout:view大小的高寬,如倒計(jì)時(shí)組件等;四、UI與布局viewlayout方式修改位置,如彈幕組件等;canvasinvalidate(intl,intt,intintb)等方式限定刷新區(qū)域;requestLayoutrequestlayout、onSizeChanged方法,判斷控件的大小沒有改變的情況下,當(dāng)進(jìn)入requestLayoutsuperrequestLayout方法?!就扑]】ActivityPopupWindowDialog?!就扑]】盡量不要使用AnimationDrawable,它在初始化的時(shí)候就將所有圖片加載到內(nèi)存中,特別占內(nèi)存,并且還不能釋放,釋放之后下次進(jìn)入再次加載時(shí)會(huì)報(bào)錯(cuò)。說明:Android的幀動(dòng)畫可以使用AnimationDrawableOOMOOM正例:圖片數(shù)量較少的AnimationDrawable還是可以接受的。<?xmlversion="1.0"encoding="utf-8"?><?xmlversion="1.0"encoding="utf-8"?><animation-listxmlns:android="http:///apk/res/android"android:oneshot="true"><itemandroid:duration="500"android:drawable="@drawable/ic_heart_100"/>android:duration="500"android:drawable="@drawable/ic_heart_75"/><itemandroid:duration="500"android:drawable="@drawable/ic_heart_50"/>android:duration="500"android:drawable="@drawable/ic_heart_25"/><itemandroid:duration="500"android:drawable="@drawable/ic_heart_0"/></animation-list>反例:<animation-listxmlns:android=<animation-listxmlns:android="http:///apk/res/android"android:oneshot="false">阿里巴巴Android開發(fā)手冊(cè)<itemandroid:drawable="@drawable/soundwave_new_1_00040"android:duration="100"/><itemandroid:drawable="@drawable/soundwave_new_1_00041"android:duration="100"/><itemandroid:drawable="@drawable/soundwave_new_1_00042"android:duration="100"/><itemandroid:drawable="@drawable/soundwave_new_1_00043"android:duration="100"/><itemandroid:drawable="@drawable/soundwave_new_1_00044"android:duration="100"/><itemandroid:drawable="@drawable/soundwave_new_1_00045"android:duration="100"/><itemandroid:drawable="@drawable/soundwave_new_1_00046"android:duration="100"/><itemandroid:drawable="@drawable/soundwave_new_1_00047"android:duration="100"/><itemandroid:drawable="@drawable/soundwave_new_1_00048"android:duration="100"/><itemandroid:drawable="@drawable/soundwave_new_1_00049"android:duration="100"/><itemandroid:drawable="@drawable/soundwave_new_1_00050"android:duration="100"/><itemandroid:drawable="@drawable/soundwave_new_1_00051"android:duration="100"/><itemandroid:drawable="@drawable/soundwave_new_1_00052"android:duration="100"/><itemandroid:drawable="@drawable/soundwave_new_1_00053"android:duration="100"/><itemandroid:drawable="@drawable/soundwave_new_1_00054"android:duration="100"/><itemandroid:drawable="@drawable/soundwave_new_1_00055"android:duration="100"/><itemandroid:drawable="@drawable/soundwave_new_1_00056"android:duration="100"/><itemandroid:drawable="@drawable/soundwave_new_1_00057"android:duration="100"/><itemandroid:drawable="@drawable/soundwave_new_1_00058"android:duration="100"/><itemandroid:drawable="@drawable/soundwave_new_1_00059"android:duration="100"/><itemandroid:drawable="@drawable/soundwave_new_1_00060"android:duration="100"/><itemandroid:drawable="@drawable/soundwave_new_1_00061"android:duration="100"/><itemandroid:drawable="@drawable/soundwave_new_1_00062"android:duration="100"/><itemandroid:drawable="@drawable/soundwave_new_1_00063"android:duration="100"/><itemandroid:drawable="@drawable/soundwave_new_1_00064"android:duration="100"/><itemandroid:drawable="@drawable/soundwave_new_1_00065"android:duration="100"/><itemandroid:drawable="@drawable/soundwave_new_1_00066"android:duration="100"/><itemandroid:drawable="@drawable/soundwave_new_1_00067"android:duration="100"/>四、UI與布局<item<itemandroid:drawable="@drawable/soundwave_new_1_00068"android:duration="100"/><itemandroid:drawable="@drawable/soundwave_new_1_00069"android:duration="100"/></animation-list>上述如此多圖片的動(dòng)畫就不建議使用AnimationDrawable了。擴(kuò)展參考:ame-by-frame-animation-in-android3) /a/11900000059876594) nDrawable.html【強(qiáng)制】不能使用ScrollView包裹ListView/GridView/ExpandableListVIew;因?yàn)檫@樣會(huì)把ListView的所有Itemcpu去繪制圖面。說明:ScrollViewListRecyclerViewListViewUI組件自身有ScrollViewUIMaterialDesignNestedScrollView。正例:<?xmlversion="1.0"encoding="utf-8"?><?xmlversion="1.0"encoding="utf-8"?><LinearLayout><android.support.v4.widget.NestedScrollView><LinearLayout><ImageView/>...<android.support.v7.widget.RecyclerView/></LinearLayout></android.support.v4.widget.NestedScrollView>Android</LinearLayout> 反例:<ScrollView><ScrollView><LinearLayout><TextView/>...<ListView/><TextView/></LinearLayout></ScrollView>擴(kuò)展參考:/reference/android/widget/ScrollView.htmlrollView.html五、進(jìn)程、線程與消息通信五、進(jìn)程、線程與消息通信【強(qiáng)制】不要通過Intent在Android(bindertransaction1BOO?!緩?qiáng)制】Application正例:publicclassMyApplicationextendsApplication{@OverridepublicclassMyApplicationextendsApplication{@OverridepublicvoidonCreate(){//在所有進(jìn)程中初始化//僅在主進(jìn)程中初始化if(mainProcess){...}//僅在后臺(tái)進(jìn)程中初始化if(bgProcess){...}}}【強(qiáng)制】ThreadPoolExecutor或者其他形式自定義的線程池說明:使用線程池的好處是減少在創(chuàng)建和銷毀線程上所花的時(shí)間以及系統(tǒng)資源的開銷,解決資源不足的問題。如果不使用線程池,有可能造成系統(tǒng)創(chuàng)建大量同類線程而導(dǎo)致阿里巴巴Android開發(fā)手冊(cè)消耗完內(nèi)存或者“過度切換”的問題。另外創(chuàng)建匿名線程不便于后續(xù)的資源使用分析,對(duì)性能分析等會(huì)造成困擾。正例:intNUMBER_OF_CORES=Runtime.getRuntime().availableProcessors();intKEEP_ALIVE_TIME=1;intNUMBER_OF_CORES=Runtime.getRuntime().availableProcessors();intKEEP_ALIVE_TIME=1;TimeUnitKEEP_ALIVE_TIME_UNIT=TimeUnit.SECONDS;BlockingQueue<Runnable>taskQueue=newLinkedBlockingQueue<Runnable>();ExecutorServiceexecutorService=newThreadPoolExecutor(NUMBER_OF_CORES,NUMBER_OF_CORES*2,KEEP_ALIVE_TIME,KEEP_ALIVE_TIME_UNIT,taskQueue,newBackgroundThreadFactory(),newDefaultRejectedExecutionHandler());//執(zhí)行任務(wù)executorService.execute(newRunnnable(){...});反例:newThread(newRunnable(){@OverridenewThread(newRunnable(){@Overridepublicvoidrun(){//操作語句...}}).start();擴(kuò)展參考:/threadpoolexecutor-in-android-8e9d22330ee3ExecutorsThreadPoolExecutor的方說明:五、進(jìn)程、線程與消息通信Executors返回的線程池對(duì)象的弊端如下:FixedThreadPool 和 SingleThreadPool:允許的請(qǐng)求隊(duì)列長(zhǎng)度為Integer.MAX_VALUE,可能會(huì)堆積大量的請(qǐng)求,從而導(dǎo)致OOM;CachedThreadPool和ScheduledThreadPool:允許的創(chuàng)建線程數(shù)量為OOM。正例:intNUMBER_OF_CORES=Runtime.getRuntime().availableProcessors();intKEEP_ALIVE_TIME=1;intNUMBER_OF_CORES=Runtime.getRuntime().availableProcessors();intKEEP_ALIVE_TIME=1;TimeUnitKEEP_ALIVE_TIME_UNIT=TimeUnit.SECONDS;BlockingQueue<Runnable>taskQueue=newLinkedBlockingQueue<Runnable>();ExecutorServiceexecutorService=newThreadPoolExecutor(NUMBER_OF_CORES,NUMBER_OF_CORES*2,KEEP_ALIVE_TIME,KEEP_ALIVE_TIME_UNIT,taskQueue,newBackgroundThreadFactory(),newDefaultRejectedExecutionHandler());反例:ExecutorServicecachedThreadPool=Executors.newCachedThreadPool(); 擴(kuò)展參考:/2014/06/cached-thread-pool-considered-harmlful.html【強(qiáng)制】子線程中不能更新界面,更新界面必須在主線程中進(jìn)行,網(wǎng)絡(luò)操作不能在主線程中調(diào)用?!緩?qiáng)制】UIViewStubnull。APP影響用戶體驗(yàn)。正例:publicclassMyThreadextendsThread{publicclassMyThreadextendsThread{publicMyThread(){阿里巴巴Android開發(fā)手冊(cè)super.setName("ThreadName");…}super.setName("ThreadName");…}}【推薦】ThreadPoolExecutor設(shè)置線程存活時(shí)間(setKeepAliveTime),確??臻e時(shí)線程能被釋放?!就扑]】禁止在多進(jìn)程之間用SharedPreferences共享數(shù)據(jù),雖然可以(MODE_MULTI_PROCESS),但官方已不推薦。AndroidActivity的功能;首次進(jìn)入新啟動(dòng)進(jìn)程的頁面時(shí)會(huì)有延時(shí)的現(xiàn)象(Actity的主題有關(guān);應(yīng)用內(nèi)多進(jìn)程時(shí),Application有進(jìn)程中初始化;SharedPreferences共享數(shù)據(jù)時(shí)不穩(wěn)定。六、文件與數(shù)據(jù)庫六、文件與數(shù)據(jù)庫【強(qiáng)制】AndroidAPI訪問。說明:Android應(yīng)用提供內(nèi)部和外部存儲(chǔ),分別用于存放應(yīng)用自身數(shù)據(jù)以及應(yīng)用產(chǎn)生的用戶數(shù)據(jù)??梢酝ㄟ^相關(guān)API接口獲取對(duì)應(yīng)的目錄,進(jìn)行文件操作。android.os.Environment#getExternalStorageDirectory()android.os.Environment#getExternalStorageDirectory()android.content.Context#getFilesDir()android.content.Context#getCacheDir正例:publicFilegetDir(StringalName){publicFilegetDir(StringalName){Filefile=newFile(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),alName);if(!file.mkdirs()){Log.e(LOG_TAG,"Directorynotcreated");}returnfile;}反例:publicFilegetDir(StringalName){publicFilegetDir(StringalName){//appFilefile=newFile("/mnt/sdcard/Download/Album",alName);if(!file.mkdirs()){Log.e(LOG_TAG,"Directorynotcreated");}returnfile;Android} 擴(kuò)展參考:/training/data-storage/files.htmlernalStorageDirectory()//讀/寫檢查//讀/寫檢查publicbooleanisExternalStorageWritable(){Stringstate=Environment.getExternalStorageState();if(Environment.MEDIA_MOUNTED.equals(state)){returntrue;}returnfalse;}//只讀檢查publicbooleanisExternalStorageReadable(){Stringstate=Environment.getExternalStorageState();if(Environment.MEDIA_MOUNTED.equals(state)||Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)){returntrue;}returnfalse;}【強(qiáng)制】應(yīng)用間共享文件時(shí),不要通過放寬文件系統(tǒng)權(quán)限的方式去實(shí)現(xiàn),而應(yīng)使用FileProvider。正例:<!--AndroidManifest.xml--> 六、文件與數(shù)據(jù)庫<manifest>...<application>...<providerandroid:name="android.support.v4.content.FileProvider"android:authorities="com.example.fileprovider"android:exported="false"android:grantUriPermissions="true"><meta-dataandroid:name="android.support.FILE_PROVIDER_PATHS"android:resource="@xml/provider_paths"/></provider>...</application></manifest><!--res/xml/provider_paths.xml--><paths><files-pathpath="album/"name="myimages"/></paths>voidgetAlbumImage(StringimagePath){Fileimage=newFile(imagePath);IntentgetAlbumImageIntent=newIntent(MediaStore.ACTION_IMA

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論