android 四大組件詳解「android菜鳥教程目錄」

前言

最近完成了移動編程課程的學習,加上其它安卓開發項目的經歷,感覺收穫頗為豐富。故在此總結整理安卓開發中比較常見的一些問題,技巧和指南。

1.開發環境

Android Studio是谷歌基於IntelliJ IDEA社區版開發的,面向安卓開發的免費集成開發環境。其方便快捷的開發調試和可視化UI編輯可以令安卓開發事半功倍。本項目所使用集成開發環境為Android Studio 4.1.1,編程語言為Java,使用JDK 1.8,使用Gradle 4.1.1進行項目工程構建和依賴管理。

2. 項目新建

Android Studio新建項目時選擇一個Activity模板作為默認MainActivity,先選擇Empty Activity作為開始。接著,Minimum SDK指的是本項目所支持的最小安卓SDK,點擊「Help me choose」會出現如下界面幫助選擇合適的安卓最小SDK版本:學習筆記 | Android Studio安卓開發入門經驗總結 乾貨

圖1 安卓API版本選擇幫助界面

其中CUMULATIVE DISTRIBUTION表示如果支持該安卓版本以上設備,則預估能支持安卓設備占所有安卓設備的百分比。可見Minimum SDK越小所能支持設備越多,但沒有必要一味追求支持更多設備,這需要根據一定的市場調查與經驗來決定。本項目選擇支持默認的安卓6.0及以上。

3.項目結構

3.1 開發模式

安卓開發常見的開發模式有MVC,MVP,MVVM等(詳見本站文章 「學習筆記 | Android開發常用的幾種模式」),其中MVC非常容易上手,結構清晰易懂,為了簡化開發,本項目使用MVC模式進行開發。

3.2 安卓項目文件及目錄結構簡介

  • 安卓應用配置文件AndroidManifest.xml: 用於配置包名、應用許可權、應用圖標及名稱、主題等基本信息,此外包括了應用的Activity相關配置,沒有在此進行註冊的Activity是不能被啟動的。
  • 程序代碼java: 在java目錄下的對應包名中存放包括Activity在內的各java程序文件。
  • 資源文件res: 存放用於UI相關的各類資源,主要有:drawable:存放可被繪製的圖形,包括矢量圖和點陣圖,以及由xml編寫的各類圖層、狀態選擇器等比較實用的前端UI部件。layout: 以xml文件形式編寫的用戶交互界面,可以在Android Studio中進行實時渲染預覽、可視化編輯等。values:arrays.xml: 存放數組,在程序中按照自定義的數組名進行讀取。colors.xml: 存放Hex色值,在程序中按照自定義的顏色名字進行讀取。dimens.xml: 存放尺寸信息。strings.xml: 存放字元串,按照自定義的字元串名進行獲取,方便多語言程序的本土化。themesthemes.xml: 程序主題,包括主色次色和各類樣式。themes.xml(night): 程序夜間主題。mipmap: 存放貼圖文件,如果期望貼圖有放大縮小動畫之類的可以獲得更好的圖像表現。xml: 存放一些其它xml格式的文件,例如網路安全配置文件network_security_config。
  • Gradle構建配置文件build.gradle項目級構建配置build.gradle(Project: $project_name):用於配置適用於項目的Gradle構建設置,例如使用的Gradle版本,構建腳本的倉庫,依賴包倉庫。例如:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
    repositories {
        //這裡放置項目構建倉庫
        google()
        jcenter()
    }
    dependencies {
        //這裡放置項目構建所需的依賴,而不是模塊(總之平時用的依賴一般都不是放這裡)的依賴
        classpath "com.android.tools.build:gradle:4.1.1"
        // NOTE: Do not place your application dependencies here; they belong in the individual module build.gradle files
    }
}

