主頁 > 移動端開發 > Android瘋狂講義前10章知識點總結

Android瘋狂講義前10章知識點總結

2021-01-04 11:42:32 移動端開發

Android瘋狂講義前10章知識點總結

/-------------------------10-31號晚上學習筆記----------------------------/
在設定了最小支持版本為18及以上的時候,需要將獲得actionBar組件的包參考改為
import androidx.appcompat.app.ActionBar; 即可,

2.11.3:啟用程式圖示導航:
已實作

2.11.4:添加ActionView組件:

有些時候只可以使用監聽事件處理機制

3.2基于監聽的事件處理:
控制飛機移動實體實作:
邏輯:{
1.先創建一個飛機畫圖的view類
2.然后再mainActivity中創建一個內部類作為監聽器
3.為飛機的view物件設定監聽器實作對用戶手勢的監聽
}

實作對于事件監聽的監聽器的設定方式:{
內部類
外部類(該監聽器主要被很多GUI界面共享)
mainActivity實作監聽器介面
使用Lambda運算式實作監聽器
}

如果確實有多個監聽器需要同一個業務邏輯組件,那么我們可以將這些業務邏輯
使用業務邏輯組件進行定義

3.2.5中Activity本身作為事件監聽器類{
該種方法出現的問題:{
1.會造成程式結構的混亂(因為Activity類主要是用來初始化頁面)
2.會覺得比較怪異
}
}

3.2.6 Lambda運算式作為事件監聽器類:{
使用原因:
大部分的事件監聽器沒有復用價值(因為可以復用的都設定為事務邏輯組件)

實際上Lambda運算式時目前使用最為廣泛的監聽器的實作形式:{
實作形式:
textView.setOnClickListener(view -> show.setText(“xxx”));

}

}

直接系結到標簽:{

}

基于回呼的事件處理:{
機制可以通過自定義View來實作,自定義View時重寫該view的事件處理方法即可
此時的事件處理還是事件源本身來進行的
}

基于監聽的事件處理中,事件源和事件處理是分開的,

3.3.2-基于回呼的事件傳播:{
如果事件處理的回傳值是:true 表示該事件不會進行傳播;
如果事件處理的回傳值是:false 表示該事件會進行傳播;

事件可以進行傳播的情況下-觸發事件的順序是:{
1.自定義組件中實作的監聽器內容
2.給組件注冊的監聽器中的內容
3.該組件所在的activity中的OnTouchEvent()方法中
}
}

3.4 回應系統設定的事件:{
3.4.1 Configuration 類{
作用:專門用于描述手機設備上的配置資訊{包括的是用戶特定的配置項和系統的動態配置項}
實體:獲取系統設備狀態{
實作步驟:{
第一步:獲取系統當前的Configuration物件
第二步:呼叫Configuration物件的屬性來獲取設備狀態
}
}
}
}

重寫onConfigurationChanged()方法回應系統設定更改:

重點:Handler訊息傳遞機制{
作用:處于對性能的優化,安卓的UI操作并不是執行緒安全的,這意味著如果有
多個執行緒并發操作UI組件,有可能導致的執行緒安全問題,為了解決的這個問題,使用了
handler處理機制,

在啟動主執行緒的時候,即是UI界面只可以被主執行緒修改,但是后期也會繼續
對UI界面進行修改,那么就需要使用Handler事件處理機制

handler類的作用主要有兩個:{
1.在新啟動的執行緒中發送訊息
2.在主執行緒中獲取、處理訊息
}

實體:實作自動播放的影片
}

一個執行緒對應的是一個Looper()物件
在執行緒中使用Handler的步驟如下:
{
1.呼叫Looper的perpare()方法為當前執行緒創建Looper物件,創建Lopper物件的時候
它的構造器會創建與之配套的MessageQueue();
2.有了Looper之后,創建Handler子類的實體,重寫handlemMessage()方法,
該方法負責處理來自其他執行緒的訊息
3.呼叫Looper()的loop()方法啟動Looper
}

//實體:使用執行緒計算質數
(使用另外一個執行緒計算的原因是:否則會導致ANR例外)

重點:不要在UI界面中引入一些過多的操作

3.6 使用異步任務{
AsyncTask實作呼叫的時候需要的是系統進行呼叫
實體:使用異步任務執行下載
}

截止到:234/767(電子版)

/-----------------------------2020-12-15號下午學習筆記-------------------------------/

第四章學習筆記:

使用activity繼承自LauncherActivity實作的是整個activity作為一個串列實作渲染,

android應用要求所有的應用程式組件都必須顯式進行配置
使用bundle在Activity之間交換資料
bundle是一個簡單的資料攜帶包 該bundle物件包含了多個方法來存盤資料{
putxxx()
putSerializable()
}等

intent中的提供的putExtra()方法以及向intent中存盤資料其實還是用的bundle中的資料
如果呼叫以上的方法時,intent中沒有bundle物件,那么就創建一個bundle物件
//截止到2020-12-15日下午 16:02學習筆記

2020-12-15日晚上學習筆記:
4.2Activity回呼機制:
Activity中的回呼和web中的回呼是類似的
程式架構中的點:可以是介面形式存在也可以是抽象方法實作(后者就是Activity中的呼叫機制的實作方法)
回呼實作的第一種實作方式就是典型的命令者模式
當前活動的Activity在堆疊頂
在onStart()方法之后一定會回呼onResume()方法

Activity中的資料展示是由UI組件搭建而成的,但是Servlet中的資料的顯示是由瀏覽器直接生成的

