-
Android Support v4:為兼顧1.6及以上的包
ViewPager官硝、FragmentActivity
-
Android Support v7:為兼顧2.1及以上的包吐根,v7依賴v4包
ActionBarActivity璧微、ViewDragHelper咪鲜、DrawerLayout
Android Support v13:為兼顧2.1及以上的包,一般是為了平板開發(fā)
TextView
-
<selector/>
正常顏色要放在最后面 - 通過drawable減少層級
Bitmap&Factory
在Android 2.3.3(API Level 10)以及之前扛门,Bitmap的backing pixel 數(shù)據(jù)存儲在native memory, 與Bitmap本身是分開的烦衣,Bitmap本身存儲在dalvik heap 中。導致其pixel數(shù)據(jù)不能判斷是否還需要使用勤众,不能及時釋放舆绎,容易引起OOM錯誤。 從Android 3.0(API 11)開始们颜,pixel數(shù)據(jù)與Bitmap一起存儲在Dalvik heap中吕朵。
-
圖片寬高
BitmapFactory.decode(BitmapFactory.Option) // 使用參數(shù)解析圖片以減少內(nèi)存占用 BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; // 第一次解析,只為獲取options.outWidth/outHeight的值 bitmap = BitmapFactory.decodeFile(path, options); // 通過解析的寬窥突、高計算合適的取樣大小 if (sampleSize <= 0){sampleSize = 2;} // 解析時壓縮(2的次方更快):1400*1400變?yōu)?00*700 options.inPreferredConfig=Bitmap.Config.ARGB_4444; options.inJustDecodeBounds=false; // 第二次解析努溃,獲取真正的bitmap bitmap = BitmapFactory.decodeFile(path, options);
-
根據(jù)分辨率適配后的顯示寬高(可以在onCreate的時候就獲取到)
BitmapDrawable drawable = (BitmapDrawable) res.getDrawable(R.drawable.xx); int arrowHeight = drawable.getIntrinsicHeight(); int arrowWidth = drawable.getIntrinsicWidth();
-
Bitmap內(nèi)存大小 =
寬度px
*高度px
*位深度所占大小
Bitmap.Config.ARGB_8888:每個A、R阻问、G梧税、B通道分別占4byte(8位256種顏色) 如700 * 700的圖片占用(700*700*4)/1024/1024=1.87M
-
獲取View快照
view.destroyDrawingCache(); view.setDrawingCacheEnabled(true); Bitmap bitmap = Bitmap.createBitmap(view.getDrawingCache()); view.setDrawingCacheEnabled(false);
ImageView
-
ImageView
的設(shè)置內(nèi)容方法最終會生成一個mBitmapDrawable
對象,其內(nèi)部持有真正的Bitmap
對象称近;注意mUri/mResource將在主線程解析bitmap第队,因此可能會引起阻塞setImageURI() setImageResource() setImageBitmap() setImageDrawable()
-
回收
protected void recycleImageView(ImageView imageView) { if (imageView != null) { Drawable drawable = imageView.getDrawable(); imageView.setImageDrawable(null); // 先切斷關(guān)聯(lián) if (drawable != null) { // 獲取圖片 Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap(); if (bitmap != null && !bitmap.isRecycled()) { bitmap.recycle(); } } } }
-
Bitmap
加載出來的大小(包括內(nèi)存占用大信俑选)和ImageView
顯示的大小沒有必然關(guān)系:顯示的小未必占用內(nèi)存械是;且這兩個不同大小的矩形矩形重疊在一起顯示衡未,需要不同的縮放策略private void initImageView() { mMatrix = new Matrix(); mScaleType = ScaleType.FIT_CENTER; } ScaleType.MATRIX, // Matrix ScaleType.FIT_XY, // Matrix.ScaleToFit.FILL ScaleType.FIT_START, // Matrix.ScaleToFit.START ScaleType.FIT_CENTER, // Matrix.ScaleToFit.CENTER ScaleType.FIT_END, // Matrix.ScaleToFit.END ScaleType.CENTER, // 底圖bitmap不進行縮放尸执,按原圖居中顯示,只是在draw bitmap之前將畫布移動到左上角缓醋,對齊圓點而已 ScaleType.CENTER_CROP, // 把bitmap縮放后平移至居中剔交;依照view的大邊縮放(縮放比例較小) ScaleType.CENTER_INSIDE
ListView
AdapterView
中的addView()
改衩、removeAllView()
都是不能使用的(拋異常)來保證所有的視圖操作都是通過adapter來操作的-
設(shè)置底色為透明岖常,優(yōu)化性能
android:background="@android:color/transparent" android:cacheColorHint="@android:color/transparent" android:listSelector="@android:color/transparent"
setEmptyView()
; 需要empty view在當前布局中,可以結(jié)合ViewStub
item
高度最好使用確定值葫督,因為ListView需要根據(jù)累計高度和總高度比較判斷是否再調(diào)用getView()
android:duplicateParentState="true"
父控件響應點擊事件竭鞍,子View不響應點擊事件,但是顏色要隨著點擊而發(fā)生變化多類別重寫
getItemTypeCount()
; 決定了getView()
緩存幾個converView-
listview是循環(huán)滑動的,所以沒有所謂的
scrollY
掰茶,但可以通過監(jiān)聽計算得到mListView.setOnScrollListener(new OnScrollListener(){});
-
pointToPosition(downX,downY)
根據(jù)傳入的XY判斷點擊的是哪個條目int clickPosition = pointToPosition(downX, downY); // 獲取我們點擊的item view View itemView = getChildAt(clickPosition - getFirstVisiblePosition());
復用
getView()
參數(shù)中的convertView株茶;使用ViewHolder
減少findViewById次數(shù)-
addHeadView
-
addHeaderView(headView, null, false)
,false用來設(shè)置header是否可以被選擇晒夹;可以多次調(diào)用,添加的View按照調(diào)用的順序 - API19之前
addHeaderView()
必須放在listview.setadapter()
前面調(diào)用,API19之后可以隨處調(diào)用丐怯。實質(zhì)是對Adapter包裝為HeaderViewListAdapter
- HeadView的點擊事件在onItemClick中處理[?]
-
ViewPager
startUpdate()
destroyItem() // 先刪除一個廢棄的
instantiateItem() // 創(chuàng)建一個即將使用的
setPrimaryItem() // 多次調(diào)用喷好,可以用來保存當前對象
finishUpdate() // 多次調(diào)用
saveState()
restoreState()
- ViewPager在切換的時候回重新定位焦點,導致重新布局[?]
Fragment
-
FragmentActivity
防止重復創(chuàng)建protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); MyFragment myFragment; if (savedInstanceState == null) { myFragment = MyFragment.newInstance(); // add fragment } // 或者 MyFragment myFragment = getSupportFragmentManager().findFragmentById(R.id.contentFrame); if (myFragment == null) { myFragment = MyFragment.newInstance(); // add fragment } }
-
Fragment
聲明周期public class MyFragment extends BaseFragment { private Persenter mPersenter; private Listener mListener; public MyFragment() { setRetainInstance(true); } public static MyFragment newInstance() { return new MyFragment(); } public void onAttach(Activity activity) { super.onAttach(activity); if (activity instanceof Listener) { mListener = (Listener) activity; } } public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.xxx, container, false); initView(); // ButterKnife.inject(this, view); return rootView; } public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); if (savedInstanceState == null) { this.loadUserDetails(); } } public void onDestroyView() { super.onDestroyView(); listview.setAdapter(null); ButterKnife.reset(this); } public void onDestroy() { super.onDestroy(); this.mPresenter.destroy(); // view = null; unsubscribe(); } public void onDetach() { super.onDetach(); mPersenter = null; } }
android:configChanges="orientation|screenSize"
- 如果不配置
Activity
和Fragment
將重新創(chuàng)建读跷,setRetainInstance(true)可使Fragment不走onDestory方法 - 如果配置了
Activity
和Fragment
都不會重建