第二行代碼學習總結 & 我遇到的BUG彙總

半年一更新,一更拖半年……前階段直至在“不踏實”地學習Android知識;跟了不少視頻,看了不少書;實際上學地都不踏實;直到今天徹底迷茫,不知道該怎樣“系統地”學習Android;我想那不如把前階段的收穫總結分享一下吧:

如果你從中有所收穫的話,請給我點個贊鼓勵下吧!😀

一、Android Studio導入現有工程的幾個步驟

這裏是參考的:“Android Studio導入現有工程的幾個步驟.”
概括以下四步:

  1. 根目錄下的 build.gradle裏定義了gradle tool的版本號;手動修改這裏的版本號爲當前支持的版本號:
  2. 根目錄下的gradle\wrapper裏的gradle-wrapper.properties文件修改爲自己的gradle配置中的zip包的版本;
  3. 最後修改一下app模塊下的build.gradle;對應的sdk的版本,build tool的版本號,以及一些依賴的jar包;
  4. 如果Android studio運行出錯 compilation failed see the compiler error output for details.;點擊下圖圈圈;切換一下顯示模式;就可以具體修改代碼中的錯誤;在這裏插入圖片描述

二、這裏推薦一篇好文

這篇文章裏有不少經驗分享和資料分享: Android小白學習成長路線.

三、四大應用組件之ContentProvider

不知道這裏爲什麼會有這篇經驗;如有侵權,請聯繫我立即刪除!

  1. 理解
    1). 爲會麼要有ContentProvider?
    在這裏插入圖片描述
    2). ContentProvider是什麼?
    在這裏插入圖片描述

  2. 相關API:

    1). ContentProvider: 內容提供者類
    在這裏插入圖片描述
    2). ContentResolver: 內容解析器類 :
    在這裏插入圖片描述
    3). Uri: 包含一個具有一定格式的字符串所對應資源的類
    在這裏插入圖片描述
    4). UriMatcher: 用來識別uri的一個uri容器
    在這裏插入圖片描述
    5). ContentUris: 操作uri的工具類
    在這裏插入圖片描述

  3. 自定義ContentProvider
    在這裏插入圖片描述

  4. 使用ContentResolver訪問ContentProvider
    在這裏插入圖片描述

  5. 應用練習

    1). 使用 ConentResolver 查詢得到所有聯繫人數據列表
    2). 使用 ListView + BaseAdapter 顯示列表
    3). 使用帶回調啓動 Activity 和帶結果的返回

四、Git

  1. 期間裏用一週時間瞭解了一下Git;
  2. 學習資料當然是“業界公認"的: 廖雪峯的官方網站.
    我打起了廣告?額……不管了,自己的學習總結而已;

五、View學習總結和BUG

  1. 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"中;去重方法 寫了;可是,每次打開軟件都是重新填充數據,而不會用到去重方法。.

  2. BUG :List 使用 add 方法時;List集合add方法覆蓋原來的內容 ;修改 用 addAll 複製得到的數據 arrayList 中 ,修改數據時,原數據也被修改;結果就是,最終添加的結果都一樣,全都是最後一次add的效果,<都是Java基礎不紮實的原因啊>
    a. 這是因爲,arrayList 的性質!如果元素是引用類型,保存的是引用,如果是值類型,保存的是值本身。這裏addAll 只是複製了地址,並非複製了全部的元素!同理,數據的add(),可以在set()前,也可在其後;
    b.解決方法:就是每次循環的時候,都把要添加的對象, new 一遍然後進行 set 等操作;如果元素是 值類型 ,那麼就不許重複 new 對象;
    c. 那麼如何複製 集合中的元素!還是老老實實的遍歷吧……

  3. 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 下

關於廣播接收器的註冊和銷燬

  1. 廣播接收器都是在 .onCreate() 中註冊,在 .onDestroy() 中銷燬;
  2. 但是本次實例,是要接受一個,強制下線的廣播,只需要保證:處在棧頂位置的活動能接收到廣播,非棧頂活動不需要接受;
  3. 所以本處用到了 activitycollect 和 BaseActivity 寫的十分巧妙;來看一下 activity 的生命週期在這裏插入圖片描述