allprojects {
    repositories {
    //依賴包倉庫,也就是依賴包從哪下載,一般使用國內鏡像下載快很多
        maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'}//阿里雲的倉庫,便於下載依賴包
        maven{ url "https://jitpack.io"}
        google()
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

  • 模塊級構建配置build.gradle(Module: $project_name.app)
…
dependencies {
//這裡才是放置要用到的第三方依賴的地方
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'com.google.android.material:material:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.0.0'
    implementation 'androidx.fragment:fragment:1.2.4'
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'

    implementation 'com.squareup.okhttp3:okhttp:3.10.0'//http通信的依賴庫
    implementation 'com.github.bumptech.glide:glide:3.7.0'//載入圖像的依賴庫
    implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.0.0'
    implementation 'com.makeramen:roundedimageview:2.2.1'
    implementation 'com.google.code.gson:gson:2.8.7'
}

3.3 程序設計要點

3.3.1 Activity和Fragment的生命周期

正如生物一樣,Activity和Fragment作為安卓交互程序也有「生死」,也就是生命周期。
Activity生命周期
如圖為一個Activity從被啟動到被停止的生命周期:學習筆記 | Android Studio安卓開發入門經驗總結 乾貨

圖2 Activity生命周期[2]

  • onCreate(): Ativity被創建的時候,常用於初始化基本布局,使用setContentView()載入布局文件,進行一些其它基本不耗時間的操作,實在需要就用非同步線程,避免頁面長時間空白。
  • onStart(): Activity被展示的時候,也就是說被創建了不一定要顯示出來,但要顯示出來了才onStart()。
  • onPause(): Activity將要被掛起的時候,頁面失去焦點無法交互,此時Activity仍可見,比如將轉入後台運行。
  • onResume():Activity已經從後台喚起並顯示出來,將要但還未獲得焦點無法操作的時候。
  • onStop(): Activity以及失去焦點且要轉入後台的時候,此時Activity已不可見。
  • onRestart(): Activity被掛起後又被喚醒的時候,此時Activity還未顯示出來。
  • onDestroy(): Activity被徹底銷毀的時候。

Fragment生命周期
Fragment生命周期與Activity周期較為類似,但其中比較值得提及的是:

  • onAttach():Fragment與Activity建立關聯的時候,也就是此時Fragment已經知道了擁有自己的「上司」Activity是誰。
  • onActivityCreated():此時建立關聯的Activity已經結束了onCreate()並返回。
  • onCreateView():此時初始化Fragment布局,也是將基本的布局載入好,不建議耗時間的操作,實在需要就用非同步線程。
  • onDestroyView():Fragment的視圖已經被銷毀,但與Activity的關聯未銷毀,仍然可以重新創建視圖。
  • onDetach():與Activity的關聯將要被解除,Activity在onDestory()時會自動調用與之有關聯的Fragment的onDetach()方法。

3.3.2 網路請求與非同步線程

Android 4.0以後網路請求不能在主線程中執行已經是老生常談了,這是為例放置線程阻塞應用無響應。解決方案一般就是啟動非同步線程進行處理,UI線程和網路請求就分離開了,各干各的。但這之間如何通信呢,或者說網路請求結束,不管成功失敗,如何告訴UI線程?這將在3.3.3 Handler消息處理中提到。
線程通常還要用到線程輔助類Runnable,在Runnable的要求強制重寫的方法run()中執行網路請求任務。例如:

Runnable networkRunnable = new Runnable() {
    @Override
    public void run() {
        //可以在此處執行網路請求和數據解析操作,拉取聯繫人消息之類
     }
};
Thread thread = new Thread(networkRunnable);
thread.start();//啟動線程

不僅如此,耗時操作通常都是在線程中執行的,例如資料庫讀寫和一些其它文件操作之類,可見,多線程是安卓開發中一個重要的技術。

3.3.3 Handler和消息處理

上節中提到,不同線程間如何通信,Handler就是一個易用的方案。如果把各個線程比作各干各活的工人,Handler就像是個中間人,負責把各個工人傳來的消息進行處理,並有權操作UI線程中的組件,比如更新TextView的文字(非UI線程是不能操作的)。「工人」如何給Handler發一條消息?實現起來很簡單,比如網路請求處理成功以後:

private final int NETWORK_PROCESS_OK = 1;//定義一個數字代號代表網路處理成功
private final int NETWORK_PROCESS_FAIL = 0; //代表網路處理失敗
Message msg = handler.obtainMessage();//需要保證此時Handler的實例handler已經實例化不為空。
msg.what= NETWORK_PROCESS_OK;
msg.sendToTarget();
//失敗以後也可以傳回原因:
Message msg = handler.obtainMessage();
msg.what= NETWORK_PROCESS_FAIL;
msg.obj=reason;//reason一般是String,但可以是任何Object
msg.sendToTarget();

而Handler接收到消息後的處理一般如下:

handler = new Handler(){
     public void handleMessage(Message msg) {  
            switch (msg.what) {  
            case NETWORK_PROCESS_OK:  
                textview.setText("處理成功!");  
                break; 
           case  NETWORK_PROCESS_FAIL:  
                textview.setText("處理失敗!原因:" + msg.obj.toString());  
                break;
            }  
        };  
};

3.3.4 Activity間的跳轉

Activity間使用Intent類進行跳轉和數據傳輸,具體如下:

Intent intent = new Intent(this,TargetActivity.class);//this是一個Activity對象
intent.putExtra(「param1」,paramString1);//通過intent傳送額外數據,可以在目標Activity中,使用getIntent()獲取傳入的intent對象,利用該intent對象的getStringExtra()接受傳入的String類型參數,當然也有其它類型的,此處不列舉。
startActivity(intent);

值得注意的是,Intent所能傳輸的數據容量是有上限的,過多的數據不建議使用Intent進行傳輸。

3.3.5 回收型列表視圖RecyclerView的使用

RecyclerView是基於viewholder的回收理念在ListView上的一個升級版,功能強大,當然在不需要進行回收的場景就當然不要用了,例如實現多行可選擇的標籤,如果標籤滑出屏幕外被回收了的話,選中狀態也會一起丟失,除非用額外的對象進行選中狀態記錄。
RecyclerView的適用場景是有大量用於展示的列表數據的場景,比如微信的公眾號頁面的推文卡片、微信朋友圈、QQ的好友列表、小紅書的瀑布流帖子等。
和ListView類似,要將數據適配到視圖上進行展示需要使用適配器Adapter,不同的是RecyclerView的BaseAdapter已經將viewholder模式封裝好了,而目前RecyclerView的適配器有很多優秀的第三方庫,例如Github上開源的CymChad的適配器助手
BaseRecyclerViewAdapterHelper,封裝了基本的適配器操作,秩序簡短的幾行代碼就能實現基本的適配操作,也封裝了很多功能豐富的類與介面,例如可以實現下拉刷新,上拉載入的介面,可以實現多布局共存的MultiItemAdapter<T>等等[4],因此在合適的場景下使用是很好的,避免重複造輪子,但為了學習和了解更底層的原理,本項目中還是用最原始的ListView和RecyclerView的自帶適配器。

3.3.6 適配器理念Adapter

如上所說,列表視圖需要一個中間件:適配器,來將數據適配到布局上,這是一個從結構化的數據到結構化的視圖的中間過程,縱觀整個項目開發,可以發現有很多地方在使用這樣的理念,除了列表視圖的適配器以外,裝載Fragment的ViewPager的PagerAdapter也是同樣使用了適配器的概念,使得ViewPager可以比較方便的管理多個Fragment,降低耦合。同樣的,這樣的理念也可以運用到有著多種網路請求的場景中,使用工廠模式和適配器理念,將網路請求返回結果適配到實體類對象或UI視圖裡,這對於降低耦合度和提高多態性是很有幫助的。

原創文章,作者:投稿專員,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/268471.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
投稿專員的頭像投稿專員
上一篇 2024-12-16 13:09
下一篇 2024-12-16 13:09

相關推薦

發表回復

登錄後才能評論