Android 經(jīng)典筆記之一

Android 經(jīng)典總結(jié)案例一
目錄介紹:
1.完美解決onActivityResult提前執(zhí)行調(diào)用的一系列問題
1.1 出現(xiàn)的問題
1.2 解決方案
1.3 相關(guān)原理說明
1.4 知識拓展
2.EditText調(diào)用軟鍵盤搜索的setOnKeyListener方法事件執(zhí)行兩次
2.1 出現(xiàn)的問題
2.2 解決方案
2.3 相關(guān)原理說明
2.4 知識拓展
3.關(guān)于64k方法書限制的原理和解決方案探討
3.1 先看看報錯
3.2 64k****產(chǎn)生原因?
3.3 如何解決64k的問題
3.4 優(yōu)化Multidex的開發(fā)和構(gòu)建

好消息

  • 博客筆記大匯總【16年3月到至今】,包括Java基礎(chǔ)及深入知識點(diǎn),Android技術(shù)博客,Python學(xué)習(xí)筆記等等,還包括平時開發(fā)中遇到的bug匯總,當(dāng)然也在工作之余收集了大量的面試題,長期更新維護(hù)并且修正,持續(xù)完善……開源的文件是markdown格式的!同時也開源了生活博客,從12年起,積累共計47篇[近20萬字],轉(zhuǎn)載請注明出處,謝謝!
  • 鏈接地址:https://github.com/yangchong211/YCBlogs
  • 如果覺得好,可以star一下,謝謝!當(dāng)然也歡迎提出建議,萬事起于忽微,量變引起質(zhì)變!

1.完美解決onActivityResult提前執(zhí)行調(diào)用的一系列問題

這是原本要啟動的MainActivity
int requestCode = 200;
Intent intent = new Intent(this,SecondActivity.class);
startActivityForResult(intent,requestCode);

SecondActivity回傳攜帶的數(shù)據(jù)
Intent mIntent = new Intent();
mIntent.putExtra("addr_id", retData.get(position));
// 設(shè)置結(jié)果,并進(jìn)行傳送
setResult(resultCode, mIntent);     
finish()

清單文件manifest.xml配置
<activity android:name=".activity.SecondActivity" android:launchMode="singleTask"/>

1.1.問題:代碼沒有任何問題,onActivityResult方法一直回調(diào)不過來數(shù)據(jù),debug調(diào)試以后才發(fā)現(xiàn)onActivityResult方法在開啟另外一個activity的時候提前執(zhí)行了
1.2.解決方案: 發(fā)現(xiàn)manifest.xml配置AddressActivity的啟動模式是singleTask,就抱著試試看的態(tài)度,把他改成了標(biāo)準(zhǔn)啟動模式,然后突然回傳數(shù)據(jù)
1.3.原理說明:
如圖:假設(shè)當(dāng)前的應(yīng)用程序存在兩個棧:其中一個直接顯示在屏幕上負(fù)責(zé)與用戶完成交互,叫BackStack;另一個是隱藏在后臺的background task,且位于該棧頂?shù)腁ctivity Y的啟動模式被設(shè)置為singleTask。
參考官方文檔可知:

Image.png

在上圖中,存在著前兩個棧,其中直接顯示在屏幕上與用戶交互的Back Stack,及另一個隱藏在后臺的Background Task,該棧棧頂?shù)腁ctivity Y其launchMode為singleTask。
如果在Activity 2中調(diào)用BackgroundTask中已經(jīng)啟動過的Activity Y,則Background Task內(nèi)占據(jù)屏幕并且該Task下所有的棧都會保留當(dāng)前的棧位置及順序push進(jìn)Back Task形成新的結(jié)構(gòu),順序由上至下為Activity Y→Activity X→Activity 2→Activity 1。
在Activity Y界面按返回鍵,則ActivityY出棧,Activity X占據(jù)屏幕!注意,由Activity2調(diào)用的Activity Y,但返回鍵后,回退顯示的是Activity X!所以即使在Activity Y執(zhí)行setResult(),Activity 2也是無法接收到的。換回文章開頭的問題,即在JumpActivity處啟動LoginActivity(已經(jīng)被設(shè)置singleTask了),則LoginActivity的setResult()結(jié)果有可能不會傳給JumpActivity。
繼續(xù)按返回鍵,則才回到Activity 2。
由于這種現(xiàn)象的存在,所以android系統(tǒng)處于某種保護(hù)機(jī)制,發(fā)現(xiàn)將要跳轉(zhuǎn)的Activity的啟動模式是singleTask時,若需要執(zhí)行onActivityResult()函數(shù)則立即執(zhí)行。這樣就好理解多了。

