陳昱儒
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note No publishing access yet

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.

      Your account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

      Your team account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

      Explore these features while you wait
      Complete general settings
      Bookmark and like published notes
      Write a few more notes
      Complete general settings
      Write a few more notes
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Make a copy
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Make a copy Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note No publishing access yet

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.

    Your account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

    Your team account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

    Explore these features while you wait
    Complete general settings
    Bookmark and like published notes
    Write a few more notes
    Complete general settings
    Write a few more notes
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    1
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    # Android Studio 學習筆記 - 課程 ## 序 * 主要閱讀資料-:[android developer官方文件](https://developer.android.com/guide/topics/ui/declaring-layout?hl=zh-tw#write) * 次要學習資料: * [HKT線上教室【從零開始學 Kotlin 程式設計】Android Kotlin](http://tw-hkt.blogspot.com/2018/11/kotlin_57.html)、 * [Android Studio快捷鍵](https://developer.android.com/studio/intro/keyboard-shortcuts?hl=en) * 使用的後端資料庫:Node.js + MongoDB(mongoose套件) *測試伺服器名稱(androidproj)* * [範例Code](https://www.notion.so/Android-code-0abf76b0d303451c9f0bcc3995bd1ee7) ## 一、基本重要觀念 - Activity LifeCircle (生命週期) ![](https://i.imgur.com/ENu39Lx.png) 1. lifecycle:每個階段觸發條件達成時就呼叫一次,每次打開,就是一個activity(ex:google Map . spotify...)。 2. create: 創建一次就不會創建的資料,ex:地圖元件。 3. start: 將每次activity開始時,所需要設定的初始值寫在這,也可以寫在create。 4. resume: 每次回到這個畫面都要做的事情,ex:更新api刷新畫面、重新定位。 5. create&start&resume,在activity被開啟時,就會一次跑完,然後停留在running的狀態。 6. pause: 當有其他的activity被打開時,就會先把原本的暫停然後放到stack,所以按下返回會回到畫面,並跑一次resume。 7. stop:如果在暫停一段時間後(通常都滿快的-pause的事情跑完後),就會到stop此時就會停留在手機要開啟分頁才會點即看到的地方),++**如果此時點開會回到resume**++,除非是經過navigates才會到restart -> 再到start,但這一段比較複雜點通常不會執行到。 8. Destroy:除非到手機開啟分頁時,把該程式滑掉,才會被destroy。 9. 記憶體要控管好,才不會閃退,另外pause、stop狀態時如果有碰到記憶體不夠時就會自動釋放掉,所以點開他的時候才會重新create->start->rusume。 --- ## 二、專案基本知識 1. manifests->AndroidManifest.xml 整個專案的主幹,設定檔~ ```xml= <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.kotlintest"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.KotlinTest"> <!-- label 標題名稱; theme就像遊戲的選單模組的theme一樣,系統會套用 --> <activity android:name=".MainActivity"> <!-- 如果有新設的activity要在這裡設定,不然系統不會管 --> <intent-filter> <!-- intent非常重要,所有android的跳轉功能(ex: 開啟app),都是這裡的功能 --> <action android:name="android.intent.action.MAIN" /> <!-- 標示這一個是主Activity --> <category android:name="android.intent.category.LAUNCHER" /> <!-- 設定首頁的概念,第一個要跑進來的activity --> </intent-filter> </activity> </application> </manifest> ``` 2. java 資料夾:撰寫activity 程式邏輯的地方,實際執行的地方。 3. res 資料夾:所有的資源庫都放這,有內建的R可用(會跑一遍resource資料,然後像是幫你建好path(但是是常數-int)),所以打R就可以呼叫,在.要的資料,ex: `R.id.btnTest`、`(R.layout.activity_main` ★檔名一定要全小寫,_區隔,不然會抱錯,包含圖片 1. drawable:放圖檔、向量檔。 2. layout:放所有的畫面(Activity、元件..) 3. mipmap:放icon 4. values:設定整個系統的資料、幾乎都是enum(ex:Global) 5. 之後用到動畫、選單等等,會在新增。 6. 裡面的檔名命名規則:全小寫、 '_' 區隔、倒裝(先寫功能,在寫元件名稱 ex:activity_main。) 7. layout並非執行的地方,是資料給java讀檔後寫出(像是地圖產生器&地圖編輯器合併起來的概念)。 8. values為了後面的彈性方便,所以會把String、Color等等都變成變數,放在這裡,這樣在之後如果要發展多國語系等等時,只需要在這邊設定,全部的地方都會跟著被變動。 4. Gradle: 就像npm,是套件管理工具。 1. android defaultConfig裡面會放可以支援的java version 從幾到幾,以及該程式的版本號。 1.versionCode:實際的版本號(內部)。 2.versionName:要顯示給外面看的版本號(外部)。 2. dependencies:要安裝導入的套件。 --- ## 三、基本知識 1. 開發流程: 1. res-layout刻出畫面。 2. java-activity撰寫程式邏輯。 3. 中間有需要的資源就在res放對應的資料。 2. 原則上所以程式的String都會用變數替代,然後該變數放到res-values裡面,以利後續程式做不同語言時可以使用。 3. androidx是為了解決相容性的問題而產生的套件,基本上都建議使用他,以免版本不同,而導致程式有問題。 4. layout是容器(就像java的JFrame、JPanle)。 5. Android是利用XML ++(標記式語言,可以依照使用者需求來決定解析的方式)++ 來決定UI佈局的設定,並且在編譯(Compile)時,系統會將所有XML版面配置檔案(Layout)編入View資源,再利用setContentView來載入XML資源並產生實際畫面。 6. IDE的資料夾顯示:Compact Middle Package 的設定可以隱藏空的資料夾。 7. 要創建新的activity,要用new->activity->empty activity,才會自動幫你建好layout以及放入manifest裡面。 8. ★網路連線會放到IO(工作用執行緒)的執行緒去跑,不會放在UI(主執行緒) ,不然會阻塞,嚴重可能會直接閃退,只要在主執行緒上處理網路連線,會直接報錯。 9. android studio 用 Log.d印資訊,可以處裡的東西比較多。 ### 執行緒 1. 重要觀念,要特別注意及處理: 1. Race Codition 資源競爭 兩條以上執行緒同時對一個資源做事,導致值異常,此時可以用java Synchronized -把值鎖住,這段時間外面不可以拿到他的值;鎖的方式有分很多種。 2. Dead Lock 死鎖:用Synchronized鎖起來後,也可能會因為互相鎖住,導致無限卡死,此時就稱為Dead Lock,通常單例都會鎖同步。 2. 因為兩個執行緒是平行(異步)的,每次兩邊都是跑一點點(是電腦指令而非程式碼):ex: i+=1 是好幾個電腦指令做動的 EX: 先加i放到暫存其,有個Atomit.. 可以把這些指令包成一個原子,也就是是同一個指令 3. ★ Andriod 有兩個執行緒: * UI 主執行緒:畫面相關的,絕對不要在IO裡面做修正修改,不然一定會壞,UI要盡量降低運算的複雜度,這樣畫面才不會卡頓,手機的卡頓,就會直接閃退。 * IO執行緒(副執行緒-工作處理用)(可能有多個)-利用Callback來讓主執行續得到資料。 4. ★IO執行緒可以用`runOnUiThread(()->{})`,把資料傳到主執行緒上,主執行緒在依照收到的資料做事情,要注意送資料不一定會先做,所以先把要跑的邏輯跑完後在送出資料。 5. 只要不在UI跑得都算是背景執行,要像跳通知那樣是程序,跨程序溝通要用作業系統才能處理(C++ 或比較用到底層的寫法才會用到)(IPC) 。 6. 不要用Looper.prepare() 事情Looper.loop(),因為執行續不會被關閉,除非是要像網路連線那樣,程式打開中都要使用,有點類似背景執行,但還不是LINE跳通知(是process程序),。 7. Android 有提供機制輔助你在兩個執行續先傳遞資料,內建處理的,不然實際實現很麻煩。 補充資料:[Synchronized用法-java](https://www.jackforfun.com/java-synchronized) --- ## 四、撰寫畫面(layout) 1. 刻畫面主要為LinearLayout(線性布局)、ConstrainLayout: 1. Linear: 利用水平、垂直排版物件,可以linear接一個linear以此達到像表格的形狀(稱為嵌套)。 * 適合格局方正的工具型App。 * 可以直接編輯code,更快速。 2. Constrain:利用的是與其他物件或螢幕邊框的相對位置(比率)對齊物件,要設定物件上下左右依靠的物件(要相對的目標)。 * 建議用拖曳的,code太複雜不會比較快。 3. 實務上大多會先用Linear完成大部分排版後,再套到Constrain細部調整,已完成自適應大小。 4. 目前預設容器都是ConstrainLayout。 2. 畫面設定大小的三種方式: 1. 100dp => 依照螢幕解析度寫死大小 2. match_parent => 依照父容器的大小決定 3. wrap_content => 依照容器內元素的大小決 * 若最外層的容器設為match_parent即為手機的寬/高大小 * 若最內層的原件設為wrap_content即為元件所需要的範圍大小 3. 常用的元件及縮寫表: | 名稱 | 縮寫 | 備註 | | -------- | ------ | ---- | | [TextView](https://developer.android.com/reference/kotlin/android/widget/TextView?hl=en#top_of_page) | tvName | 1.顯示文字所使用的元件<br>2.text屬性為設定顯示出的文字(set或get)<br>3.正常開發時不會有textview留著,因為在連線時會被看到。 | | [EditText](https://developer.android.com/reference/kotlin/android/widget/EditText?hl=en) | etName | 1.輸入框的元件<br>2.text屬性為讀取到的文字(set或get),但格式不是String要自己轉。<br>3.`.isNullorEmpty()`判斷是否有輸入值。<br>4.[自定義邊框、圓角](https://www.itread01.com/content/1546117761.html) | | [Button](https://developer.android.com/reference/kotlin/android/widget/Button?hl=en) | btnName |1.按鈕的元件<br>2.基本上邏輯寫在按鈕,也就是點擊後觸發。 | 4. 白色畫面是外部顯示的畫面,藍色畫面是元件的實際大小 --- ### 撰寫畫面-LinearLayout 1. 更改第一層的Layout方式:到code,把`androidx.constraintlayout.widget.ConstraintLayout` 改成LinearLayout。 2. 第一層LinearLayout:所有元件都會在這裡面,寬高通常都會設成match_parent。 通常除了第一層LinearLayout外的元件寬高都會設wrap_content(依照實際內容)。 3. LinearLayout會由起始位置開始擺放其中的元件,可以在接LinearLayout當子元件(不一樣的方向),設計時以橫跨螢幕的最長邊為基準作為方向判定的方式。 * 垂直 => 由上往下照順序擺放元件 * 水平 => 由左至右照順序擺放元件 4. 其中Padding與Margin皆有all/top/bottom/left/right五種屬性,當all被設定時,其餘屬性會失去效果,如果需要針對不同邊有不同間距,需要個別進行設定。 5. LinearLayout(orientation)分為Vertical與Horizontal兩種: * Vertical中的子元件layout_gravity中center_vertical將會無效(垂直的位置由LinearLayout決定) * Horizontal亦然,子元件layout_gravity中center_horizontal將會無效。 6. 常用的設定表格及其說明: | 名稱 | 用途 | | ------------- | ------------------------ | | orientation | 決定LinearLayout垂直(vertical)/水平排版(horizontal)的屬性 | | layout_width<br>layout_height | 設定寬跟高的大小 | | padding(內間距) | 1.此元件對元件內部的間距<br>2.通常用於要改變按鈕、內容大小,會影響元件wrap_content的大小| | layout_margin(外間距) | 1.此元件對元件外部的間距<br>2.通常用於要有間格距離時,不會改變內容大小 | | gravity (內重心)<br> layout_gravity(外重心) | 內重心:將其子元件設到其重心位置,基本上寬高跟父類時使用。<br>外重心:將其重心位置對應父元件的相對位置,基本上寬高跟內容時使用。 | | hint | 該欄位提示文字(輸入框),不會影響輸入。 | | text | 該欄位顯示文字,可以後面用set去設定,要注意如果是輸入框會影響到輸入的值。 | | text.size | 該欄位顯示文字大小。 | | id | 這個元件的變數名稱(縮寫+功能名),後面可用R.id.這個名稱找到他,要注意要是被導入的layout,其id名稱才有效。(因為findViewById 是吃layout裡的view,所以要在該layout內的id才有效。 | | inputType | ★editText使用,用來決定輸入時要跳出什麼鍵盤EX:`Editor.Info.TYPE_CLASS_NUMBER`開啟數字鍵盤 | | weightSum <br> layout_weight (分配比重) | 1.子元件與父元件(LinearLayout)的分配,將這段距離(剩餘的空間)按weightSum切分,看其比重占多少。<br>2.weightSum只有LinearLayout有,layout_weight都有。<br>3.比重可以有小數點。<br>4.如果沒設weightSum,預設就是weight的總和,ex:有三個元件weight設1,就會剛好分三等份。<br>5.要注意比重分配並不代表間距會自動隔開,還是要靠margin去調整。<br>6.layout_weight設定後,有設定layout_weight的子元件,需把對應方向的大小設定為0dp(vertical->height;Horizontal->width),不可以將對應方向大小刪除,將會造成錯誤 | 補充資料:[XML屬性大全](https://developer.android.com/reference/kotlin/android/widget/TextView?hl=en#xml-attributes) --- ## 五、撰寫程式邏輯- Activity & intent 1. override 要設定的地方(ex:onCreate、onResume) 2. 創建該activity的元件實體(ex:TextView、Button) 3. 對元件編寫程式邏輯(ex:btn按下後要做什麼事情、設定tv顯示的文字) ```kotlin= class MainActivity : AppCompatActivity() { //1.override 要設定的地方 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_bmi) //設定畫面要顯示什麼,xml這時候才被抓取出來使用 // Log.d("test","Button Login Clicked");// Debug印資訊使用-測試用 //2.創建該activity的元件實體 var etHeight = findViewById<EditText>(R.id.etHeight) var etWeight = findViewById<EditText>(R.id.etWeight) var btnBmi = findViewById<Button>(R.id.btnBmi) var tvBmi = findViewById<TextView>(R.id.tvBmi) //3.對元件編寫程式邏輯ex:設定按下button後的邏輯及textview顯示的文字。 btnBmi.setOnClickListener( View.OnClickListener { var height = etHeight.text.toString().toDouble() / 100.0 var weight = etWeight.text.toString().toDouble() var ans = String.format("%.2f", (weight / (height * height))) tvBmi.text = "BMI: " + ans }) } } ``` ### Intent(跳轉頁面) - 廣播系統 1. 先創建另一個activity->layout可將code改過去,記得要修正`tools:context=".LoginActivity">`。 2. manifests看哪個要設成首頁、起始頁,把intent 放進去`<activity><intent-filter>...</activity>`。 3. 在要移轉的地方,撰寫: 1. 宣告要跳轉的頁面,放入(目前的activity實體, 要跳轉的頁面.class),這邊還是要看之後要跳轉什麼決定放什麼參數。 ex: `intent(Context packageContext, class<?> cls)` * activity實體:lambda 可以只打this,如果是匿名內部類就要打類名.this。 * 要跳轉的activity.class:是用反射的方式幫你把class new出來。 2. `startActivity(intent)`:執行跳轉的動作。 3. `finish()`:再執行完跳轉後,把自己關掉->這裡只是告知系統我可以被關掉了,並不是真的自己結束,會等系統GC,如果沒有設定,那就代表剛打開的頁面,按下上一頁時會回到這裡(因為是stack)。 ```java= //1.宣告要跳轉的頁面 Intent intent = new Intent(LoginActivity.this, MainActivity.class); //目前這個intent 代筆著從login跳到main。 //2.執行跳轉的動作。 this.startActivity(intent); //跳轉到main //3.//把登入頁面關掉,但是要等到系統把它刪掉,他只是告知系統我沒用了 finish(); ``` 4. startActionMode: 是用來處理有需要背景控制的時候使用,可以設定要不要關掉前一個頁面等等的細節。 5. 跳轉頁面過去後會觸發該activity的onCreate()。 補充資料:[跳轉頁面帶值](https://www.itread01.com/p/1368293.html) --- ## 六、撰寫網路連線功能 1. 使用第三方套件OkHttp,核心在request。 2. 環境建置: 1. 用gradle 安裝OkHttp(Releases) ->放到deoendencies->會跳出小大象,案同步(Sync Now)及會安裝。`implementation("com.squareup.okhttp3:okhttp:4.9.0")` 2. 開啟網路權限:manifests->在manifest及application之間加入`<uses-permission android:name="android.permission.INTERNET" /> `、`<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />` 3. Request裡面的get.post,代表的是postman的get.post。 4. Client.newCall的enqueue - 非同步,異步,所以一定有Callback 才能知道要幹嘛; execute -同步,結束後在下一行,**基本上都要用enqueue,不然會錯誤**。 5. 使用方式: 1. ++創建request實體:設定url->get或post->build()。++ 2. 如果是get要走params,就在url直接加/:變數名稱/value即可;post看下方4.5。 3. ++運行request(記得要用enqueue)及撰寫其callback func(實現OkHTTP的Callback介面)++`client.newCall(request).enqueue(new Callback()...)` 1. `@NotNull`代表該值不能是null,不然就會報錯。 2. onFailure:如果連線失敗時,會把call傳回來,所以可以重試或做其他處理。 3. onResponce:成功時,會回傳結果回來,**`response.body().string()`:接收後端(Server)給的資料,但這個function一次請求就只能夠呼叫一次,第二次時就會報錯,所以一定要用一個變數存取下來。** 4. 如果是json格式,要再利用JSONObject轉成json物件後處理。 4. 如果是post -JSON版: 1. 先設置JSON的常數(MediaType JSON)`MediaType.get("application/json; charset=utf-8")`。 2. 利用java內建的JSONObject類取得json物件,輸入JSON內容後(put),會幫你轉成JSON物件。 3. 製作RequestBody,利用`create(jsonObject.toString,JSON)`,將json物件包裝成MediaType。 4. 放入post裡面。 5. JSON要用try...catch。 5. 如果是post - form-data版: 1. 不用設常數 2. 製作RequestBody,利用`RequestBody requestBody = new FormBody.Builder().(jsonObject.toString,JSON)`,用add將資料包成form-data。 4. 放入post裡面。 5. 不用try..catch 6. 如何選擇,就是看後端SERVER如何收取資料(Body的資料格式)。 6. ★基本上會開一類NetworkController,做成單例+橋接器模式:利用三個Interface + 一個中介層 + 一個靜態類別(實現Callback(OkHTTP的)但不一定,要看狀況決定。 ![](https://i.imgur.com/XfgIFEX.png) 7. NetworkController總結-請依照實際所需製作,格式不同、傳入、出的參數、interface做的事情都可能也不同: 1. 先做好導入OKHTTP的前置作業-皆在OKHTTP官方文件: 1. manifests要加入uses-permission(OKHTTP) 2. build.gradle要先導入OKHTTP 3. 設定常數(網路連線的Header) 2. 製作單例(因為enqueue,如果不用就不會在同個queue裡面): 1. 擁有靜態自己 2. 創建子 3. instance 3. 製作interface*3(傳失敗、成功、完成的function)分開做是為了可以寫成lambda。 4. 製作橋接器`CallbackAdapter`(用來將自己的Callback包裝成OKHTTP可以接受的Callback): 1. 實現OKHttp的Callback。 2. 擁有失敗、成功、完成的interface-到時候會由中介層傳入這個方法。 3. 寫好三階段要做的事情(這裡是指固定情況都必須要跑的事情,ex:送出錯誤資訊,response時再次確認自己伺服器上的錯誤代碼,是不是真的正確,因為OKHttp的response抓得很鬆-基本上只是看有沒有連成功。 4. 寫時要注意都要判斷是否null不然會程式掛掉。 5. 製作中介層`CallbackMiddle` - 實際上設定、呼叫方法的地方: 1. 擁有Request、失敗、成功、完成的interface。 2. Request為創建時擁有-設定(networkController)各項需求時會創建中介層。 3. 給外面(main)設定失敗、成功、完成方法,每個設定都回CALL自己(builder概念) 4. 最後使用他,`call.enqueue()`,會在括號內放入`new CallbackAdapter(三個interface)`,因為要先用橋接器幫他轉換成OKHTTP可以接受的Callback。 6. 撰寫API的內容: 1. 設定body的內容(如果是get不用設):`RequestBody x = FormBody.Builder()`用add放入內容,最後build()。 2. 設定request(路徑、token、資料-原本postman在做的事情),用Request的builder,url放網址,post(requestBody)/get,最後builder()。 3. 回傳給中介層。 7. 整個呼叫流程: 1. 在main呼叫.apiName後完全通過中介層操作。 2. 所以只需在NetworkController裡撰寫api(postman的設定)即可。 8. EX:須兼容JSONObject及JSONArray時,將onResponseInterface,改回傳出String,在外面撰寫時在決定他要被New什麼資料格式,然後做事情。 9. 最大重點就是要彈性的使用,一切都可能可以改變,要理解哪邊是為了要達到什麼功用而製作的。 8. 最小限制String 但也可能要直接傳Response 9. 傳入參數request,從OKHttp角度思考,在包裝一層,為了要吻合所有可能的api,因為為了符合我們自己的規範,才會製作networkcontroller。 補充資料:[OkHTTP](https://square.github.io/okhttp/)、[範例code-App-java-NetworkController](https://www.notion.so/Android-code-0abf76b0d303451c9f0bcc3995bd1ee7)、[網路連線權限](https://developer.android.com/training/basics/network-ops/connecting?hl=en) --- ### 橋接器設計模式 Adapter Pattern (Design Pattern) 1. 目的:是將A類別轉為B類別,使其可以給B類別用:建立一個可以被重複使用的類別,不管哪種input實現對應的轉接方法即可使用。 2. 使用時機:需要使用現有的類別但不符合系統所需時。 3. 實現方式一: 1. Adapter繼承A類並且實現轉換目標的方法。 2. 要轉換的目標只能是介面。 3. 不用A類別直接實現介面,是怕破壞A類別本身的結構。 4. 實現方式二(較優): 1. Adapter持有A類別,在實現目標方法。 2. 目標可以是介面或類別,彈性較高。 3. 可以隱藏A類別原有方法,避免被破壞封裝性。 5. 實現方式三: 1. 將Adapter做成抽象類別,並利用泛型來限制轉換輸入的類別範圍(抽象類別+泛型+實現目標方法介面-不寫實現,給繼承人寫)。 2. 使用者另創一類繼承Adapter並實現目標的方法。 --- ## 七、RecycleView ### 序-第一階段 1. 用來取代ListView所使用的套件,ListView不會回收View所以會很耗資源,因此資料有多長(顯示過),就會有多長。 2. 而RecycleView則會在上下各預留1~2個,如果完全超過畫面,就會把格子拿到上或下,更改裡面的資訊,在顯示,因此總長度就是畫面可顯示的長度+預留的個數,很省資源。 3. RecycleView本身是沒有放大縮小的功能,通常也不會有。 4. 示意圖: ![](https://i.imgur.com/JfdgGcI.png) 5. 後端要處理的分頁API,不管是下拉更多,或是按下一頁都是同樣概念。 6. 當使用RecyclerView,必須指定LayoutManager來指定顯示的模式,有三種Manager: 1. LinearLayoutManager(橫向/縱向的列表) 2. GridLayoutManager(方格式的列表) 3. StaggeredGridLayoutManager(瀑布流式的列表)-格子有大有小。 7. LinearLayout建構子有三種: 1. 預設:Context 2. 小更動:放入Context,方向(預設是垂直Vertical),boolean reverseLayout(是否要新資料放在上面,預設是false) 3. 自定義:99%不會用到。 4. Context 是 Activity的父類,跟使用者有交互的意思,使用上放this代表自己即可。 8. 自己寫的東西建議不要存context 因為很容易導致有指向,會沒辦法GC 9. 實現方法: 1. 先開立處理的類別(ProductListAdapter)繼承RecyclerView.Adapter<RecyclerView.ViewHolder>抽象類別,並實現其方法。 2. 在要放入RecycleView的Activity layout放入recycleview 3. 開立新的layour(item_list_product),改成LinearLayout,並設置上間距(這樣資料才會有間格),在放入一個textview(當作資料顯示區-格子樣式),也就是這個textview會把recycleview的每個item替換成這個格式。 4. 在類別中加入要做的資料庫,可以是任何集合。 5. onCreateViewHolder: 在畫面還沒超過前會跑的內容,主要功能是創建自己刻好的實體。 6. onBindViewHolder:畫面更新時要做的事情,在畫面滑動時、創建時、自己呼叫時會觸發(` ProductListAdapter.this.notifyDataSetChanged();//更新全部`、`ProductListAdapter.this.notifyItemChanged(getAdapterPosition());//單一個更新,會有內建動畫`。) 7. 創建自己的ViewHolder繼承RecycleView.ViewHolder, 8. 在要使用的地方,先設定LayoutManager的格式`LayoutManager lay = new 三種選一個(this)`,在對Layout(LinearLayout) `setLayoutManager()`。 9. 在創建ProductListAdapter,並設定adapter。 10. 如果要在不滑動的情況下更新畫面,可以把textview設定點擊事件,在用notify去更新數值(ArrayList裡的)。 11. 要開立該類別的Class,可以先在一開始放空的ArrayList進去Adapter後,最後在設定,設定完成後跑一次更新(`adapter.notifyDataSetChanged`)-ArrayList 及 Adapter的型態都應該是該class,而不是JSONObject等等 。 10. ViewHolder:是用來包裝View使用的,會有內建的方法。 11. ViewHolder會設成泛型是為了讓下方創建時可以不用多型向上,然後再更新時又要向下強轉型,可能會有問題,所以將工具設成泛型就不用強轉了。 12. viewholder可以拿到位置。 13. inflate viewGroup = view的集合,inflate的viewGroup就是他的爸爸。 ### 兩種ViewHolder 1. CommandAdapter、IType、BaseViewHolder、Factory 2. CardView 裡面只能放一個LinearLayout 補充資料:[context](https://spicyboyd.blogspot.com/2018/04/appcontext.html)、[LayoutInflater](https://spicyboyd.blogspot.com/2018/03/app-layoutinflater.html) --- ## 八、Dialog(彈出視窗) 1. popwindows 可自定義較高(ex:教學提示),dialogs則是會彈出在畫面中央,時間、日期選擇器(還是可以自定義,但會偏向用dialogsFragment)。 2. Button : 預設有確定、取消、其他,最多只能增加三顆,會預設右下角。 * Positive :確認按鈕 * NegativeButton:取消按鈕-預設會關閉視窗,不要的話就要自己傳view。 * Neutral:自定義功能按鈕。 3. dismiss預設是true(案其他地方就會關閉 4. 可以自定義setView,設定完後要: * show(先創建再顯示),每次返回時就會重新創建,較耗效能。 * create,先創建,之後要顯示時在該實體.show()即可<- 這個時候會判別是否已存在,有存在直接顯示(dialog的方法) ) 5. view可以傳id,但只能用於靜態資料-沒辦法設定行為事件,傳view才可以。 6. 有AlertDialog,比較多自行設定的內容以及 * TimePickerDialog 選擇時間 * DatePickerDialog 選擇日期 * 以上都可以設預設的時間、日期,目前會自動記憶,如果要清除就是讓他每次重建。 * 裡面都有個set的方法,如果有需要預設其他資訊、事件,就可以在此設定(也可以是空)。 7. 有用AlertDialog,inflate的viewgroup一定要設null,因為alertdialog會幫忙綁定,重複綁定會錯誤。 8. 關鍵字:Dialog、Dialogs、AlertDialog、AlertDialog.Builder、TimePickerDialog、DatePickerDialog 補充資料:[AlertDialog.Builder設定](https://developer.android.com/reference/android/app/AlertDialog.Builder) --- ## 九、SharedPreference與Intent_Bundle 1. SharedPreference 記錄使用者資訊用,紀錄較小的資訊(大約1.多MB),ex: 使用者密碼,如果是陣列盡量就用其他方式(如讀寫檔、資料庫)。 2. ★會在本地存資料,也就是在關閉app之後在打開時,都還是會保留資料!! 3. 創建是用`getSharedPreference(String(Key), MODE_PRIVATE)`。 4. 使用時一定要用editor才能修改資料,裡面就像HashMap,所以同樣的key值會被覆寫。 5. 寫完後一定要`commit`或`apply`,差別在: * commit: 在主執行緒做,因此可能延遲,但可以確保資料被正確存入、讀取。 ex:login * apply: 在副執行緒做,速度也不會太久,因此常用在登出功能及無須立即使用該值的時候。 6. 要取資料,先取得該Key的實體-跟2創建時同名,之後在用get資料型態(Key)拿取資料,像是JSONObject拿資料,ex:`getString("ACC")`。 ### Intent & Bundle 1. Intent可以用來在畫面間傳遞資訊-APP關閉資料就不會再了。 2. 利用Bundle包裝資料後`bundle.putString("TOKEN", token)`, 放到Intent傳給下一個畫面(本身還是可以傳很多型態)`.putExtras(bundle)`。 3. Bundle可以put很多類型,一樣是個Map,如果是要放已經包裝好的類(較複雜的資料),那就要讓類實現Parcelabe 或 Serializable,差別在於: * Parcelable:較複雜、需實現方法,但可自動產生,可以呼叫後,**填入資訊(要有資料怎麼存,跟怎麼轉回來的方法)**、但效能較好,且可以傳Array。 * Serializable:簡單、只要實現即可無須新增方法,但會怕寫檔,且效能較差。 4. 就算只有一個資料也是可以用Bundle包。 5. 收取上個場景傳到的資料,像是JSONObject拿資料: 1. 用Bundle(或你傳的型態)接收 `Bundle bundle = getIntent().getExtras()` 2. 再把資料取出: `String token = bundle.getString("TOKEN")` --- ## 補充知識JSON 1. 每間公司的資料格式都不一樣,要先確認格式,有無在用物件包裝,是否是陣列等等。 補充資料:[JSONPlaceholder(測試api資料庫)](https://jsonplaceholder.typicode.com/) ###### tags: `Android`、`CMoney7th-戰鬥營學習筆記`

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password
    or
    Sign in via Facebook Sign in via X(Twitter) Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    By signing in, you agree to our terms of service.

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully