這篇文章先匯總一下部分在平常容易遇到或可能遇到的一些難以理解或者容易忘記是什么的問(wèn)題。
-
android:supportsRtl="true"是什么珊蟀?
android:supportsRtl="true"
故名思義育灸,“Rtl”就是“right to left” 描扯,一般用于適配language文本方向,如切換系統(tǒng)語(yǔ)言為阿拉伯文時(shí)杭煎,actionbar布局要變?yōu)閺挠蚁蜃笈帕邢鄄托枰@個(gè)屬性也切。
注意:
此屬性最低SDK版本為17(Android 4.2.x)
在使用這個(gè)屬性時(shí)雷恃,盡量不適用layout_marginRight
這類倒槐,而是使用layout_marginEnd
這種讨越。
- Android res/menu/my_nemu.xml中不易記的屬性:
- android:alphabeticShortcut="n" :表示快捷鍵為:Ctrl+n 把跨、Alt+n
- android:orderInCategory = "3":表示在菜單列表中的排序着逐,值可以為大于等于0的任何整數(shù)滨嘱,數(shù)值越小太雨,排序越前囊扳。
- android:checkableBehavior = "single|all|none":分別表示radio button锥咸、checkbox搏予、checkable=false
- <group android:id="xx"……> <item android:id="yy"/>……</group>: 用一個(gè)組,包含幾個(gè)menu_item精绎,這樣,組內(nèi)部的item的順序就可以重新定義搁吓。
- Android中用Java代碼設(shè)置菜單項(xiàng)快捷鍵的方法:
menu.setQwertyMode(true);
menu.findItem(TWO_ID).setNumericShortcut('2');
- <RelativeLayout>中子view的屬性:
- android:below="@+id/xx" :表示本view在xx的下面
- android:above="@+id/xx":表示本view在xx的上面
- implements Parcelable的對(duì)象的一般寫(xiě)法:(詳見(jiàn)我的另一篇博文:Android AIDL基礎(chǔ) -- Parcelable接口)
public class Student implements Parcelable{
///-------------------------------
/// (1):基本類型堕仔、String/CharSequence贮预、Bundle仿吞、IBinder唤冈、Serializable你虹、Parcelable 的成員
private T t;
……
///---------------------------------
///(2):構(gòu)造方法(可選傅物,怎么方便賦值成員變量值并構(gòu)建實(shí)例董饰,就怎么寫(xiě))
public Student() {
……
}
//=========================================================
// 下面是Parcelable需要實(shí)現(xiàn)的方法
//=========================================================
protected Student(Parcel in) {
///建議:按成員變量順序?qū)憽疽驗(yàn)椋盒枰cwriteToParcel()方法中的寫(xiě)入順序一致】
id = in.readInt();//如:基本數(shù)據(jù)類型成員
name = in.readString();//如:String類型成員
home = in.readParcelable(Address.class.getClassLoader());//如:Parcelable類型成員
……
}
public static final Creator<Student> CREATOR = new Creator<Student>() {
///CREATOR成員,格式必須如下也祠,‘CREATOR’變量名也固定诈嘿。
@Override
public Student createFromParcel(Parcel in) {
return new Student(in);
}
@Override
public Student[] newArray(int size) {
return new Student[size];
}
};
@Override
public int describeContents() {
/// 描述標(biāo)志永淌,默認(rèn)為0即可
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
////寫(xiě)入Parcel的方法【需要與writeToParcel()方法中的寫(xiě)入順序一致】
dest.writeInt(id);
dest.writeString(name);
dest.writeParcelable(home, flags);
……
}
}
- Android Studio獲取Android簽名證書(shū)SHA1的簡(jiǎn)易步驟:
- Android Studio中打開(kāi)terminal或者配置了全局變量之后直接打開(kāi)終端輸入:
keytool -list -v -keystore 你的簽名文件所在的路徑
- 輸入密鑰庫(kù)密碼
- 成功顯示:MD5、SHA1李滴、SHA256等信息
想知道Eclipse的獲取方式所坯,更詳細(xì)的地址可以看:SHA1查看
-
JSON封裝庫(kù)的效率對(duì)比:
如果對(duì)JSON的解析速度敏感:大文件用:Jackson芹助,小文件用:Gson状土,兩種文件都有用:JSON.simple
- Java代碼執(zhí)行new一個(gè)類實(shí)例對(duì)象的過(guò)程中蒙谓,static塊累驮、static方法谤专、main方法的執(zhí)行順序:
- static塊【最先執(zhí)行,因?yàn)殪o態(tài)代碼塊屬于類層次墅垮,在類編譯時(shí)就執(zhí)行】
- -> main方法
- -> 成員塊
- -> 構(gòu)造方法
- -> static方法【在被調(diào)用時(shí)才執(zhí)行】
詳細(xì)可以看看本人的相關(guān)文章:Java面試相關(guān)(一)-- Java類加載全過(guò)程
- 在寫(xiě)Fragment的時(shí)候算色,F(xiàn)ragment.onCreateView()方法中,一般是這樣的一個(gè)結(jié)構(gòu):
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if (rootLayout == null) {
rootLayout = inflater.inflate(R.layout.fragment_reclist, null);///①
rootLayout = inflater.inflate(R.layout.fragment_reclist, container, false);///②
///rootLayout = inflater.inflate(R.layout.fragment_reclist, container);///③這樣不行C弧灾梦!
……
}
……
return rootLayout;
}
這里峡钓,要注意代碼中注釋掉的地方,這里有一個(gè)對(duì)于Fragment的知識(shí)點(diǎn):
inflater.inflate(id, ViewGroup);
說(shuō)明:
?這個(gè)方法傳入:【目的布局的R.layout 的id】 + 【目的布局的父容器】若河。那么能岩,對(duì)于Fragment的來(lái)說(shuō)萧福,F(xiàn)ragment的onCreateView()方式最終返回的View會(huì)自動(dòng)判斷本Fragment所在的父容器位置拉鹃。
?為什么上面代碼③不行呢? 答:因?yàn)?code>inflater.inflate(id, ViewGroup);最終會(huì)調(diào)用inflater.inflate(id, ViewGroup,boolean);
方法,當(dāng)ViewGroup不為null時(shí)鲫忍,這方法的第三個(gè)參數(shù)值會(huì)為true膏燕,表示的是‘inflate出來(lái)的布局自動(dòng)加到它的父viewgroup中’,那么問(wèn)題就來(lái)了悟民,如果這個(gè)父布局是一個(gè)ViewPager或者其他不易確定子View放置位置的容器坝辫,那么,方法就會(huì)報(bào)錯(cuò)射亏,因?yàn)檎也坏讲迦朦c(diǎn)近忙!所以,對(duì)于Fragment的布局智润,一般情況不需要設(shè)置自動(dòng)添加到父布局及舍,所以,上述代碼①和②二選一都可以做鹰。
-
Fragment 與 它所在的Activity的生命周期方法執(zhí)行次序:
下面用一個(gè)常用布局作為示例【FragmentActivity中用ViewPager裝載兩個(gè)Fragment 部分代碼示例】來(lái)演示 击纬,看運(yùn)行的Log就可以說(shuō)明整個(gè)執(zhí)行順序:
public class CommonTabActivity extends FragmentActivity {
……
/// TabLayout + ViewPager的主界面容器
PagerAdapter mPagerAdapter;
ViewPager mViewPager;
TabLayout mTabLayout;
////兩個(gè) Fragment
RecListFragment homeFragment;
RecListFragment collectionFragment;
……
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_commontab);
initView();
}
private void initView() {
///初始化ViewPager等控件
……
mPagerAdapter = new FragmentPagerAdapter(getSupportFragmentManager()) {
@Override
public Fragment getItem(int position) {
switch (position) {
/////////////////////////使用第一個(gè)Fragment
case 0:
default:
if(homeFragment==null){
homeFragment = new RecListFragment();
}
return homeFragment;
///////////////////////////使用第二個(gè)Fragment
case 1:
if (collectionFragment==null){
collectionFragment = new RecListFragment();
}
return collectionFragment;
}
}
…………
};
mViewPager.setAdapter(mPagerAdapter);
mTabLayout.setupWithViewPager(mViewPager);
}
}
上面的結(jié)構(gòu)大家應(yīng)該都比較熟悉,那么钾麸,我測(cè)試后給大家列出幾種情況下Activity和兩個(gè)Fragment的生命周期方法執(zhí)行情況:
-
本Activity被startActivity()等方式啟動(dòng):
-
本Activity由于點(diǎn)擊HOME更振、MENU等彈回桌面時(shí):
?下圖是Android N版本下點(diǎn)擊MENU按鍵時(shí)的操作截圖(類似平常我們長(zhǎng)按HOME鍵彈出運(yùn)行中程序):
-
本Activity啟動(dòng)其他Activity,并被完全遮掩覆蓋時(shí):
-
Activity退出時(shí):
-
總結(jié):
- 啟動(dòng)Activity時(shí)饭尝,由于ViewPager默認(rèn)采用預(yù)加載的方式肯腕,所以,雖然默認(rèn)顯示第一個(gè)Fragment钥平,第二個(gè)Fragment依然會(huì)被加載和初始化实撒。
- 啟動(dòng)Activity時(shí),Activity先執(zhí)行了它本身的onCreate()->onStart()->onResume()涉瘾,之后知态,ViewPager才真的開(kāi)始運(yùn)行起來(lái)并加載指定給他的Fragment,F(xiàn)ragment才開(kāi)始它的構(gòu)造方法和生命周期方法的執(zhí)行立叛。
- 不論Activity是被另一個(gè)Activity覆蓋负敏、還是App被返回桌面、或者是彈出啟動(dòng)中應(yīng)用的界面遮掩Activity秘蛇,此時(shí)其做,Activity都是被完全遮掩(彈出Dialog等不全屏的窗體時(shí)顶考,Activity屬于部分被遮掩),此時(shí)妖泄,Activity都會(huì)調(diào)用到onStop()方法驹沿,并且這種方式中Fragment與Activity的生命周期方法執(zhí)行順序都一樣(如上面截圖)。
- 當(dāng)Activity退出時(shí)蹈胡,①Fragment執(zhí)行onStop()后渊季,Activity再執(zhí)行onStop() ②Fragment執(zhí)行onDestroyView()和onDestroy()后,Activity才執(zhí)行onDestroy()
-
另外审残,如果到這里梭域,忘了Fragment整個(gè)生命周期是怎么樣的,這里搅轿,本人附上<u>Fragment的生命周期圖解</u>:
- 關(guān)于v4、v7富玷、v13兼容包:
- Android Support v4:為了兼容Android1.6及更高版本而設(shè)計(jì)的璧坟。(eclipse新建工程時(shí),都默認(rèn)帶有v4包)
- Android Support v7:為了兼容Android2.1及以上版本而設(shè)計(jì)的赎懦,但不包含更低雀鹃,故如果不考慮1.6,我們可以采用再加上這個(gè)包,另外注意励两,v7是要依賴v4這個(gè)包的黎茎,即,兩個(gè)得同時(shí)被包含当悔。
- Android Support v13:為了Android 3.2及更高版本的傅瞻,一般我們都不常用,平板開(kāi)發(fā)中能用到盲憎。
- Activity中嗅骄,onSaveInstanceState() 和 onRestoreInstanceState() 兩個(gè)方法何時(shí)執(zhí)行?
-
onSaveInstanceState():
- 執(zhí)行情況:當(dāng)Activity處于容易被殺死的狀態(tài)下時(shí)饼疙。
- 資源相關(guān)的系統(tǒng)配置發(fā)生改變時(shí)溺森,如:手機(jī)突然橫屏等系統(tǒng)配置變化;
- 點(diǎn)擊HOME鍵退回桌面時(shí)(此時(shí)應(yīng)用處于后臺(tái)窑眯,Activity可能因內(nèi)存不足而被回收)屏积;
- 長(zhǎng)按HOME鍵啟動(dòng)任務(wù)管理器程序的時(shí)候(同樣,Activity處于后臺(tái)狀態(tài)磅甩,容易被回收)炊林;
- 本Activity啟動(dòng)其他Activity時(shí)(原Activity進(jìn)入后臺(tái)后,容易被回收)更胖。
- 鎖屏?xí)r铛铁。
- <u>onSaveInstanceState()在onStop()方法前發(fā)生隔显。</u>
-
onRestoreInstanceState():
- 執(zhí)行情況:在Activity以異常情況下終止后重新創(chuàng)建時(shí)
- 需理解以下這種情況:當(dāng)正在顯示activity A的時(shí)候,用戶按下HOME鍵回到主界面饵逐,然后用戶緊接著又返回到activity A括眠,這種情況下activity A一般不會(huì)因?yàn)閮?nèi)存的原因被系統(tǒng)銷(xiāo)毀,故activity A的onRestoreInstanceState方法不會(huì)被執(zhí)行倍权。
- <u>onRestoreInstanceState()在onStart()方法之后執(zhí)行掷豺。</u>
- 注意:onRestoreInstanceState的bundle參數(shù)也會(huì)傳遞到onCreate方法中,你也可以選擇在onCreate方法中做數(shù)據(jù)還原薄声。
-
示例截圖(手機(jī)突然橫屏):
- Java中当船,String、StringBuffer默辨、StringBuilder三者的區(qū)別:
- String 相對(duì)與后面兩者來(lái)說(shuō)德频,指向的內(nèi)存空間是不可變的,也就是每次賦值缩幸,String對(duì)象指向的內(nèi)存地址都將發(fā)生改變壹置,相當(dāng)于摒棄原地址、重建新地址表谊。
- StringBuffer和StringBuilder都是指向可變大小的內(nèi)存空間的钞护,即每次append(String)等字符串更改操作,都不會(huì)使其重新申請(qǐng)新一塊內(nèi)存地址然后指向它爆办。
- StringBuffer相對(duì)于StringBuilder來(lái)說(shuō)难咕,字符串的修改、添加等操作相對(duì)較慢(也就是字符串操作效率低一點(diǎn))距辆,但是StringBuffer線程安全余佃,對(duì)于多個(gè)線程訪問(wèn)時(shí),StringBuffer通過(guò)內(nèi)部鎖機(jī)制進(jìn)行多線程同步挑格,所以咙冗,StringBuffer更加安全。
- StringBuilder則沒(méi)有了線程安全的功能漂彤,于是它提高了字符串操作的效率雾消,但是線程不安全。
- Android自定義View的三個(gè)構(gòu)造方法(一參挫望,二參立润,三參)的區(qū)別:
- public View(Context context):在java代碼創(chuàng)建視圖的時(shí)候被調(diào)用
- public View (Context context, AttributeSet attrs):在xml創(chuàng)建,但是沒(méi)有指定Style的時(shí)候被調(diào)用
- public View (Context context, AttributeSet attrs, int defStyle):在xml中創(chuàng)建媳板、并且指定了Style時(shí)調(diào)用
- onWindowFocusChanged() 和 onFocusChanged()的用法和區(qū)別桑腮?
-
區(qū)別:
- onWindowFocusChanged()在window$callback 和 View.java 兩個(gè)類中,主要作為Window的焦點(diǎn)獲取和失去時(shí)的一個(gè)事件監(jiān)聽(tīng)蛉幸,而window$callback當(dāng)中所使用的該方法實(shí)際上也來(lái)自View.java破讨,而onFocusChanged()只位于View.java類中丛晦,主要作為View的焦點(diǎn)獲取與失去時(shí)的一個(gè)事件監(jiān)聽(tīng)。
-
兩者的具體用法:
- <u>onWindowFocusChanged()調(diào)用時(shí)機(jī)</u>:由于window的焦點(diǎn)和view的焦點(diǎn)是分離的提陶,所以這個(gè)方法被回調(diào)的時(shí)機(jī)是:窗口獲取或者失去焦點(diǎn)時(shí)烫沙,如:
- 當(dāng)啟動(dòng)Activity時(shí),Activity當(dāng)中的窗口獲取到焦點(diǎn)時(shí)隙笆,即onResume()方法之后锌蓄,會(huì)調(diào)用一次onWindowFocusChanged()。
- 從Activity跳轉(zhuǎn)到另一個(gè)Activity撑柔,新的窗口會(huì)獲取焦點(diǎn)瘸爽,舊的Activity的窗口就會(huì)失去焦點(diǎn)。
- 打開(kāi)軟鍵盤(pán)進(jìn)行輸入铅忿,窗口失去焦點(diǎn)剪决。
- 軟鍵盤(pán)輸入完畢消失,窗口重新獲取焦點(diǎn)檀训。
- 應(yīng)用被移到后臺(tái)昼捍,窗口失去焦點(diǎn)。
- 應(yīng)用重新返回前臺(tái)肢扯,窗口重新獲取焦點(diǎn)。
- <u>onWindowFocusChanged()妙用(部分)</u>:
- 重寫(xiě)onWindowFocusChanged() 方法并在里面調(diào)用getWidth()和getHeight()方法担锤,可以正確得到整個(gè)視圖的寬高蔚晨。【原理:onResume()完畢后Window才獲取焦點(diǎn)肛循,此時(shí)視圖已經(jīng)加載完畢铭腕,這樣就避免了視圖未加載完成時(shí)獲取錯(cuò)誤寬高】
- 當(dāng)由于HOME鍵等其他原因?qū)е翧pp移到后臺(tái)時(shí),對(duì)數(shù)據(jù)的臨時(shí)保存多糠,此時(shí)累舷,除了可以使用onPause()、onStop()夹孔、onSaveInstanceState()方式被盈,還可以使用onWindowFocusChanged()方法來(lái)處理數(shù)據(jù)的自定義保存操作。
- <u>onFocusChanged()用法</u>:在EditText搭伤、Button等本身可獲取焦點(diǎn)的控件或者設(shè)置了可獲取焦點(diǎn)只怎、可通過(guò)觸摸事件獲取焦點(diǎn)的自定義View、TextView等控件下可以重寫(xiě)來(lái)處理焦點(diǎn)獲取和失去焦點(diǎn)時(shí)的事件怜俐∩肀ぃ【可以用于喚起系統(tǒng)軟鍵盤(pán):通過(guò):重寫(xiě)
View.onCreateInputConnection()
等方法獲取一個(gè)軟鍵盤(pán)連接器并可以從中設(shè)定彈出的鍵盤(pán)形式,然后利用(InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
獲取InputMethodManager
對(duì)象拍鲤,就可以調(diào)用它來(lái)啟動(dòng)和關(guān)閉軟鍵盤(pán)】
- <u>onWindowFocusChanged()調(diào)用時(shí)機(jī)</u>:由于window的焦點(diǎn)和view的焦點(diǎn)是分離的提陶,所以這個(gè)方法被回調(diào)的時(shí)機(jī)是:窗口獲取或者失去焦點(diǎn)時(shí)烫沙,如:
- 讓Activity不隨著屏幕旋轉(zhuǎn)而銷(xiāo)毀
- 法一:(API13后有效)在manifest的Activity標(biāo)簽添加
android:configChanges="orientation|keyboardHidden"
注意:
orientation表示屏幕方向贴谎,keyboardHidden鍵盤(pán)可見(jiàn)性(是否調(diào)出鍵盤(pán))
旋轉(zhuǎn)屏幕時(shí)汞扎,此時(shí)Activity只調(diào)用:onConfigurationChanged()
,不會(huì)調(diào)用onRestore…
和onSave…
- 法二:設(shè)置App不可轉(zhuǎn)屏
android:screenOrientation=”landscape|portrait”
表示:橫向或者縱向擅这,二選一
-
Fragment與Activity的生命周期方法執(zhí)行順序:
詳細(xì)可以參考本人的另一篇文章:Android -- Fragment 基本用法澈魄、生命周期與細(xì)節(jié)注意
- 我們?cè)贏ndroid中寫(xiě)xml中控件或者布局、主題等屬性值的時(shí)候蕾哟,會(huì)遇到“@android:drawable/xxx”一忱,“@+id/yyyy”,“?attr/colorPrimary”等樣子的屬性值引用寫(xiě)法谭确。那么帘营,這幾種寫(xiě)法的區(qū)別是什么?
-
@+id/ thing_id
:這個(gè)好理解逐哈,有個(gè)+
號(hào)表示需要在R.xml中新添加一個(gè)這個(gè)id值芬迄,然后,供以后被調(diào)用昂秃≠魇幔【Java中調(diào)用:findViewById("R.id.thing_id");
xml中調(diào)用:android:toLeftOf="@id/thing.id"
等方式】 -
@[+][package:]type/name
:這種形式,表示引用一個(gè)已存在的屬性值肠骆。-
@drawable/img1
:表示引用我們自定義的drawable屬性值(引用自己的內(nèi)部資源) -
@+android:drawable/search_icon
:帶了一個(gè)+
號(hào)算途,表示引用android.R.drawable
中的資源,如果此資源不存在蚀腿,則在自己項(xiàng)目的R.drawable中創(chuàng)建一個(gè)search_icon的標(biāo)識(shí)嘴瓤。 -
@android:drawable/search_icon
:表示引用系統(tǒng)(android.*)的資源,沒(méi)有則報(bào)Android.content.res.Resource$NotFoundException
的異常莉钙。
-
-
?[namespace:type/]name
:表示引用屬性廓脆。【不需要明確指出它的類型】
如:①?android:attr/android:textDisabledColor
和②?android:textDisabledColor
磁玉,兩者是一樣的停忿,前者聲明了索要屬性值的類型而后者沒(méi)有說(shuō)明,兩者都可以獲取系統(tǒng)中的主題屬性蚊伞,只要我們提供想要的屬性名席赂,它將會(huì)在主題中被查找(因?yàn)橘Y源工具知道需要的屬性資源,所以我們不需要顯式聲明這個(gè)屬性)厚柳。
感謝閱讀~
本篇文章將持續(xù)更新~
喜歡的讀者可以點(diǎn)個(gè)關(guān)注氧枣,本人將持續(xù)發(fā)布Android相關(guān)文章~