Android采用Task對多個Activity進行管理
當啟動應用的時候Android會自動創建一個Task,然后是啟動應用的入口Activity(也就是在intent-filter和zoo那個配置為
MAIN和LAUNCHER的Activity

開發者無法真正訪問Task(因為Android并沒有為Task組件提供一個介面)
但是可以通過所在的Activity中使用getTaskId()獲得其對應的Task的Id,

先啟動的Activity放到堆疊底然后后啟動的放到堆疊頂

Android中的幾種啟動方式:
{
standard:表示的是每一次啟動的時候只有一個Task也就是說后來啟動的都是直接覆寫到原來的Task上(但是會產生很多的實體)
singleTop模式:表示的是基本上和standard差不多,有區別的地方在于:當將要創建的Activity在堆疊頂的時候,
系統就不再創建一個新的實體
singleTask模式:采用的singleTask這種加載模式的Activity能保證在同一個Task中只有一個實體,當系統采用這種模式的時候
分為三種情況:
{
1.如果將要啟動的目標Activity不在,系統將會創建目標Activity的實體,并將它加入Task堆疊頂
2.如果已經位于堆疊頂,那么此時與singleTop模式的行為相同
3.如果是已經存在但是沒有在堆疊頂,那么系統會將所有的Acticity移除堆疊頂從而使得目標的Activity在堆疊頂
}
}

singleInstance模式:
{
采用本模式的時候,無論系統從哪個Task啟動目標Activity,只會創建一個目標Activity實體,并會使用一個全新的
Task堆疊來加載該Activity實體

并且采用本模式的時候有兩種情況:
{
1.如果目標不存在,系統會創建一個全新的task并創建一個Activity并將它加入到新的task的堆疊頂
2.如果已經存在,那么系統都會把它調出來放到前臺
}
}

需要說明的是采用singleInstance的模式創建Activity時,一個Task只包含一個Activity
設定xml檔案中的加載模式的同時需要設定的是exported="true"對應的是:表示該Activity可以被其他應用啟動

4.5 Android 0 升級的Fragment:
Fragment擁有自己的生命周期,并且也可以接受它自己的輸入事件

Fragment必須被嵌入到Activity中使用(就說明:Fragment自身的生命周期也會受到Activity的控制)
也就是說只有當Activity活動的時候,程式員才可以對其中的fragment進行操作

通常來說,創建Fragment類的時候需要實作的方法是:
{
1,onCreate()方法
2.onCreateView()方法(當Fragment繪制組件的時候回呼該方法,該方法回傳的一個View表示該Fragment顯示的View)
3.onPause()方法
}

創建一個對應的ListFragment類,無需重寫onCreateView()方法

對于需要添加一個Fragment組件的Activity組件也需要繼承自support-fragment下面的FragmentActivity
否則會出現錯誤,

實作大屏顯示圖書詳情fragment邏輯(自己總結):
首先先創建一個BookListFragment類(其中定義了一個interface介面,然后在Main2Activity中實作對應的callBacks介面,
在介面中實作的是對應于該特定Activity下的顯示邏輯,那就是將來在BookDetailFragment中顯示資料的傳遞邏輯(使用的是)
Bundle + setArguments() + getSupportFragmentManager().beginTransaction().replace(R.id.book_detail_container, bookFragment).commit();)
這里重點說明一下:對于callBacks介面來說,不同的Main2Activity下,有不同的實作邏輯,
然后是,每一次在點擊了Main2Activity中的左邊的listFragment中的項之后,都會在右邊的detailfragment中的onCreate()方法
從而實作對于資料的更新,
對于listFragment來說,直接在Main2Activity中的xml檔案中第一次渲染的時候就呼叫了對應的onCreate()方法,

/------------------------12-16號晚上學android學習筆記--------------------------/
page 268回顧筆記:
在Activity中使用fragment的時候可以使用id或者是tag屬性來標記fragment物件

4.5.4 fragment管理與fragment事務:
fragmentManager物件可以實作的功能是:{
1.使用findFragmentById()方法或者是findFragemntByTag()方法可以獲得
在該Activity中系結的Fragment組件
2.使用popBackStack()方法獎Fragment從后臺彈出,模擬用戶按下back回傳鍵的情形
3.使用addOnBackStackChangeListener()注冊一個監聽器,用于監聽后臺堆疊的變化
}

需要添加 洗掉 替換 Fragment物件可以使用的是FragmenTransaction物件
(該物件代表的是Activity對Fragment執行的多個改變)

在使用事務物件commit之前,可以使用addToBackStack()方法將該事務物件添加到backStack
中,然后當用戶按下回退的時候,直接回傳的是上一個fragment的狀態

實體:開發兼顧螢屏解析度的應用
為了實作這個目的可以在res/目錄下為大螢屏,600dpi的螢屏建立相應的
資源檔案夾:values-large,values-sw600dp,在該檔案夾下建立一個名為
refs.xml的參考資源檔案,
該資源檔案專門用于定義各種參考項,

實作上述目的的邏輯(自我總結):
首先在res/目錄下面創建一個values-large檔案夾,里面創建一個資源物件主要是用來存放對應資源檔案

<?xml version="1.0" encoding="utf-8"?> @layout/activity_main2 然后在Main2Activity中的onCreate()方法中使用if陳述句判斷當前布局界面是否包含container,如果是, 就表明是大螢屏顯示,此時出現的listFragment是存在于activity_main2.xml中的booklist檔案(此時還需要設定 此時的book_list組件時單選模式,用來實作大屏顯示的效果(即:左邊點擊右邊顯示詳情)) 對于Main2Activity中的實作的onItemSelected()方法來說,需要判斷是否是大屏顯示,如果是和原來的邏輯一樣 如果不是大屏顯示,那么需要在點擊了對應的list之后跳轉到對應的bookDetailActivity中,用來實作詳情的顯示, 在BookDetailActivity的onCreate()方法中,使用如下陳述句來創建新的顯示詳情的bookDetailFragment物件 if(savedInstanceState == null){ //創建BookFragment物件 BookDetailFragment bookDetailFragment = new BookDetailFragment(); //創建Bundle物件 Bundle bundle = new Bundle(); bundle.putInt(BookDetailFragment.ITEM_ID, getIntent().getIntExtra(BookDetailFragment.ITEM_ID,0));
        //向Fragment傳入引數
        bookDetailFragment.setArguments(bundle);
        //將指定fragment添加到book_detail_container容器中
        getSupportFragmentManager().beginTransaction()
                .add(R.id.book_detail_container,bookDetailFragment).commit();
    }

并在其中實作了對應的actionBar點擊之后的時間方法邏輯:
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {

    if(item.getItemId() == android.R.id.home) {
        //創建啟動的MainActivity的Intent
        Intent intent = new Intent(this,Main2Activity.class);
        //添加額外的Flag,獎Activity堆疊中處于Main2Activity之上的Activity彈出來
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        //啟動intent對應的Activity
        startActivity(intent);
        return true;
    }
    return super.onOptionsItemSelected(item);
}

至此,根據螢屏大小實作不同的顯示的邏輯得以實作,

//截止到2020-12-17日凌晨(0:45)
截止到(270)

/**------------------------------2020/12/20號下午學習筆記-----------------------------*/
Fragement生命周期:
其中的onAttach()、onCreate()等,方法在該fragment被加入到對應的activity中的時候只會別呼叫一次,
onCreateView()方法在每一次被回呼的時候創建一次,

最常用的是就是onCreateView()方法,

4.7管理Fragment導航
Android的support-fragment中下提供了一個ViewPager組件,該組件非常方便實作分頁導航,
ViewPager只是一個容器組件,其中顯示的內容可由Adapter進行提供,
{其中使用的PageAdapter和FragmentPageAdapter子類(該子類是專門用于管理多個Fragment的)}

實體:結合ViewPager實作分頁導航,
實體:結合TabLayout實作Tab導航,

由于tablayout需要appcompat主題的支持,需要設定實體的主題是dark.actionbar

//第5章:使用intent和IntentFilter通信
使用intent提供了一致的編程模型,并且可以降低耦合,
這里的Intent有點類似于spring、sprngMVC中的邏輯視圖名的設計,
Android中包含三種重要的組件:
{
Activity
Service
BroadcastReceiver
}

//5.2 Intent的屬性和intent-filter配置
1.Component屬性
創建一個ComponentName需要指定包名和類名(這樣就可以唯一指定一個組件類)
Android中的context代表了訪問該應用環境資訊的介面,包名是作為應用的唯一標識,故
context和包名是一一對應的關系,
制定了Component的intent已經明確了它將要啟動的那個組件,因此這種intent被稱為顯示intent
沒有指定Component的intent被稱為隱式intent
隱式intent沒有指定要啟動那個組件,所以會啟動符合條件的組件,但是具體是哪一個組件
是不確定的,

當intent使用顯式intent啟動另外一個組件的時候,被啟動組件基本上不需要使用

5.2.2 Action Category屬性與intent-filter配置
action表示該Intent所要完成的一個抽象“動作”,而Category則用于為了Action增加額外的附加類
資訊,通常Action屬性會與Category屬性結合使用,

其中的action表示的只是一種抽象動作,例如:Activity查看view,實際上,action這個字串
并不管具體查看什么,具體查看取決于Activity的配置,

一個intent物件只能包括一個action屬性,當程式創建的時候,該intent默認啟動Category
屬性值為Intent.CATEGORY_DEFAULT常量的組件,

5.2.3 指定Action,Category呼叫系統的Activity
實體:查看并獲取聯系人的電話
實體:回傳系統 Home桌面

5.2.4 Data,Type屬性與intent-filter配置

Data屬性通常表示向action屬性提供需要操作的資料,
Data屬性接受一個Uri物件,該Uri物件通常通過如下形式的字串來表示,

content://com.android.contacts/contacts/1
tel:123

Uri字串總滿足如下格式:
scheme://host:port/path

Type屬性用于指定該Data屬性對應的MIME型別,這種MIME型別可以是任何自定義的MIME型別,
只要符合abx/xyz格式的字串即可,

Type和Data會產生覆寫,那么如果不想覆寫就可以使用intent.setDataAndType();

在Manifest中為組件宣告Data Type 屬性都通過<data…/>元素,改元素的格式如下:

如果<data…/> 子元素只有android:port屬性,沒有指定android:host屬性,那么android:port屬性,沒有指定android屬性將不會起作用

//5.2.5 Extra屬性

//5.2.6 Flag 屬性

//第六章Android應用資源
從物理存在形式上分有三大類:
{
界面布局檔案.xml檔案
程式源檔案(應用中的Activity,Service,BroadcastReceiver,ContentProvider)
資源檔案(主要還是以xml檔案為主,還可有圖片形式等)
}

Android中除了res/目錄下存放資源外,assets目錄也用于存放資源,
一般來說,assets資源存放的是無法直接訪問的原生資源,應用程式需要通過AssetsManager以
二進制流的形式來讀取資源,

6.1 應用資源概述

6.1.1 資源的型別及存盤方式
animator/ 存放的是屬性影片的XML檔案
anim/ 定義補間影片的XML檔案
color/ 定義不同狀態下顏色串列的XML檔案
drawable/ 存放適應不同螢屏解析度的各種位圖檔案
mipmap/ 存放適應不同螢屏解析度的應用程式圖示
layout/ 存放各種用戶界面的布局檔案
menu/ 存放為應用程式定義各種選單的資源,包括選項選單、子選單、背景關系選單資源
raw/ 存放任意型別的原生資源(比如:音頻檔案、視頻檔案等)
values/ 存放各種簡單值的xml檔案
xml/ 存放任意原生的xml檔案

drawable-ldpi解析度,drawable-mdpi中等解析度,drawable-hdpi高解析度,drawable-xhdpi超高解析度
drawable-xxhdpi超超高解析度 等子目錄,

如果開發時候所有的螢屏提供的是同一張圖片,那么可以直接放在drawable目錄下,

6.1.2使用資源
1.在源程式中使用資源清單項
2.在源代碼中訪問實際的資源(使用Resources類,可以稱為:“資源訪問總管家”)
3.在xml檔案中使用資源

6.2 字串 顏色 尺寸資源
6.2.1 顏色值的定義
6.2.2 定義字串 顏色 尺寸資源檔案

尺寸資源位于:/vlues資源檔案夾下
<dimen…/>

6.2.3 使用字串 顏色 尺寸資源檔案
Android中允許定義boolean資源檔案
在values/下面,使用:
true
并使用R.bool.name實作訪問

還可以定義整形變數:
<integer…/>定義整形變數

6.3 陣列資源
Android中并不推薦在程式源代碼中定義陣列

陣列元素包含三種子元素:
<array…/>
<string-array…/>
<integer-array…/>

6.4 使用drawable資源
(只要一份xml檔案可以被系統編譯成Drawable子類的物件,那么這份xml檔案即可作為Drawable資源)
6.4.1 圖片資源
Android要求圖片資源的檔案名必須符合java或Kotlin識別符號的命名規則,否則不會生成索引,

6.4.2 StateListDrawable資源
該物件可以組織多個Drawable物件,當使用該物件作為目標組件的背景的時候,該物件所顯示的Drawable
物件可以隨著目標組件狀態的改變而自動切換,

定義StateListDrawable物件所顯示的Drawable物件會隨著目標組件狀態的改變而自動切換,

定義的StateListDrawable物件的根元素為:<selector…/>
該元素可以包含多個item元素,
實體:高亮顯示正在輸入的文本框

//LayerDrawable資源
該物件類似于StateListDrawable物件,也包含很多item元素,系統會按照這些Drawable物件的陣列
順序來繪制他們,索引最大的Drawable物件將會被繪制在最上面,

定義LayerDrawable物件的XML檔案的根元素為:<layer-list …/>
可以包含有多個item元素
item元素中的屬性如下:
android:drawable
android:id 該Drawable物件指定一個標識
android:button|top|left|button:用于指定一個長度值,用于指定將該Drawable物件繪制
到目標組件的指定位置,

實體:定制拖動條外觀

//6.4.4 ShapeDrawable資源

該組件用于定義一個基本的幾何圖形,定義該物件的xml檔案的根元素是<shape…/>元素
android:shape=“rectangle|oval|line|ring”

定義格式如下:
<corners…/> 定義幾何圖形四個角的弧度
<gradient…/> 定義使用漸變色填充
<padding…/> 定義幾何形狀的內邊距
<size…/> 定義幾何形狀的大小
<solid…/> 定義使用單色填充
<stroke…/> 定義為幾何形狀繪制邊框

實體:橢圓形、漸變背景的文本框
//截至2020/12/22日晚上19:05(由于筆記太長,換下一個新的筆記本)

//-------------------------------------以上是截止到12-22日的筆記----------------------------------------------//

實體:實作橢圓形 漸變背景的文本框
//截至到上邊目錄顯示所謂的318頁

//12-23號晚上學習筆記
//6.4.5 ClipDrawable資源
ClipDrawable代表從其他位圖上截取一個“圖片片段”,

使用該物件的時候可以使用setLevel()方法來設定截取的區域的大小,
當設定的level值為0時表示截取的片段為空,當該值為10000的時候表示截取的圖片是整張圖片
//實體:徐徐展開的風景(可以使用該物件實作圖片進度條)

//6.4.6 AnimationDrawable資源
以實作補間影片為例:需要定義的是AnimationDrawable物件的屬性是:{
alpha:設定透明度的改變
scale:設定圖片進行縮放變換
translate:設定圖片進行位移變換
rotate:設定圖片進行旋轉
}

該物件需要定義在anim檔案夾中
上面屬性包括<set…/>在內還可以定義一個interpolator屬性,該屬性指定影片的變化速度
如果程式想讓再一個set下面的所有元素使用相同的影片速度,那么可以指定屬性:
android:shareInterpolator=“true”

為了在java代碼中呼叫影片物件可以使用AnimationDrawableUtils物件

實際上想要保存對應的狀態需要設定set中的屬性fillAfter="true"即可,

6.5 屬性影片資源
Animator是一個抽象類,實際開發中通常使用其子類
定義屬性影片資源可以以{set objectAnimator animator}中的任意一個作為根元素

//實體:不斷漸變的背景色

//6.6 使用原始的XML資源
6.6.1 原始資源的路徑
原始xml資源一般保存在/res/xml路徑下(但是開發者需要自己創建xml檔案夾)
使用XmlResourceParser getXml()獲取xml檔案
使用InputStream openRawResource(int id);獲取xml檔案對應的輸入流

大部分時候都可以直接呼叫getXml()方法來獲取XML檔案
Android默認使用內置的pull決議器來決議xml檔案(pull決議器是一個開源專案)

pull決議器方式有點類似于SAX決議,都采用時間驅動方式來進行決議,
當pull決議器開始決議之后,開發者可不斷呼叫pull決議器的next()方法獲取下一個決議事件
當處于某一個標簽時,可以呼叫XmlPullParser的nextText()方法來獲取文本節點的值,

6.6.2 使用原始的XML檔案

//6.7 使用布局資源

//6.8 使用選單資源

//6.9 樣式 和 主題 資源
6.9.1 樣式資源
一個樣式相當于多個格式的集合,其他UI組件通過style屬性來指定樣式

樣式可以使用繼承,繼承之后子樣式會覆寫對應的父樣式

6.9.2 主題資源
主題與樣式的區別是:
主題不可以用在單個view組件中
主題定義的格式應該是改變視窗外觀的格式,例如:視窗標題,視窗邊框等,

//6.10 屬性資源
使用的情景:如果用戶開發自定義的view組件需要指定屬性,那么就需要屬性資源的幫助了
屬性資源檔案的跟元素也是:<resources…/>元素,改元素包含如下兩個屬性,
{
attr
declare-styleable元素:定義一個styleable物件,每個styleable物件就是一組attr屬性的集合
}

在自定義組件的構造器中通過AttributeSet物件來獲取這些屬性,

//6.11 使用原始資源
只要是Android沒有為之提供專門的支持,這種資源都是原始資源
位于:raw(會在R中生成一個索引項)下 或 assets(是更徹底的資源,需要通過AssetsManager資源)下

//6.12 國際化
6.12.1 為Android應用提供國際化資源
我們需要在res/values/資源的檔案夾下面保存程式中用到的字串訊息,為了給這些訊息提供不同
國家、語言的版本,開發者需要為values目錄添加幾個不同的語言國家版本,
不同的values檔案夾的命名方式為:
values-語言代碼-r國家代碼

在不同的國際化資源中所有的訊息的key是相同的,但是對應的value不同

//6.12.6 國際化Android應用
定義的國際化資源可以自動發揮作用

//6.13 自適應不同螢屏的資源
盡量使用dp為解析度單位

//6.14 本章小結

/--------------------第七章 圖形于影像處理------------------/
//截止到2020/12/23號晚上22:02 (page 343)

/-----------2020/12/22號晚上23:58分開始學習------/
7.1 使用簡單圖片
//使用Drawable物件
7.1.2 Bitmap 和 BitmapFactory
BitmapDrawable里封裝的圖片就是一個Bitmap物件,
可以呼叫BitmapDrawable的構造方法將bitmap物件包裝成一個BitmapDrawable物件

獲得bitmapDrawable物件所包裝的bitmap物件可以通過getBitmap();來獲得

7.1.3 Android 新增的ImageDecoder
使用該api對圖片解碼的時候,程式回傳一個AnimatedImageDrawable物件,呼叫該回傳
物件的start()方法,可以開始執行影片,

截至到2020/12/24—凌晨0:44—7.2繪圖 (page 347/511)

//2020/12/24號下午學習筆記7.2 繪圖
7.2.1 繪圖基礎Canvas Paint等
Android中應該繼承view類并重寫其onDraw()方法
Canvas代表“依附于”一個指定View的畫布
Canvas提供了一個Paint物件,因此Paint類主要用于設定繪制風格,包括畫筆顏色等
Canvas中的另一個apiPath,代表任意多條直線連接而成的任意圖形,Canvas根據path繪制時
可以繪制出任意的圖形,

呼叫canvas.drawPath(path,paint)方法實作按照對應path路徑繪制圖片

前期只要美工把應用程式所需要的圖片制作出來后期看發的時候直接使用就可以

7.2.2 Path類
該類可以預先將N個點連成一條“路徑”,然后呼叫Canvas的drawPath()方法即可以沿著路徑繪制
圖形,

Android中還為路徑繪制提供了PathEffect來定義繪制效果,

實作繪制文本的邏輯是:
//繪制路徑
paint.setStyle(Paint.Style.STROKE);
canvas.drawPath(paths[2],paint);
//沿著路徑繪制一段文本
paint.setStyle(Paint.Style.FILL);
canvas.drawTextOnPath(drawStr,paths[2],-20f,20f,paint);

7.2.3 繪制游戲影片
所謂的影片就是不斷呼叫onDraw()方法,在呼叫的同時需要更改一部分的資料,
而通知View實作重新繪制需要呼叫的是invalidate(在ui執行緒中) 或 postInvalidate(在不是ui的執行緒中)

//實體采用雙緩沖實作圖畫板
所謂的雙緩沖技術其實很簡單:當程式需要在指定的View上進行繪制時,程式并不直接繪制到該
View組件上,而是先繪制到記憶體中的一個Bitmap物件上(這就是緩沖區),等到記憶體中的Bitmap繪制
好之后,再一次性地將Bitmap繪制到View組件上,

//實體:彈動的小球

7.3 圖形特效處理
7.3.1 使用Matrix控制變換
使用該物件的步驟如下:
1.獲取Matrix物件
2.呼叫Matrix的方法進行平移、旋轉、縮放、傾斜等
3.將程式對Matrix所作的變換應用到指定影像或組件
Matrix 還可以用于對于View組件的平移、旋轉和縮放,

Canvas呼叫drawBitmap()方法可以實作繪制bitmap的時候應用Matrix變換

7.3.2 使用drawBitmapMesh扭曲影像
該函式中的各種關鍵引數如下:
bitmap:指定需要扭曲的源位圖
meshWidth:該引數控制在橫向上把該源位圖劃分成多少格
meshHeight:該引數控制在縱向上把該源位圖劃分為多少格
verts:該引數是一個長度為(meshWidth + 1) * (meshHeight+1) * 2的陣列
vertOffset:控制verts陣列中從第幾個陣列元素開始才對bitmap進行扭曲

//7.3.3 使用Shader填充圖形
前面介紹Paint時提到的Shader包含了一個setShader(Shader s)方法
該方法控制畫筆的繪制效果

//7.4 逐幀影片(Frame)
7.4.1 逐幀影片AnimationDrawable與逐幀影片
只需要在<animation-list…/>元素中使用<item…/> 子元素定義影片的全部幀,
并指定各真的持續時間即可,

其中item中的屬性oneshot設定為true表示不回圈播放

在Java代碼中先創建AnimationDrawable物件,然后呼叫addFrame()向該影片中添加幀
一旦程式獲取了AnimationDrawable物件之后,接下來就可以用ImageView把AnimationDrawable
物件顯示出來(習慣上把AnimationDrawable設定程ImageView的背景即可)

//實體:在指定點爆炸(實作邏輯:
先在MainActivity中創建FrameLayout物件,然后設定背景,然后加載myView組件,并設定對應的
影片資源,
獲取影片物件(目的是在后期的為frame設定的監聽器中可以呼叫影片物件開始和停止動作)
自己定義的MyView物件,主要是在onDraw()實作部分邏輯的目的是,為了使得播放到最后一幀時
自動停止播放并將view組件設定為不可見,

//7.5 補間影片(Tween)
補間影片是指:開發者只需要指定對應的開始和結束圖片,中間部分的圖片系統自動補齊,
//7.5.1Tween影片與Interpolator

//Interpolator根據特定演算法計算出整個影片所需要動態插入幀的密度和位置,

為了在影片資源檔案中指定補間影片所使用的Interpolator,定義補間影片的<set…/>集合元素
支持一個android:interpolator屬性,

7.5.2 位置 大小 旋轉度 透明度改變的補間影片
//實體:蝴蝶飛舞

7.5.3 自定義補間影片
自定義補間影片需要繼承Animation類,關鍵是重寫該基類的applyTransformation();方法

Camera提供了一個三維空間變換的工具,功能比matrix更加強大,

//截止到378/511 at 2020/12/25 0:28

/----------------------2020/12/26號晚上 21:05 學習筆記------------------------/
接著7.5.3學習:
自定義補間影片需要繼承Animation類,關鍵是重寫該基類的applyTransformation();方法
其中的引數:
{
interpolator:表示影片的時間進行比,不管影片實際的持續時間如何,該引數都是從
0-1進行變化的,

transformation:代表了補間影片在不同時刻對圖形或組件的變形程度,(該物件可以)
實作對于圖片或者視圖的控制)
}