1.4.知識延伸:
singleTop模式,可用來解決棧頂多個重復(fù)相同的Activity的問題。
singleTask模式和后面的singleInstance模式都是只創(chuàng)建一個實例的。
當(dāng)intent到來,需要創(chuàng)建singleTask模式Activity的時候,系統(tǒng)會檢查棧里面是否已經(jīng)有該Activity的實例。如果有直接將intent發(fā)送給它。
singleInstance模式解決了這個問題(繞了這么半天才說到正題)。讓這個模式下的Activity單獨(dú)在一個task棧中。這個棧只有一個Activity。導(dǎo)游應(yīng)用和google地圖應(yīng)用發(fā)送的intent都由這個Activity接收和展示。

2.EditText調(diào)用軟鍵盤搜索的setOnKeyListener方法事件執(zhí)行兩次

etProjectName.setOnKeyListener(new View.OnKeyListener() {
    @Override
    public boolean onKey(View v, int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_ENTER) {
        // 先隱藏鍵盤
        ((InputMethodManager) getSystemService(INPUT_METHOD_SERVICE))
            .hideSoftInputFromWindow(PublishProjectActivity.this.getCurrentFocus()
                .getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
        //進(jìn)行搜索操作的方法,在該方法中可以加入mEditSearchUser的非空判斷
        **search();     //執(zhí)行兩次,想一想為什么?**
        return true;
    }
    return false;
    }
});

2.1.問題:點(diǎn)擊后事件執(zhí)行兩次
2.2.原理分析:
setOnKeyListener之所以執(zhí)行兩次就是因為down和up占用了

2.3.解決方案:
第一種方案

etProjectName.setOnKeyListener(new View.OnKeyListener() {
    @Override
    public boolean onKey(View v, int keyCode, KeyEvent event) {
    **//發(fā)現(xiàn)執(zhí)行了兩次因為onkey事件包含了down和up事件,所以只需要加入其中一個即可。**
**    //這個是個取巧的辦法**
**    if (keyCode == KeyEvent.KEYCODE_ENTER && event.getAction() == KeyEvent.ACTION_DOWN)** {
        // 先隱藏鍵盤
        ((InputMethodManager) getSystemService(INPUT_METHOD_SERVICE))
            .hideSoftInputFromWindow(PublishProjectActivity.this.getCurrentFocus()
                .getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
        //進(jìn)行搜索操作的方法,在該方法中可以加入mEditSearchUser的非空判斷
        search();     //執(zhí)行兩次,想一想為什么?
        return true;
    }
    return false;
    }
});

第二種方案

et.setOnEditorActionListener(new TextView.OnEditorActionListener() { 
    @Override 
    public boolean onEditorAction(TextView v, int actionId, KeyEvent event){ 
        //判斷是否是“放大鏡”鍵【簡稱搜索鍵】
        if(actionId == EditorInfo.IME_ACTION_SEARCH){ 
        //隱藏軟鍵盤 
        //對應(yīng)邏輯操作
        return true; 
        } 
        return false; 
    } 
});

需要注意的是 setOnEditorActionListener這個方法,并不是在我們點(diǎn)擊EditText的時候觸發(fā),也不是在我們對EditText進(jìn)行編輯時觸發(fā),而是在我們編輯完之后點(diǎn)擊軟鍵盤上的各種鍵才會觸發(fā)

2.4.知識延伸:
修改Editview屬性:Android:imeOptions="actionSearch" 在該Editview獲得焦點(diǎn)的時候?qū)ⅰ盎剀嚒辨I改為“搜索”