八、一些小的注意事項

  1. 代碼順序,由上而下一定要有邏輯,.findViewById() 一定要先寫,不然程序閃退。

  2. 學習存儲的時候,因爲無法使用DDMS查看手機的文件,而大費周章,原來就在 AS右下邊有一個豎條形的鍵,就是打開文件存儲的快捷方式。

  3. manifest 中申請權限;一定要加 uses- uses- permission android:name=“android.permission.READ_CONTACTS”

  4. BUG :關於 String 判空

    錯誤: if (mResponseData.equals(null) || mResponseData.length() == 0) {
    正確: if (mResponseData == null || mResponseData.equals("")) {
    或者: if (!TextUtils.isEmpty(restoreText)) {
    
  5. 真機安裝 apk 失敗;在 gradle.properties 文件添加一句 android.injected.testOnly = false

  6. 真機(Android9)安裝後閃退:Failed resolution of: Lorg/apache/http/params/BasicHttpParams;;解決辦法:在AndroidManifest.xml 文件的 application 標籤下添加:<uses-library android:name="org.apache.http.legacy" android:required="false" />

  7. 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;
    
  8. 自定義控件使用:

    a. 編寫 title.xml 文件;
    b. 編寫自定義控件 類 在構造器中引入.xml
     	LayoutInflater.from(context).inflate(R.layout.title, this);
    c. 在需要引用自定義控件的 xml 中引用(LinearLayout);
    	<com.example.myapplication200122.TitleLayout
    				...
    
  9. 碎片的使用:

    a. 編寫佈局 fragment.xml; 
    b. 編寫碎片 類 ;.onCreate() 中使用 .inflate() 將碎片佈局引入;
      View view = inflater.inflate(R.layout.fragment, container, false);
    c. 在需要使用碎片的 xml 中使用:
        <fragment
            android:name="com.example.fragmenttest.LeftFragment"
                    ...
    
  10. View 和ViewGroup 的區別
    首件刪除了筆記,現場直編……

    1. 如果點擊事件出問題,不響應或者響應其他控件時;應該 檢查 xml 的佈局,是否控件被覆蓋;
    2. View 不能對其子空間進行操作,而 ViewGroup 可以,所以如果出現,動畫已經從頁面消失,而仍然響應點擊;可以考慮
      a. 把 View 更改成 ViewGroup ,然後遍歷其子控件,當子控件消失設置其不可點;
      b. 或者使用 屬性動畫(ObjectAnimator) 代替 值動畫;
  11. Android編譯出錯:app:checkDebugDuplicateClasses;檢查是不是依賴包重複了;

  12. 當我打不開“https://developer.android.com/reference/android/view/View.html”時;
    把".com" 換成".google.cn" 就可以了

  13. 導入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

  1. 先看代碼:

    報錯: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 文件中名稱不一致,找不到;

  2. 學習資源來自 郭神《第一行代碼Ⅱ》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 方法

  1. 介紹
    LayouInflater 中 inflate 方法兩個參數和三個參數
    LayoutInflater.from(RecylerActivity.this).inflate(R.layout.my_text_view,viewGroup,false);
    View.inflate(RecylerActivity.this, R.layout.my_text_view, null);
    
  2. 如果我們採用 convertView = inflater.inflate(R.layout.item_list, null);方式填充視圖,item佈局中的根視圖的layout_XX屬性會被忽略掉,然後設置成默認的包裹內容方式;
  3. 如果要保證item的視圖中的參數不被改變,我們需要使用convertView = inflater.inflate(R.layout.item_list, parent,false);進行填充;
  4. 除了這種方式,我們還可以設置item佈局的根視圖爲包裹內容,然後設置內部控件的高度等屬性,這樣就不會修改顯示方式。
    總之推薦用inflater.inflate(R.layout.item, parent, false);
    關於這節內容你應該是看不懂,推薦你看: inflate方法兩個參數和三個參數的區別;.

如果你從中有所收穫的話,請幫我點贊收藏分享鼓勵我吧!😀

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章