對于Camera類中的常用的方法有:
1.getMatrix()將Camera所作的變換應用到指定的matrix上
2.rotateX 表示使目標組件沿X軸旋轉
3.rotateY 表示使目標組件沿Y軸旋轉
4.rotateZ 表示使目標組件沿Z軸旋轉
5.translate 表示使得目標組件在三維空間里進行位移變換
6.applyToCanvas() 表示將剛才進行的變換應用到對應的canvas中

對于android手機的三維空間坐標系來說
平行于螢屏從左到右是X軸
平行于螢屏從下到上是Y軸
垂直于螢屏從里到外是Z軸

//自己總結的關于實作自定義的三維影片邏輯:
首先是自定義一個類繼承animation類,然后定義對應的構造方法,設定其中的initialize()方法
中的邏輯,設定其中的applyTransformation()方法實作的是對于出來組件的時候影片渲染邏輯
該方法中的重要邏輯是:{先呼叫camera.save()方法,然后根據interpolationTime控制三個坐標軸上的偏移量
然后使用camera.rotateX 與 camera.rotateY()方法設定X和Y軸上的旋轉角度,然后獲取Transformation
引數的Matrix物件,并使用camera.setMatrix(matrix);設定物件,然后呼叫matrix.preTranslation() 及 matrix.preTranslation()
;方法;最后呼叫camera.restore()方法實作保存 }

//7.6 Android 8 增強的屬性影片:
從大體上來說,屬性影片是增強版的補間影片,但是屬性影片更加強大
補間影片只可以對UI組件執行影片,但是屬性影片幾乎可以對任何物件執行影片(不管他是不是顯示在螢屏上)

//屬性影片的API
Animator 提供了創建屬性影片的基類(基本上不使用該類)
ValueAnimator屬性影片主要的時間引擎,負責計算各個幀的屬性值,

屬性影片主要由兩方面組成{
計算各幀的相關屬性值
為指定物件設定這些計算后的值
}

ValueAnimator主要負責的是第一個方面的值

ObjectAnimator 是ValueAnimator的子類,用于組合多個Animator,并指定多個ANimtor
是按次序播放還是同時播放,

除此之外,屬性影片還需要一個Evaluator該工具類控制屬性影片如何計算屬性值,

Android 8 還為AnimatorSet新增了幾個方法:{
reverse(); //反向播放屬性影片
long getCurrentPlayTime(); 獲取影片的當前播放時間
setCurrentOlayTime(); 設定影片的播放時間
}

通過設定setCurrentPlayTime()方法可以使得直接在對應的時間點進行播放

測驗實作:
1.ValueAnimator創建影片
四個步驟:
呼叫其中的ofInt() ofFloat() ofObject() 靜態方法創建ValueAnimator實體
呼叫ValueAnimator的setXxx()方法設定影片持續時間,插值方式,重復次數,
呼叫ValueAnimator的start()方法啟動影片
為ValueAnimator注冊AnimatorUpdateListerner()監聽器,在該監聽器中可以監聽
ValueAnimator計算出來的值的改變,并將這些值應用到指定物件上,

2.使用ObjectAnimator創建影片
該類可以直接將其父類中計算出來的值直接用到指定物件的屬性上

與ValueAninmator不同的是,使用ObjectAnimator的注意點:
要為該物件對應的屬性提供對應的setter方法
如果是對于其中方法的ofInt()等中的引數時,其中的values陣列如果只提供了
一個值,那么該值會被認為是結束值,該物件還應該為該屬性提供一個getter()方法,該getter
方法回傳的值就是開始值,
若該影片物件不是view,為了顯示影片效果,還需要在onAnimatorUpdate()事件監聽方法中
呼叫.invalidate()方法,實作對應的組件的更新,(view組件會自動呼叫故不需要指定)

//7.6.2 使用屬性影片
屬性影片可以既可以用于UI組件,也可以用于對應的普通的物件

定義屬性影片有兩種方式:
使用ValueAnimator 或 ObjectAnimator 的靜態工廠來創建影片
使用資源檔案來定義影片

具體步驟如下:
創建ValueAnimator 或 ObjectAnimator 物件–既可從XML檔案中加載該影片資源;也可以使用兩個類的
靜態構造方法來創建影片,
根據需要可以為animator設定對應的屬性,
如果需要設定監聽animator的影片開始事件等,應該為animator物件設定事件監聽器,
如果有多個影片需要按次序或同時播放,則應該使用AnimatorSet組合這些影片,
呼叫Animator物件的start()方法啟動影片,

//---------------2020/12/27晚上學習筆記(從p 383 開始學習)---------------------
-0x1000000 + red << 16 | (green << 8) | blue
對于上式的解釋:
oxff000000代表透明度為ff,也就是完全不透明
red代表一個0-255的隨機整數,但是這個整數要添加到oxff000000加粗
的兩個位上,也就是說要將red的值左移(16位,對應為十六進制的4位)
,這就是red << 16的原因

green 代表的是0-255的隨機整數,但是這個整數要添加到0xff000000張加粗的兩個位置

blue…

//實體:大珠小珠落玉盤

//使用SurfaceView實作影片
View存在的缺陷:
{
View缺乏雙緩沖機制
當程式需要更新view上的圖片時,程式必須重繪View上顯示的整張圖片
新執行緒無法直接更新view組件
}

7.7.1 SurfaceView繪圖機制
surfaceView會和surfaceHolder結合使用
使用getHolder()可以得到對應的holder物件

surfaceHolder物件提供下面的方法來獲得canvas物件:
lockCanvas()鎖定整個SrufaceView物件,獲取該SurfaceView上的canvas
lockCanvas(Rect dirty) 鎖定SurfaceView上的Rect劃磁區域,獲取該區域上的canvas(該方法只更新對應的
圈出來的區域))

需要說的是當需要呼叫surfaceHolder的unlockCanvasAndPost()方法之后,該方法之前所繪制的圖形所處于緩沖區中
下一次lockCanvas()方法鎖定的區域可能會“遮擋”它,

