前階段的Android學習總結
半年一更新,一更拖半年……前階段直至在“不踏實”地學習Android知識;跟了不少視頻,看了不少書;實際上學地都不踏實;直到今天徹底迷茫,不知道該怎樣“系統地”學習Android;我想那不如把前階段的收穫總結分享一下吧:
如果你從中有所收穫的話,請給我點個贊鼓勵下吧!😀
一、Android Studio導入現有工程的幾個步驟
這裏是參考的:“Android Studio導入現有工程的幾個步驟.”
概括以下四步:
- 根目錄下的 build.gradle裏定義了gradle tool的版本號;手動修改這裏的版本號爲當前支持的版本號:
- 根目錄下的gradle\wrapper裏的gradle-wrapper.properties文件修改爲自己的gradle配置中的zip包的版本;
- 最後修改一下app模塊下的build.gradle;對應的sdk的版本,build tool的版本號,以及一些依賴的jar包;
- 如果Android studio運行出錯 compilation failed see the compiler error output for details.;點擊下圖圈圈;切換一下顯示模式;就可以具體修改代碼中的錯誤;
二、這裏推薦一篇好文
這篇文章裏有不少經驗分享和資料分享: Android小白學習成長路線.
三、四大應用組件之ContentProvider
不知道這裏爲什麼會有這篇經驗;如有侵權,請聯繫我立即刪除!
-
理解
1). 爲會麼要有ContentProvider?
2). ContentProvider是什麼?
-
相關API:
1). ContentProvider: 內容提供者類
2). ContentResolver: 內容解析器類 :
3). Uri: 包含一個具有一定格式的字符串所對應資源的類
4). UriMatcher: 用來識別uri的一個uri容器
5). ContentUris: 操作uri的工具類
-
自定義ContentProvider
-
使用ContentResolver訪問ContentProvider
-
應用練習
1). 使用 ConentResolver 查詢得到所有聯繫人數據列表
2). 使用 ListView + BaseAdapter 顯示列表
3). 使用帶回調啓動 Activity 和帶結果的返回
四、Git
- 期間裏用一週時間瞭解了一下Git;
- 學習資料當然是“業界公認"的: 廖雪峯的官方網站.
我打起了廣告?額……不管了,自己的學習總結而已;
五、View學習總結和BUG
-
ListView
- 設置一個ListView並找到;
- 初始化數據(把數據裝到集合裏);
- 數據設置到adapter中;
- adapter 又設置給ListView;
- 難點在於自定義adapter;
a. 自定義adapter繼承與ArrayAdapter<或BaseAdapter>;併產生其構造器;
b. 重寫 .getView() ;此時 ListView 中每一個項目可用 .getItem() 獲得;
c. 其中重寫了一個 ViewHolder 類;
d. 難點 在於兩步優化和 .getView() 的理解。 - BUG:判斷 ArrayList 中是否爲空;絕不能用
mFruitList == null;
要用 mFruitList.size() == 0 代替
疑問:"com/example/listviewtest/FruitActivity.java:25"中;去重方法 寫了;可是,每次打開軟件都是重新填充數據,而不會用到去重方法。.
-
BUG :List 使用 add 方法時;List集合add方法覆蓋原來的內容 ;修改 用 addAll 複製得到的數據 arrayList 中 ,修改數據時,原數據也被修改;結果就是,最終添加的結果都一樣,全都是最後一次add的效果,<都是Java基礎不紮實的原因啊>
a. 這是因爲,arrayList 的性質!如果元素是引用類型,保存的是引用,如果是值類型,保存的是值本身。這裏addAll 只是複製了地址,並非複製了全部的元素!同理,數據的add(),可以在set()前,也可在其後;
b.解決方法:就是每次循環的時候,都把要添加的對象, new 一遍然後進行 set 等操作;如果元素是 值類型 ,那麼就不許重複 new 對象;
c. 那麼如何複製 集合中的元素!還是老老實實的遍歷吧…… -
BUG
Android報錯:Attempt to invoke virtual method 'boolean java.lang.String.equals(java.lang.Object) Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.String.equals(java.lang.Object)' on a null object reference
解決方法:
1. 根據提示找到出錯行;
2. xml 佈局文件中,id不能大寫;
3. 資源名不能大寫!
4. 控件名稱首字母要大寫:< V iew
5. View劃橫線:用的是 background如果你從中有所收穫的話,請給我點個贊吧!😀
六、fragment 和 Framelayout
學習資源來自 郭神《第一行代碼Ⅱ》4.2.2 動態加載碎片 P148
原圖如下(注意右邊半拉):
設置了點擊事件,當點擊button時,會動態載入碎片:
main_activity.xml 使用 <FrameLayout 佈局時,得到的是正常的結果:
如果使用 fragment 碎片;得到的結果沒有用新界面完全代替就界面,如下:
原因:
a. 因爲默認的這層 right_fragment,使用的 linear layout 填充的,而這個layout裏面只有一個text view,當你設置的點擊事件直接使用碎片 fragment ,來動態加載碎片時,就只能在這個textview之下。
b. 要想動態加載碎片,就必須用另一個 FrameLayout 替換 LinearLayout,而後往 layout 中填充碎片。到此問題解決。
七、關於廣播接收器的註冊銷燬
學習資源來自 郭神《第一行代碼Ⅱ》5.5 最佳實踐 P190 下
關於廣播接收器的註冊和銷燬
- 廣播接收器都是在 .onCreate() 中註冊,在 .onDestroy() 中銷燬;
- 但是本次實例,是要接受一個,強制下線的廣播,只需要保證:處在棧頂位置的活動能接收到廣播,非棧頂活動不需要接受;
- 所以本處用到了 activitycollect 和 BaseActivity 寫的十分巧妙;來看一下 activity 的生命週期
八、一些小的注意事項
-
代碼順序,由上而下一定要有邏輯,.findViewById() 一定要先寫,不然程序閃退。
-
學習存儲的時候,因爲無法使用DDMS查看手機的文件,而大費周章,原來就在 AS右下邊有一個豎條形的鍵,就是打開文件存儲的快捷方式。
-
manifest 中申請權限;一定要加 uses- uses- permission android:name=“android.permission.READ_CONTACTS”
-
BUG :關於 String 判空
錯誤: if (mResponseData.equals(null) || mResponseData.length() == 0) { 正確: if (mResponseData == null || mResponseData.equals("")) { 或者: if (!TextUtils.isEmpty(restoreText)) {
-
真機安裝 apk 失敗;在 gradle.properties 文件添加一句
android.injected.testOnly = false
-
真機(Android9)安裝後閃退:
Failed resolution of: Lorg/apache/http/params/BasicHttpParams;
;解決辦法:在AndroidManifest.xml 文件的 application 標籤下添加:<uses-library android:name="org.apache.http.legacy" android:required="false" />
-
java生成隨機數有兩種方法:
1、使用Math方法, int num = (int) (Math.random() * 15); (int) (Math.random() * num) //生成的是 0 ~ num-1 (int) (Math.random() * num + 1) //得到的是 1 ~ num 2、使用Random方法, Random random = new Random(); int length = random.nextInt(20) + 1;
-
自定義控件使用:
a. 編寫 title.xml 文件; b. 編寫自定義控件 類 在構造器中引入.xml LayoutInflater.from(context).inflate(R.layout.title, this); c. 在需要引用自定義控件的 xml 中引用(LinearLayout); <com.example.myapplication200122.TitleLayout ...
-
碎片的使用:
a. 編寫佈局 fragment.xml; b. 編寫碎片 類 ; 在 .onCreate() 中使用 .inflate() 將碎片佈局引入; View view = inflater.inflate(R.layout.fragment, container, false); c. 在需要使用碎片的 xml 中使用: <fragment android:name="com.example.fragmenttest.LeftFragment" ...
-
View 和ViewGroup 的區別
首件刪除了筆記,現場直編……- 如果點擊事件出問題,不響應或者響應其他控件時;應該 檢查 xml 的佈局,是否控件被覆蓋;
- View 不能對其子空間進行操作,而 ViewGroup 可以,所以如果出現,動畫已經從頁面消失,而仍然響應點擊;可以考慮
a. 把 View 更改成 ViewGroup ,然後遍歷其子控件,當子控件消失設置其不可點;
b. 或者使用 屬性動畫(ObjectAnimator) 代替 值動畫;
-
Android編譯出錯:
app:checkDebugDuplicateClasses
;檢查是不是依賴包重複了; -
當我打不開
“https://developer.android.com/reference/android/view/View.html”
時;
把".com" 換成".google.cn" 就可以了 -
導入GitHub上項目報錯:
Could not resolve all dependencies for configuration ':app:debugRuntimeClasspath'
在根目錄下 build.gradle 文件中,加上 “google() mavenCentral()” 寫成:
buildscript { repositories { jcenter() google() mavenCentral() } allprojects { repositories { google() jcenter() mavenCentral() } }
九、數據庫學習中遇見的BUG
-
先看代碼:
報錯:org.litepal.exceptions.DatabaseGenerateException: can not find a class named com.coolweather.android.db.Province 問題在於:數據庫知識掌握不紮實;litepal.xml 文件中結構。如此 stupid 問題…… <litepal> <dbname value="cool_weather" /> <version value="1" /> <list> <mapping class="com.example.coolweather.db.Province" /> //放數據庫所在 包名 <mapping class="com.example.coolweather.db.City" /> <mapping class="com.example.coolweather.db.County" /> </list> </litepal>
這是因爲數據庫中定義的名稱和 .java 文件中名稱不一致,找不到;
-
學習資源來自 郭神《第一行代碼Ⅱ》14.5.3 將天氣顯示到界面上 P520
報錯:Attempt to read from field 'java.lang.String com.example.coolweather.gson.Basic.cityName' on a null object reference java.lang.NullPointerException: Attempt to read from field 'java.lang.String com.example.coolweather.gson.Basic.cityName' on a null object reference
這是因爲:在JSON中的一些字段可能不太適合直接作爲java字段來命名,因此使用了 @SerializedName 註解的方式來讓JSON 字段和Java字段之間建立映射關係;而JSON的數據是鍵值對的格式存在的,我們在Json格式文件中寫的 鍵,和java文件中的取值 鍵 不對應;所以無法獲取到對應的值。
十、inflate 方法
- 介紹
LayouInflater 中 inflate 方法兩個參數和三個參數 LayoutInflater.from(RecylerActivity.this).inflate(R.layout.my_text_view,viewGroup,false); View.inflate(RecylerActivity.this, R.layout.my_text_view, null);
- 如果我們採用
convertView = inflater.inflate(R.layout.item_list, null);
方式填充視圖,item佈局中的根視圖的layout_XX屬性會被忽略掉,然後設置成默認的包裹內容方式; - 如果要保證item的視圖中的參數不被改變,我們需要使用
convertView = inflater.inflate(R.layout.item_list, parent,false);
進行填充; - 除了這種方式,我們還可以設置item佈局的根視圖爲包裹內容,然後設置內部控件的高度等屬性,這樣就不會修改顯示方式。
總之推薦用inflater.inflate(R.layout.item, parent, false);
關於這節內容你應該是看不懂,推薦你看: inflate方法兩個參數和三個參數的區別;.
如果你從中有所收穫的話,請幫我點贊收藏分享鼓勵我吧!😀