android:singleLine="true"      不然回車【搜索】會換行
可以隨自己的需求更改軟鍵盤右下角的顯示樣式,例如:搜索,下一步,Q(搜索圖標(biāo))

actionNone : 按下后光標(biāo)到下一行(回車)
actionGo : 按下后搜索(Go)
actionSearch : 放大鏡【搜索】
actionSend : Send 按下后發(fā)送
actionNext : Next 下一步
actionDone : Done,確定/完成,隱藏軟鍵盤(包括不是最后一個文本輸入框的情況也會隱藏)
使用方法:在xml里面寫布局時直接加給EditTxt的imeOptions屬性,例如:

項目開發(fā)中涉及到按鍵事件處理:

**“dispatchKeyEvent” “onKeyDown ”“onKeyLisenter” 簡單理解**
接受按鍵優(yōu)先級:

**dispatchKeyEvent > Activity的onKeyDown > view的onKeyLisenter**
其中按鍵處理事件return true ;表示已消耗此事件,不再繼續(xù)傳遞;

3.關(guān)于64k方法書限制的原理和解決方案探討
3.1 先看看報錯,截圖如下

[圖片上傳中。。。(2)]
3.2 產(chǎn)生原因?
Android APK文件本質(zhì)上是一個壓縮文件,它包含的classes.dex文件是Dalvik字節(jié)碼文件,這個dex文件中存放的就是編譯后的Java代碼。Dalvik可執(zhí)行文件規(guī)范限制了單個.dex文件最多引用的方法數(shù)是65536個。Android官方的叫法是64k,也就是1024x64=65536個Java方法。
其中包含第三方庫,App應(yīng)用,以及Framework及自身的方法。
3.3 如何解決64k的問題
google為了規(guī)避上述問題,推出了MultiDex解決方案解決方法數(shù)超限問題。
A:首先需要配置build.gradle文件【注意是項目下的build文件】
添加代碼如下所示:

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.0"    //必須使用21或之后的版本
    defaultConfig {
        minSdkVersion 14
        targetSdkVersion 21       

        // Enabling multidex support.
        **multiDexEnabled true**
    }
}

dependencies {
    compile 'com.android.support:multidex:1.0.0'
}

B:配置Application
如果用戶沒有重寫Application,只需修改Manifest文件中的內(nèi)容:

<application
    android:name="android.support.multidex.MultiDexApplication">
</application>

如果用戶繼承變重寫了Application,可以將繼承的Application換成MultiDexApplication。 或者重寫attachBaseContext() 方法

@Override
 protected void attachBaseContext(Context base) {
     super.attachBaseContext(base);
     MultiDex.install(this);     //這個方法是在onCreate之前執(zhí)行的
}

特別注意,如果沒有實現(xiàn)這部分代碼,運(yùn)行時會出現(xiàn)NoClassDefFoundError的錯誤,尤其是在依賴三方函數(shù)庫時。

3.4 優(yōu)化Multidex的開發(fā)和構(gòu)建

這塊看書后還是不太懂,

后續(xù):
平時喜歡寫寫文章,筆記。別人建議我把筆記,以前寫的東西整理,然后寫成博客,所以我會陸續(xù)整理文章,只發(fā)自己寫的東西,敬請期待:
知乎:https://www.zhihu.com/people/yang-chong-69-24/pins/posts
領(lǐng)英:https://www.linkedin.com/in/chong-yang-049216146/
簡書:http://www.itdecent.cn/u/b7b2c6ed9284
csdn:http://my.csdn.net/m0_37700275
網(wǎng)易博客:http://yangchong211.blog.163.com/
新浪博客:http://blog.sina.com.cn/786041010yc
github:https://github.com/yangchong211
喜馬拉雅聽書:http://www.ximalaya.com/zhubo/71989305/
脈脈:yc930211
開源中國:https://my.oschina.net/zbj1618/blog

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容