//測驗實作使用surfaceView影片效果實作
(實作邏輯(自己總結:{
首先創建一個FishView類,然后在構造方法中得到系結的holder物件,并將本view
放進去,然后創建一個bitmap物件得到對應的資源檔案;初始化對應的陣列,然后
得到;實作對應的resume() pause()方法 surfaceCreated()方法 surfaceChanged()方法
創建一個心得thread類,然后再其中的run方法中得到fishView類的getHolder()方法,可以開始執行影片,
鎖定SurfaceView并回傳到繪圖的Canvas,然后繪制背景圖片,然后是判斷魚是否
已經出了螢屏,并使用matrix來控制魚的旋轉角度和位置,然后呼叫canvas.drawBitmao()
表示在畫布上繪制對應的圖片(并設定了旋轉的角度和對應的速度,然后是解鎖canvaas)并渲染)
當前影像,設定執行緒沉睡0.06秒,然后是設定如下代碼即可:

void requestExitAndWait(){
//把這個執行緒標記為完成,并合并到主程式執行緒中
done = true;
try{
join();
}catch (Exception e){
e.printStackTrace();
}
}

    void onWindowResize(int w,int h){
        //處理SurfaceView的大小改變事件
        System.out.println("w:" + w + "===h:" + h);
    }


}))

//截止到392 頁面學習筆記 (2020/12/27晚上11:30)

/-----------------------2020/12/28 晚上學習筆記 (從392開始)----------------------------/
surfaceView來說和view的顯著區別是,執行緒可以使用surfaceView物件的surfaceHolder物件來繪制影像,

//基于surfaceView開發示波器
重點:考慮surfaceView組件的情況是:程式或游戲界面的影片元素很多,并且很多影片元素的移動都需要
通過定時器來控制,就可以考慮該組件,

//2020/12/28號 22:30開始 晚上學習筆記
/----------------------------第八章 Android 資料存盤與IO-----------------------/
Android中Sqlite資料庫對應于一個檔案(沒有后臺行程)
8.1 使用SharedPreference物件存盤資料
使用情景:少量的資料保存 資料格式簡單 都是普通的字串 標量型別的值等
SharedPreference物件主要是保存類似于配置資訊格式的資料,主要是key-value形式,
通過SharedPreference.Editor物件才可以寫進去資料
使用Editor物件的.apply()方法可以更新資料,(使用commit會立即修改但是使用apply()不會阻塞前臺行程)

為了得到SharedPreference物件可以是喲個context物件的getSharedPreference();方法得到
想要將本應用中的資料暴漏出來的話,Android 4.2 開始推薦使用ContentProvider物件來訪問,

8.1.2 SharedPreference物件的存盤位置和格式
使用該物件保存的資料放在:
/data/data//shared_prefs 目錄下,并總是以xml格式來保存

//8.2 Filr存盤
8.2.1 openFileOutPut 和 openFileInput
除此之外,context提供了幾個方法來訪問應用程式的資料檔案夾
getDir()方法獲得子目錄
file getFileDir()獲得絕對路徑
String[] fileList回傳應用程式資料檔案夾下面的全部檔案
deleteFile()洗掉指定檔案

使用context存盤的都是再手機的內置存盤中

讀寫SD卡上的檔案步驟如下:
1.請求動態獲取讀寫SD卡的權限
2.呼叫Environment的getExternalStorageDirectory()方法來獲取外部存盤器(SD)的目錄
3.使用FileInputStream FileOutputStream FileReader或FileWriter命令來創建虛擬存盤卡,
4.為了讀寫SD卡上的資料,必須在應用程式的清單檔案中設定權限:

//截止到2020/12/29號晚上23:32min

/---------------------------2020/12/30號下午13:46開始學習筆記--------------------/
from 404 begin

//實體:SD卡檔案瀏覽器

8.3 SQLite資料庫
該資料庫是一個輕量級的資料庫,是一個嵌入式的資料庫引擎
該資料庫只是一個檔案

8.3.1 SQLiteDatabase(底層就是一個資料庫檔案)簡介
該物件的作用有點類似于JDBC的connection介面

該物件支持的查詢方法回傳的都是一個Cursor物件

當移動到指定行之后,接下來就可以呼叫Cursor的getXxx()方法獲取該行的指定列的資料了,

8.3.2 創建資料庫和資料表

8.3.3 SQLiteOpenHelper類
實際專案中很少使用直接的openOrCreateDatebase()靜態方法來打開資料庫,通常都會繼承該類并通過
該類的getReadableDatabase() 和 getWritableDatabase()方法打開資料庫

該類可以用來進行版本更新和資料庫的創建,

重寫其中的onCreate()方法,該方法是只有在第一次生成資料庫表結構的時候呼叫,在里面可以
設定資料庫表的結構(也可以添加一些資料進去)

當用戶創建一個helper物件時,程式員指定資料庫版本號(當某一次創建的時候版本號高于原來的版本時,
系統會自動進行必需的表結構的更新)

當資料庫升級失敗的時候,需要先進行轉儲,然后對資料表進行更新,之后再保存回來原來的資料,

getWritableDatabase()以寫的方式打開資料庫,然后使用getReadableDatabase()方法,先以讀寫的方式打開
資料庫,如果資料庫的磁盤已經滿了就會打開失敗,當打開失敗的時候會繼續嘗試以只讀的方式打開資料庫,

//8.3.4 使用SQL陳述句操作資料庫
使用execSQL()方法可以執行任意的SQL陳述句,包括帶有占位符號的Sql陳述句,
當需要執行查詢陳述句的時候,可呼叫rawQuery()方法

//8.3.5 使用sqlite3工具
在android SDK 的 platform-tools 目錄下提供了一個sqlite3.exe 檔案,他是一個簡單的sqlite資料庫管理工具
類似于MySQL提供的命令列視窗,

sqlite3常用命令如下:
.database查看當前的資料庫
.tables 查看當前資料庫里的資料表
.help 查看sqlite3支持的命令

再將sql陳述句真正地插入到資料庫中的之前先在sqlite3這個工具類中測驗是否是有語法錯誤

需要說明的是sqlite內部只支持NULL,INTEGER,REAL(浮點數),text(文本),和BLOB(大二進制物件)

但實際上其他的型別該資料庫也會接受只不過是在保存到底層資料庫中的時候會轉換成上述的5種資料,

同時,sqlite3還會把各種型別的資料保存到任意型別的欄位中,開發者可以不用關心宣告該欄位所使用的資料型別,
但是有一種例外情況:
定義為:INTEGER PRIMARY KEY 的欄位 只能存盤64位整數,當向這種欄位中保存除了整數之外的其他型別的資料時
SQLite會產生錯誤,

//8.3.6 使用特定的方法操作SQLite資料庫

insert方法插入一行記錄使用ContentValues存放(該型別類似于Map)
其中的引數:(String table,String nullColumnHack,COntentValues values)
第二個引數只有當vlues是null時,會添加除了主鍵之外其他欄位都是null的記錄,(第二個引數指定的是插入的列名)

8.3.7 事務
當結束事務的時候,會根據前邊SQLiteDatabase物件是否呼叫了setTransactionSuccessful()方法來設定事務標志
如果事務執行中呼叫該方法設定了事務成功,則提交事務,否則程式將會回滾事務,

//8.3.8 SQLite資料庫最佳實踐建議

1.關于打開資料庫的方式
通過前面介紹我們知道,打開SQLite資料庫有兩種方式
直接通過SQLiteDatabase的靜態方法打開資料庫;
通過SQLiteOpenHelper類的子類來打開資料庫(強烈建議使用第二種方式)

2.關于SQLite的用途:
不要把大量的資料都放到SQLite中;如果需要保存大量資料需要設定服務器端,
SQLite可以快取部分的服務器端的資料,

4.關于操作資料庫的方式
使用execSQL()原生操作,rawQuery()方法執行原生操作SQL陳述句

使用insert update delete query 方法執行SQL陳述句

強烈建議使用OEM工具:Ormlite GreenDao LitePal等(有Hibenate經驗優先)

//8.4 手勢
Android提供了手勢檢測并為手勢檢測提供了相應的監聽器
Android允許開發者自己添加手勢,并提供了相應的API識別用戶手勢

8.4.1 手勢檢測
Android為手勢檢測提供了一個GestureDetector類,該類的一個實體代表了一個手勢檢測器
創建該類時需要傳入一個GestureDetector.OnGestureListener實體(該實體就是一個監聽器,負責給用戶的手勢提供相應)

使用Android手勢的步驟:
使用GestureDetector物件(該物件必須實作的是監聽器介面)
為應用程式的Activity的TouchEvent事件系結監聽器(將Activity上的touchEvent事件交給GestureDetector處理)

//實體:通過手勢縮放圖片
實作邏輯自己總結:
首先需要定義手勢檢測器變數、Bitmap變數、定義圖片的寬和高、記錄當前的縮放、控制圖片縮放的matrix物件
然后定義一個手勢檢測器初始化,先得到對應的vx滑動速度,根據vx進行圖片的縮放,然后重置matrix物件
縮放matrix物件,然后是得到BitmapDrawable物件,判斷是否已經回收,如果沒有回收就回收
然后根據新的matrix創建新的bitmap位圖物件,然后設定imageView顯示位圖物件,最后是
在acitivity中的onTouchEvent()方法中回傳一個手勢檢測器的onTouchEvent(event);結果,

處理多點觸碰也通過重寫onTouch()方法進行實作,通過該方法中的MotionEvent引數的getPointerCount()方法可判斷
觸碰點的數量

通過MotionEvent的getActionMasked()方法來判斷觸碰事件的型別,

//8.4.2 增加手勢

Android中使用GestureLibrary來代表手勢庫,并提供了GestureLibraries工具類來創建手勢庫

