平時都會在印象筆記寫日報和週報,現在嘗試寫一寫月報,總結10月份的收穫與體會,具體的內容如下:
自我學習: 本月在工作之餘,學習了什麼知識
收穫體會: 本月在工作學習過程中,有哪些收穫或者感悟體會,有哪些優秀點,繼續堅持。
待改進的地方: 本月工作學習過程中,有哪些地方做的不好,以後需要改進。
自我學習
學習清單
- 1、Glide學習
- 2、完成《第一代碼》(第2版)的重溫,用Kotlin寫書中例子
- 3、JAVA多線程——線程安全之原子性,有序性和可見性
- 4、實現勻速加載的進度條的方法
- 5、學習單元測試
- 6、學習Flutter
1、 Glide學習
主要跟着郭霖的Glide專欄系列學習,最後自己總結輸出一篇博客
2、 完成《第一代碼》(第2版)的重溫,用Kotlin寫書中例子
在寫kotlin時印象較深的地方有
- 沒有Java的switch,Kotlin用when代替
例如
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
when (item?.itemId) {
android.R.id.home -> {
mDrawerLayout?.openDrawer(GravityCompat.START)
}
R.id.backup -> {
Toast.makeText(this, "You clicked Backup", Toast.LENGTH_SHORT).show()
}
R.id.delete -> {
Toast.makeText(this, "You clicked Delete", Toast.LENGTH_SHORT).show()
}
R.id.setting -> {
Toast.makeText(this, "You clicked Setting", Toast.LENGTH_SHORT).show()
}
}
return true
}
- 多用Kotlin的內聯函數美化代碼,如
let
、run
、apply
等等
let
:函數塊用it指代該對象,返回值是函數塊的最後一行
run
: 函數塊不需要it,返回值是函數塊的最後一行
apply
: 函數塊不需要it,返回值是傳入對象的本身 (多用於初始化實例賦值)
推薦閱讀: Kotlin系列之let、with、run、apply、also函數的使用
- Kotlin的數組表示
val fruits: Array<Fruit> = arrayOf(
Fruit("Apple", R.drawable.apple),
Fruit("Banana", R.drawable.banana))
或者
var fruitList = ArrayList<Fruit>()
3、JAVA多線程——線程安全之原子性,有序性和可見性
-
原子性:指操作是不可分的,如a++操作,實際是取a、++、賦值a三個操作,這三個操作要不可分。
-
可見性:指一個操作執行的結果需要對另一個操作可見,即緩存、主內存同時改變(參考下面推薦文章的內存模型圖)。使用volatile關鍵字實現
-
有序性:指程序的代碼執行順序和語句的順序是一致的。
這是因爲在Java內存模型中,允許編譯器和處理器對指令進行重排序,
但是重排序過程不會影響到單線程程序的執行,卻會影響到多線程併發執行的正確性。
推薦閱讀: JAVA多線程——線程安全之原子性,有序性和可見性
4、實現勻速加載的進度條的方法
方法(1):使用Timer實現網頁勻速加載的進度條
參考 https://blog.csdn.net/qq_33589836/article/details/54616262
方法(2):使用Timer實現網頁勻速加載的進度條
private static final int DURATION_TIME = 2000;
private int mCurrentProcess = 0;
private void startFakeProgress() {
ValueAnimator anim = ValueAnimator.ofInt(0, 90);
anim.setDuration(DURATION_TIME);
anim.setInterpolator(new AccelerateInterpolator());
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int progress = (int) animation.getAnimatedValue();
if (progress > mCurrentProcess) {
mCurrentProcess = progress;
getView().updateDownloadDialog(progress);
}
}
});
anim.start();
}
5、學習單元測試
- 如何創建測試類
可以自己手動在相應目錄創建測試類,AS也提供了一種快捷方式:
選擇對應的類->將光標停留在類名上->按下ALT + ENTER->在彈出的彈窗中選擇Create Test
- 如何在測試類中獲取Context
如果要獲取Context,那麼需要加儀器化測試,可以採用常用單元測試開源庫Robolectric 配置如下
(1)在app model添加配置
android {
...
testOptions {
unitTests {
includeAndroidResources = true
}
}
}
dependencies {
...
testImplementation "org.robolectric:robolectric:3.8”
}
(2)在app/src/test/java/添加這個類,後續類可以繼承這個類,然後調用getContext
@RunWith(RobolectricTestRunner.class)
@Config(manifest = Config.NONE, application = Application.class)
public abstract class RoboBase {
protected Context getContext() {
return RuntimeEnvironment.application;
}
}
推薦閱讀: Android單元測試只看這一篇就夠了
6、學習Flutter
跟着Flutter官網學習
官網:https://flutter.io/get-started/install/
自己輸出一篇博客:Flutter的安裝與使用
收穫體會
1、完成項目先保證整體流程的完成。怎麼算整體流程?即大部分用戶、大部分機型的可用性。
爲什麼呢?因爲Android的版本很多、各個廠商偶爾還有定製,所以如果糾結太多細節,忽略整個流程的完整度,那麼會導致自己完成項目的效率變慢(直觀看,就是做需求太慢)。
以前自己爲了追求完美,每個細節都追究,結果費力不討好,甚至深陷泥潭,需求開發慢,還加班很晚。這種情況就本末倒置了,只見樹葉不見森林。
因此,以後自己先把握整體進度,完成整體需求框架。如果有細節問題,先記錄下來,等開發完整體流程,再解決細節問題。
2、一個人精力是有限的,晚上很晚回家,就沒有太多精力做其他事情,即便想做,注意力也不集中,還不如早早休息,或者簡單看書。
3、做好一件事件需要時間,比如寫博客,需要一點點完善補充,急不來。也需要自己平時一點點寫。
4、某晚又加班太晚,主要是因爲發版前排查一個問題,最終也沒有什麼結論,停止發版,第二天再發版。
很多事情都無法預測,計劃趕不上變化,想做什麼事情都需要提前做,遇到突發情況就要推遲了。
5、讀完《碼農翻身》,受益匪淺,做了一些摘錄
教訓:讀書太多,而實踐太少
吸取教訓:不僅看書,還去讀JUnit源碼、Spring源碼、Hsqldb源碼、Jive源碼,再加上工作寫的大量代碼
凡事必先騎上虎背,勇敢地邁出去,努力地爭取一下,你就會發現自己登上了更高一層的臺階。逼着自己趕緊進入未知領域,拼命地去學。
養成計算機的思維方式,這個基本功的訓練就是數據結構和算法,劉欣老師的經驗是多做習題,讓這種思維在腦子裏固化,以後的編程就可以信手拈來。
計算機的組成原理、操作系統、編譯原理、計算機網絡、數據庫、彙編語言等等,融會貫通
停下來,思考,纔是進步的本質。
寫出漂亮代碼並不容易,需要思路清晰,有良好的編程基礎,有優秀的抽象能力,以及對一門語言的熟練掌握。
每一個季度定一個小目標,努力達成,獲得成就感,就能刺激自己更進一步。
6、看生老闆的優化分支,體會良多,這就是跟老闆的差距,老闆嘗試不少實踐,想必老闆的技能又提升不少,實踐見真理。
7、終於把以前遺留的一個問題解決了。
出現問題還是一樣解決方式,先分析問題,比如這次是加載慢的問題,那麼需要找出耗時的地方。
剛開始不確定哪裏比較耗時,那麼只能打log來定位。然後不斷縮小範圍,找到最耗時的地方,比如這次是獲取錢包數據時的Json解析耗時。
這個操作大概20ms,而且是在循環裏,有近1000次循環,意味20秒。找到根源,可以把耗時操作放在循環外,減少不必要的耗時操作。
8、堅持解決問題的方法論,避免焦躁,分析問題,找出可能的原因,逐一驗證。
9、主動性,主動跟蹤問題,雖然有些問題不是自己造成,但是自己主動去查找,從錯誤中學習。
10、問題跟到底,針對問題打破砂鍋問到底,跟蹤問題的根本原因,從中學到不少東西。
例如,有一個空指針問題,正常加個判null就行,但是需要找原因,爲什麼會產生null指針,如下最後一行token.getData()空指針
List<Token> tokenList = coinInfo.getTokens()
if(tokenList == null) {
return;
}
for(Token token: tokenList) {
TokenData data = token.getData();
}
正常token不爲null,除非list add一個空對象,或者什麼場景導致tokenList有數據,但讀取其中一個數據時token爲空
經排查,發現存在多線程操作,在另外一個線程中存在CoinInfo.addToken,而且沒有加鎖。
在併發情況,可能導致tokenList的size+1,但是數據還沒有添加進去,這時候線程切換時就獲取token爲空。
因此根本解決方法不是加判null處理,而是在addToken時加鎖同步
反思:以後在List add數據時,注意有沒有多線程問題,如有記得加同步,因爲ArrayList的add方法不是線程安全
待改進的地方
1、提高晚上工作的效率。
後續改進:晚上加班很晚的時候,需要評估工作量,不要做太多無所謂的工作,晚上多留些時間給自己充電。
2、提前完成任務,提高計劃執行力。週末因爲一些臨時突發事情,導致事情沒有完成,要推遲。
後續改進:把一些任務提前完成,避免突然情況。
3、某周學習內容比較雜,還是一件一件來好。
後續改進:先專心完成一件事件,再去做另一件事件。
4、時間安排不夠合理,比如週五調休,出去拍景後回家修圖太久,而且晚上只學習了一會(看漫威電影了)。前幾天一直在學習,到週五就放鬆過頭了。
後續改進:以後安排好時間,持續學習,延遲滿足感。