Android還提供了一個手勢編輯組件:GestureOverlayView組件,用戶可以在組件上繪制的不是圖形而是手勢

該組件還提供了三個監聽器
onGestureListener onGesturePerformedListener onGesturingListener (分別表示手勢開始 結束 完成 取消等事件)
第二個是最常用的監聽器,它用于在手勢事件完成時提供相應,

注意:一個組件不是標準的視圖組件的時候因此在界面布局中使用該組件時需要使用全限定類名

<android.gesture.GestureOverlayView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/gesture"
    android:gestureStrokeType="multiple"
    />

該組件中使用的android:gestureStrokeType="multiple"屬性表示的是設定為single(手勢只有一筆完成)
使用multiple表示多筆完成

實體:實作存盤用戶手勢邏輯
自己總結邏輯:

1.創建GestureOverlayView 以及 Gesture物件
初始化手勢編輯視圖物件,為繪制手勢物件系結監聽器并設定動態獲得SD卡權限

2.然后在activity中的內部方法中實作保存手勢的邏輯:
判斷用戶是否同意了獲得讀寫權限,如果是,那么獲得對應的布局檔案,然后在布局檔案中添加一個imageView組件
接著將剛才在GestureOverlayView組件中繪制的影像以bitmap(位圖)顯示在imageView組件中,然后創建一個對話框
將剛才準備好的布局組件顯示到對話框中,然后設定確定的實作邏輯是:保存手勢到手勢庫中,

//截止到2020.12.30 晚上 22:11  (p432)

//---------------截止到2020.12.31 晚 20:38開始學習筆記-------------//

//2020.12.31 晚 20:40 學習筆記:
8.4.3 識別用戶自定義手勢

GestureLibrary提供了recognize(Gesture ges) 方法來識別手勢,該方法回傳該手勢庫中所有與ges手勢匹配的手勢,
回傳的結果是一個ArrayList 集合,其中的Prediction物件封裝了匹配的屬性資訊,其中的name表示匹配的手勢
名字,其中的score表示匹配的相似度,

//截止到2020.12.31 晚上 21:42 止 //截止到433頁

//2021.1.1 上午 1:40 學習筆記:---------------------------------------------
//8.4.3 識別用戶手勢
識別用戶手勢邏輯自己總結:

定義手勢編輯組件變數和手勢變數;在onCreate()方法中請求用戶允許讀寫SD卡權限;在activity中自帶的方法中處理顯示
組件邏輯(包括:判斷用戶是否同意授權,如果同意那么先得到之前創建的手勢庫,然后手勢庫裝載,是否成功;如果成功,
獲取手勢編輯組件,給手勢編輯組件增加監聽器;在監聽器中實作:{
創建一個List 陣列用來保存回傳的識別結果,然后創建以惡個List result 陣列物件,實作的是
用來生成需要顯示的陳述句;然后遍歷得到的回傳陣列(當識別度大于2.0的時候生成對應的結果,然后判斷自己定義的結果陣列長度
是不是大于0的,如果是,則生成一個配接器用于準備結果;然后創建一個帶有List的對話框來顯示所有的手勢;至此邏輯總結完畢)
})

8.5 讓應用說話(TTS)(TextToSpeech)
Android提供的自動朗讀功能,
android中還支持將文本生成的音頻錄制成音頻檔案,
使用的時候需要提供一個OnInitListener監聽器,該監聽器負責監聽TextToSpeech的初始化結果,
在程式中獲得了TextToSpeech物件之后可以使用setLanguage()方法來設定該TTS語音引擎應使用的語音,國家選項,
目前內置的TTS引擎對中文支持的效果不好,但是科大訊飛的TTS引擎對中文支持比較好,

TextToSpeech的兩個常用的方法是:
speak() 該方法只是朗讀文本
synthesizeToFile() 該方法可以將轉換得到的音頻保存到聲音檔案中,

speak()方法中的queueMode引數指定TTS發音佇列模式,該引數支持下面的兩個常量:
TextToSpeech.QUEUE_FLUSH 表示當TTS呼叫speak()方法時,會中斷當前實體正在運行的任務,
TextToSpeech.QUEUE_ADD 表示將當前的語音加入到對應的語音佇列中,并等待當前發音佇列中的任務執行完之后才執行當前的語音,

//測驗TTS

//8.6 本章小結

/-------------------------------第9章 使用ContentProvider實作資料共享--------------------------------/
ContentProvider是Android提供的用于實作不同應用之間資料互動的標準API
而其他的應用程式則可以使用ContentResolver物件來操作對應的資料,

//截止到 2021.1.1 下午 13:08 (p439)

//2021.1.1 下午 16:56 開始學習筆記:
ContentProvider也是android四大組件之一,也需要在Manifest.xml檔案中進行配置

只要是一個應用提供了Contentprovider介面,那么不管該應用是否啟動,外部的應用都可以訪問資料等,

9.1 資料共享標準:ContentProvider組件
該物件提供Uri形式對外提供資料

9.1.1 ContentProvider簡介

開發一個ContentProvider的步驟:
1.定義一個ContenProvider類,需要繼承Android提供的ContentProvider基類,
2.向Android系統中注冊一個ContentProvider,注冊的時候需要指定一個Uri(也就是authorities)即可
只要在<application…/>元素下添加子元素即可,

對于自己定義的provider類除了需要繼承ContentProvider類之外還需要提供如下幾個方法:
1.onCreate() 在ContentProvider創建后呼叫
2.insert()根據uri插入vlaues對應的資料
3.delete()根據uri洗掉selection條件所匹配的全部記錄
4.update()根據uri修改selection條件所匹配的全部記錄
5.query() 根據uri查詢得到selection條件匹配的全部記錄 其中的projection就是一個列名串列,表明只選擇出來指定的資料列
6.getType()方法用于回傳當前uri代表的MIME型別,

//9.1.2 Uri簡介:
一個Uri分為三個部分:
content//:這個部分是Android的ContentProvider規定的,就像上網的協議默認是http一樣,用來暴露對于contentprovider的訪問
org.wyy.providers.testprovider 這個部分就是ContentProvider的authorities
words資源部分(或者說資料部分),當訪問著需要訪問不同資源時,這個部分是動態改變的,
在words/2 表示的是words資料中的ID為2的資料
上述的Uri借本上遵循的是RESTFul

使用uri物件的Uri.parse(""); 可以實作將String型別的字串轉換為:Uri

9.1.3 使用ContentResolver操作資料(用來操作contentProvider物件中保存的資料)
該物件可以使用context物件的.getContentResolver()方法得到對應的contentResolver物件

一般來說contentProvider是單例的

//9.2 開發contentProvider

9.2.1 contentProvider 和 contentResolver的關系

9.2.2 開發contentProvider子類
需要注意的是:在ContentProvider子類中實作的各種方法不是自身呼叫的,
而是提供給其他應用程式呼叫的,

9.2.3 配置ContentProvider
Android要求的是所有的應用組件都需要進行顯示配置
其中設定的屬性android:exported屬性表示指定該provider是否可以被呼叫(設定為true可以被呼叫)

其中設定的readPermission writePermission 屬性表示設定需要的權限
或者使用permission來設定
如果不設定權限那么表示可以被所有的APP訪問

//截止到2021.1.1 22:54為止(p444)

/--------------------------------2021.1.2 12:08 開始學習筆記--------------------------------------/
9.2.4 使用ContentResolver呼叫方法
其中update() delete()方法回傳的是更新或洗掉的資料數目

//9.2.5 創建ContentProvider的說明
實際上,為了確定該ContentProvider實際可以處理的Uri,以及確定每一個方法中Uri引數所操作的資料,Android系統提供了
UriMatcher工具類

其中的addUri(String authority,String path,int code)方法用于向該物件注冊Uri其中的authoirity和path組合成了一個Uri,而code代表該Uri對應的標識碼,

int match(Uri uri) 可以根據前面注冊的uri來判定指定uri對應的標識碼,找不到回傳-1,

可以使用ContentUris.parseId(uri)來獲得對應的ID值

//實體:開發contentProvider實作單詞本

建議:使用工具類定義常量可以實作對訪問路徑的定義,

在ContentProvider中使用sqlite3保存對應的資料,

注意的是:在使用contentProvider更新完資料之后需要使用getContext().getContentResolver().notifyChange(uri,null);
通知資料已經改變

//9.3 作業系統的ContentProvider
實際上,android中本身提供了很多的ContentProvider, 例如聯系人資訊,系統的多媒體資訊等,

開發者可以使用ContentResolver物件來獲得系統中的資料

通過查閱對應的API檔案可以獲得想要訪問的系統contentProvider物件中的資料對應的Uri

//9.3.1 使用ContentProvider物件管理聯系人

Android中提供了Contacts應用程式來管理聯系人,而且還提供了provider

android要求訪問本身的contentProvider的時候需要用戶動態獲取權限

//重點:
android中的聯系人資訊是一張表(主表),開發者需要先向該主表中插入記錄,電話資訊是一張從表(參照聯系人表),
E-mail資訊單獨是一張從表(參照聯系人表),因此開發者可以分別為一個聯系人添加多個電話資訊、多個E-mail資訊,

//自己總結實作聯系人資訊獲得的邏輯:
先給一個按鈕注冊一個請求獲得動態訪問權限的按鈕,然后點擊之后到activity中的onRequestPermmissionResult()方法,
在該方法中定義兩個陣列一個是存盤聯系人姓名的陣列一個是用來存放聯系人對應的資料的陣列List<List>
details,使用contentResolver物件的.query()方法可以根據系統提供的聯系人Uri得到對應的資料,
,然后是使用while回圈遍歷所有的聯系人{
先得到聯系人的ID,得到聯系人的名字,然后向names集合中添加名字,使用contentResolver物件的查詢聯系人的電話號碼,
其中可以設定條件是使用的聯系人的CONTACT_ID,然后創建一個detail陣列,向該陣列中通過遍歷將本聯系人的電話號資料
加入其中,然后得到聯系人的E-mail,遍歷該陣列得到e-mail中對應的多個E-mail地址資料,并向該detial陣列中添加
對應的e-mail地址,最后,將每一次回圈得到的detail陣列添加到對應的details陣列中,
接著是獲得布局視圖,然后從該布局中得到對應的ExpandableListView物件,然后創建一個ExpandalbeListViewAdapter物件
其中的設定getGroupCount()回傳的是names陣列的長度;其中的getChildrenCount()回傳的是details中對應的position陣列的長度;
其中的getGroup()獲得對應的position處的組資料;其中的getChild()方法得到的是對應位置的子串列項的資料(也就是電話號碼和對應e-mail資料)
其中的getGroupId()方法得到的是第幾組;其中的childId()方法得到的是對應的第幾個子資料;其中的getGroupView()
方法決定的是每一個組選項的外觀;其中的getChildView()方法得到的是每一個子選項的外觀,最后為獲得布局中的ExpandableListView組件
設定對應的監聽器,從而實作了結果的顯示,
}

//9.3.2 使用ContentProvider管理多媒體內容
獲得對應的多媒體的Uri即可實作管理,

注意在使用RecyclerView的時候,需要給該物件設定一個recyclerView.
show.setLayoutManager(new LinearLayoutManager(this));
這樣的話才可以顯示出來組件,

//9.4 監聽 ContentProvider的資料改變
9.4.1 ContentObserver簡介:
需要向指定的uri注冊一個ContentObserver監聽器
提供了registerContentObserver(Uri uri,boolean notifyForDescendets,ContentObserver observer);

中間的引數設定為:false時候表示必須時Uri(content://abc)變化的時候才會監聽到改變;
但是設定為true的時候表示盡管有:content://abc//xyz 或 content://abc//foo 也會監聽到變化,

9.5 小節

/----------------------------------2020.1.2 17:46 晚上看筆記------------------------------------/
/第十章 Service 和 BroadcastReceiver
Service是四大組件中與Activity最相似的組件
Service一直在后臺運行,絕對不會到前臺來,有自己的生命周期,
BroadcastReceiver組件就像一個全域的事件監聽器,只不過它用于系統發出的Broadcast,
通過使用該物件可以在不同的應用程式之間通信,

10.1 service簡介

10.1.1 創建、配置Service

service組件生命周期方法:
IBinder onBind() 該方法時Service子類必須實作的方法,該方法回傳的是一個IBinder物件,應用程式可通過該物件與
service組件通信
onCreate() 方法該service第一次被創建后將立即回呼該方法,
onDestory() 該Service被關閉之前將會呼叫該方法
onStartCommand() 該方法的早期版本是void onStart(Intent intent,Int startId) 每次客戶端呼叫startService(Intent)
方法啟動該Service時都會回呼該方法,

onUnbind() 當該service上系結的所有客戶端斷開連接時將會回呼該方法,

在onCreate() 或 onStartCommand() 方法中定義相關業務代碼

設定Service組件中的process表示該組件處于某一個行程中(默認是處于該App所在的行程中)
android中的四大組件都可以通過該屬性指定運行的行程

啟動Service由兩種方式:
1.通過context的startService()方法 該方法啟動的service與訪問者之間沒有關聯,即使訪問者退出了,該service也仍然運行
2.通過context的bindService()方法,使用該方法啟動service訪問者與service系結在一起,訪問者一旦退出,service就終止,

10.1.2 啟動和停止service

多次啟動一個service不會多次呼叫onCreate()方法,但是會多次呼叫onStartCommand()方法

10,1.3 系結本地service并與之通信
如果Service和訪問者之間需要進行方法呼叫或交換資料,則應該使用bindService()方法 和 unBindService()方法,
bindService()方法中的引數:
其中的ServiceConnection conn,表示該物件用于監聽訪問者與service之間的連接情況,當訪問者與service之間
連接成功時將回呼該ServiceConnectionn物件的onServiceConnected(ComponentName name,IBinder service) 方法,當
service所在的宿主進行由于例外中止或其他原因終止,導致該service與訪問者之間斷開連接時回呼該serviceConnection
物件的onServiceDisconnected(ComponentName)方法,(但是當呼叫者主動斷開連接的時候onServiceDisconnected()方法不會被呼叫)

其中的引數flags表示系結時是否自動創建service,該引數為0時,表示不自動創建;該引數為BIND_AUTO_CREATE(自動創建)

注意到在ServiceConnection中的onService()方法中有一個IBinder物件可以用來進行通信,

在系結了本地service的情況下,onBind(Intent intent) 方法回傳的IBinder物件將會傳給ServiceConnection物件里
onServiceConnected()方法的service引數,這樣訪問者就可以通過該IBinder物件與Service進行通信,

實際上開發的時候將通常會繼承Binder類的方式實作自己的IBinder物件,

IBinder 將會傳給service的訪問者

多次呼叫bindService()不會多次系結

重點理解:
Service的生命周期:

onCreate()創建該Service之后立即呼叫的

如果需要該Service是由Activity的startService()方法啟動之外,還需要Service子類重寫onUnbind()方法時回傳true;

只有是通過bindService呼叫的在使用了unBindService()之后才會呼叫onDestory()方法,

當一個activity使用bindService呼叫一個已經啟動的service的時候只是可以得到對應的iBinder物件,
而在呼叫了對應的unBindService之后也不會使得該service徹底destroy

10.1.5 使用IntentService
Service存在的兩個問題:
1.Service不會專門啟動一個單獨的行程,與其所在的應用位于同一個行程中
2.Service不是一條新的執行緒,因此不應該在Service中處理耗時的任務

//重點//
為什么不可以直接在activity中直接創建一個新的執行緒,因為如果是直接創建一個新的執行緒,那么
由于activity本身會被用戶退出,并且是BroadCastReceiver的生命周期本身很短,那么會出現在子執行緒還沒有結束的
情況下,activity已經被用戶退出了,或是BroadcastRececiver已經結束了,這種情況下,此時它們所在的行程就
變成了空的行程,那么此時很可能被android的回識訓制回收那么對應的子執行緒還沒有執行完畢就結束了,

IntentService會使用佇列來管理請求的intent物件,每當客戶端代碼請求i的時候都會創建一個新的worker執行緒來處理
該Intent,
對于異步的startService(),IntentService會按照次序處理佇列中的intent請求,該執行緒保證同一時刻只處理一個intent,

并且IntentService會自動停止不需要開發者自己停止,

10.2 跨行程呼叫Service(AIDL Service)
IPC(跨行程通信)

10.2.1 AIDL Service(與java中的遠程RMI具有一定的相似之處)
與RMI不同的是,service只是將service物件的代理iBinder回傳給用戶,

因此AIDL遠程介面的實作類就是那個IBinder實作類,

遠程Service的onBind()方法只是將IBinder物件的代理傳給客戶端的ServiceConnection的onServiceConnected()方法
的第二個引數,

10.2.2 創建AIDL檔案(android介面定義語言)

AIDL介面的源代碼必須以.aidl結尾
在AIDL中用到的資料型別,除了基本型別之外,其他的型別都需要導包,即使在同一個包中也需要導包,

開發人員定義的AIDL介面只是定義了行程之間的通信介面,service端,客戶端都需要使用Android SDK安裝目錄下的build-tools子目錄下面
的aidl.exe工具為該介面提供實作,(使用AS會自動為該介面提供實作)

在定義好了AIDL介面之后,android studio工具會自動在build/generated/source/aidl/debug目錄下生成了一個XXX.java
介面,再改介面中包含了一個stub內部類,該內部類,該內部類實作了IBinder.ICat兩個介面,
這個Stub類將會作為遠程Service的回呼類–它實作了IBinder介面,因此可以作為Service的onBind()方法的回傳值,

如果沒有自動生成介面那么可以使用ctrl+F9 強制生成介面,

10.2.3 將介面暴露給客戶端
上一步定義好AIDL介面之后,接下來就可以定義一個Service實作類了,該Service的onBind()方法所回傳的IBinder物件
應該是ADT所生成的ICat.Stub的子類的實體,

10.2.4 客戶端訪問AIDL Service
AIDL介面在客戶端和服務器端都需要定義,
客戶端系結遠程service步驟:
1創建ServiceConnection物件
2.以ServiceConnection物件作為引數,呼叫Context的bindService()方法系結遠程Service即可,

使用AIDL介面的作用是:
服務器端 ---- AIDL介面 ----- 客戶端

Android將指定Component屬性,以及指定Package屬性的intent都當成顯式Intent,

//實體:傳遞復雜資料的AIDL Service
Android要求呼叫遠程Service的引數和回傳值都必須實作Parcelable介面,
實作該介面不僅需要的是實作該介面中的方法,而且要求在實作類中定義一個名為CREATOR、型別為Parcelable.Creator的靜態
常量,除此之外還要求使用AIDL代碼來定義這些自定義型別,
其中定義的Creator靜態常量是用來恢復自定義物件的,

Android中實作Parcelable介面是提供了一種輕量型的序列化機制,

在AIDL介面中定義方法時,需要指定形參的傳遞模式,

實作自定義復雜資料型別的AIDL訪問步驟:
1.先定義一個Person.aidl形的介面;緊接著定義一個對應Person.java型別的介面()其中定義一個CREATOR常量,目的是
實作對應的資料型別的轉換為序列化物件,(定義Pet型別的介面同上)
2.然后定義一個IPet.aidl通信介面,(其中指定的是定義一個Pet物件型別的list集合引數型別是
person型別的 并且使用了in表示傳入引數的形式)
3.然后實作一個繼承自Service的類,其中定義一個static常量,里面實作的是一些資料的初始化,
4.繼承對應的xxx.Stub(也就是實作了IPet介面,并實作了IBinder介面),并在onBind()方法中回傳對應的binder物件
5.然后實作客戶端的Activity的創建,通過在ServiceConnection實作類中的onServiceConnected()方法實作:
petService = IPet.Stub.adInterface(service);得到回傳來的物件代理然后進行處理得到Service物件

6.然后在onCreate()方法中得到對應的資料,并使用ArrayAdapter<> 進行包裝并顯示,

//同樣地,呼叫getSystemService(String name):根據Service名稱來獲得系統的Serivice

10.3 電話管理器(TelephoneManager)

10.4 短信管理器

10.5 音頻管理器AudioManager
10.5.1 簡介:
adjustStreamVolumn(int streamType,int direaction,int flag)
第一個引數:調整手機指定型別的聲音,
第二個引數:是調大還是調小
第三個引數:是設定調整聲音時的標志

setMicrophoneMute()表示設定是否讓麥克風靜音
setMode() 設定聲音模式,
setRingMode()設定手機的電話鈴聲模式,
setSpeakphone()設定是否打開擴音器
setStreamVolume直接設定手機的指定型別的音量值,

10.6 振動器(Vibrator)
10.6.1 Vibrator簡介

vibrator提供了如下的三個方法來創建振動效果:
creaeteOneShot() 創建只震動一次的振動效果
createWaveform創建波形振動的振動效果
createWaveform創建波形振動效果第二種

10.6.2 使用Vibrator控制手機振動

10.7 手機鬧鐘服務(AlarmManager)

10.7.1 AlermManager簡介

10.7.2 設定鬧鐘
AlermManager是一個全域定時器,即使在程式推出之后也會啟動指定組件,

10.8 廣播接收器(BroadcastReceiver 四大組件之一)
本質上是一個全域監聽器,可以方便實作不同系統之間的通信,
10.8.1 簡介:

用來接受程式發出的BroadcastIntent物件,
啟動BroadcastReceiver步驟:
1.創建需要啟動的BroadcastReceiver的Intent
2.呼叫Context的sendBroadcast()或sendOrderBroadcast()方法來啟動指定的BroadcastReceiver

指定該物件可以匹配的intent物件的兩種方式:
1.使用代碼指定,呼叫BroadcastReceiver的Context的registerReceiver(BroadcastReceiver xxx,
Intent intent); 方法指定
2.在AndroidManifest.xml檔案中配置,

注意:系統指定的BroadcastReceiver找不到時,系統也不會例外終止,

不要在receive中實作一個耗時的操作因為可能會導致ANR例外,
建議使用intent在一個service中進行耗時操作(建議使用IntentService)

10.8.2 發送廣播

10.8.3 有序廣播

Broadcast被分為兩種:
1.普通廣播 是完全異步的,可以在同一時刻被所有接收者收到,訊息的傳遞效率比較高,

2.有序廣播 接收者將按照預先宣告的優先級依次接受Broadcast,接收者的優先級可以在intent-filter/>
的periority中設定,

優先接收到Broadcast的接收者可以呼叫abortBroadcast()終止行程,
優先收到的接收者可以呼叫setResultExtras(Bundle)方法將處理結果存入Broadcast物件中
然后傳給下一個接收者,

下一個接收者可以通過Bundle bundle = getResultExtras(true);獲取上一個接收者存入的資料,

//實體:基于Service的音樂播放器

//10.9 接受系統廣播訊息

//實體:開機自動運行的Activity

//實體:手機電量顯示

sendStickyBroadcast():發送持續廣播

//------------------------截止到 p511(2020.1.3 凌晨1:14截至)------------------------//

用以記錄自己的學習程序,為了方便日后復習,

轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/244317.html

標籤:其他

上一篇:網路編程

下一篇:瀏覽器端判斷當前設備的運行環境

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【從零開始擼一個App】Dagger2

    Dagger2是一個IOC框架,一般用于Android平臺,第一次接觸的朋友,一定會被搞得暈頭轉向。它延續了Java平臺Spring框架代碼碎片化,注解滿天飛的傳統。嘗試將各處代碼片段串聯起來,理清思緒,真不是件容易的事。更不用說還有各版本細微的差別。 與Spring不同的是,Spring是通過反射 ......

    uj5u.com 2020-09-10 06:57:59 more
  • Flutter Weekly Issue 66

    新聞 Flutter 季度調研結果分享 教程 Flutter+FaaS一體化任務編排的思考與設計 詳解Dart中如何通過注解生成代碼 GitHub 用對了嗎?Flutter 團隊分享如何管理大型開源專案 插件 flutter-bubble-tab-indicator A Flutter librar ......

    uj5u.com 2020-09-10 06:58:52 more
  • Proguard 常用規則

    介紹 Proguard 入口,如何查看輸出,如何使用 keep 設定入口以及使用實體,如何配置壓縮,混淆,校驗等規則。

    ......

    uj5u.com 2020-09-10 06:59:00 more
  • Android 開發技術周報 Issue#292

    新聞 Android即將獲得類AirDrop功能:可向附近設備快速分享檔案 谷歌為安卓檔案管理應用引入可安全隱藏資料的Safe Folder功能 Android TV新主界面將顯示電影、電視節目和應用推薦內容 泄露的Android檔案暗示了傳說中的谷歌Pixel 5a與折疊屏新機 谷歌發布Andro ......

    uj5u.com 2020-09-10 07:00:37 more
  • AutoFitTextureView Error inflating class

    報錯: Binary XML file line #0: Binary XML file line #0: Error inflating class xxx.AutoFitTextureView 解決: <com.example.testy2.AutoFitTextureView android: ......

    uj5u.com 2020-09-10 07:00:41 more
  • 根據Uri,Cursor沒有獲取到對應的屬性

    Android: 背景:呼叫攝像頭,拍攝視頻,指定保存的地址,但是回傳的Cursor檔案,只有名稱和大小的屬性,沒有其他諸如時長,連ID屬性都沒有 使用 cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATIO ......

    uj5u.com 2020-09-10 07:00:44 more
  • Android連載29-持久化技術

    一、持久化技術 我們平時所使用的APP產生的資料,在記憶體中都是瞬時的,會隨著斷電、關機等丟失資料,因此android系統采用了持久化技術,用于存盤這些“瞬時”資料 持久化技術包括:檔案存盤、SharedPreference存盤以及資料庫存盤,還有更復雜的SD卡記憶體儲。 二、檔案存盤 最基本存盤方式, ......

    uj5u.com 2020-09-10 07:00:47 more
  • Android Camera2Video整合到自己專案里

    背景: Android專案里呼叫攝像頭拍攝視頻,原本使用的 MediaStore.ACTION_VIDEO_CAPTURE, 后來因專案需要,改成了camera2 1.Camera2Video 官方demo有點問題,下載后,不能直接整合到專案 問題1.多次拍攝視頻崩潰 問題2.雙擊record按鈕, ......

    uj5u.com 2020-09-10 07:00:50 more
  • Android 開發技術周報 Issue#293

    新聞 谷歌為Android TV開發者提供多種新功能 Android 11將自動填表功能整合到鍵盤輸入建議中 谷歌宣布Android Auto即將支持更多的導航和數字停車應用 谷歌Pixel 5只有XL版本 搭載驍龍765G且將比Pixel 4更便宜 [圖]Wear OS將迎來重磅更新:應用啟動時間 ......

    uj5u.com 2020-09-10 07:01:38 more
  • 海豚星空掃碼投屏 Android 接收端 SDK 集成 六步驟

    掃碼投屏,開放網路,獨占設備,不需要額外下載軟體,微信掃碼,發現設備。支持標準DLNA協議,支持倍速播放。視頻,音頻,圖片投屏。好點意思。還支持自定義基于 DLNA 擴展的操作動作。好像要收費,沒體驗。 這里簡單記錄一下集成程序。 一 跟目錄的build.gradle添加私有mevan倉庫 mave ......

    uj5u.com 2020-09-10 07:01:43 more
最新发布
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:40:31 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:40:11 more
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:39:36 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:39:13 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:16:23 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:16:15 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:15:46 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:14:53 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:14:08 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:08:34 more