持續更新中…
zcy 2021/8/14
文章目錄
- 一、開始啟程
- 1. 認識Android
- 2. 創建專案
- 3. 分析第一個Android程式結構
- 3.1 Project模式的專案結構
- 3.2 app目錄下的結構
- 3.3 res目錄下的結構
- 4. 一些error解決方法
- 二、探究Activity
- 1. 活動的基本用法
- 1.1 創建活動
- 1.2 Toast
- 1.3 Menu
- 1.4 銷毀一個活動
- 2. Intent 在活動之間穿梭
- 2.1 Intent簡介
- 2.2 顯式Intent
- 2.3 隱式Intent
- 2.4 更多隱式Intent的用法
- 2.5 向下一個activity傳遞資料
- 2.6 回傳資料給上一個活動
- 3. 活動的生命周期
- 3.1 回傳堆疊
- 3.2 Activity狀態
- 3.3 Activity生存期
- 3.4 活動被回收了怎么辦
- 4. 活動的啟動模式
- 三、UI開發的點滴
- 1. 常用控制元件的使用方法
- 1.1 TextView
- 1.2 Button
- 1.3 EditText
- 1.4 ImageView
一、開始啟程
1. 認識Android
Android 大致可以分為4層架構:Linux內核層、系統運行庫層、應用框架層和應用層
Android系統四大組件分別是Activity、Service、BroadcastReceiver和 ContentProvider
Android系統還自帶了這種輕量級、運算速度極快的嵌入式關系型資料庫, SQLite資料庫,它不僅支持標準 的SQL語法,還可以通過Android封裝好的API進行操作
2. 創建專案

Package name:表示專案的包名,Android系統就是通過包名來區分不同應用程式的,因此包名一定要具有唯一性
Language:這里默認選擇了Kotlin,在過去,Android應用程式只能使用 Java來進行開發,本書的前兩個版本也都是用Java語言講解的,然而在2017年,Google引入 了一款新的開發語言——Kotlin,并在2019年正式向廣大開發者公布了Kotlin First的訊息
Minimum API level:設定專案的最低兼容版本,Android 5.0以 上的系統已經占據了超過85%的Android市場份額,因此這里我們將Minimum SDK指定成API 21就可以了
3. 分析第一個Android程式結構
3.1 Project模式的專案結構

.gradle和.idea:放置的都是Android Studio自動生成的一些檔案
app:專案中的代碼、資源等內容都是放置在這個目錄下的,我們后面的開發作業也基本是在這 個目錄下進行的
gradle:這個目錄下包含了gradle wrapper的組態檔,使用gradle wrapper的方式不需要提前將gradle下載好,而是會自動根據本地的快取情況決定是否需要聯網下載gradle,Android Studio默認就是啟用gradle wrapper方式的,如果需要更改成離線模式,可以點擊Android Studio導航欄→ File → Settings → Build, Execution, Deployment → Gradle,進行配置更改
gitignore:用來將指定的目錄或檔案排除在版本控制之外的
build.gradle:專案全域的gradle構建腳本
gradle.properties:全域的gradle組態檔
gradlew和gradlew.bat:用來在命令列界面中執行gradle命令的,其中gradlew是在Linux或Mac系統,gradlew.bat是在Windows系統
local.properties:指定本機中的Android SDK路徑
settings.gradle:指定專案中所有引入的模塊
3.2 app目錄下的結構

build:包含了一些在編譯時自動生成的檔案
libs:放置第三方jar包
androidTest:撰寫測驗用例
java:放置我們所有Java代碼的地方(Kotlin代碼也放在這里)
res:專案中使用到的所有圖片、布局、字串等資源
AndroidManifest.xml:是整個Android專案的組態檔,你在程式中定義的所有四大組件都需要在這個檔案里注冊
test:撰寫Unit Test測驗用例
接下來分析一下HelloWorld專案究竟是如何運行起來的:
首先打開 AndroidManifest.xml,這段代碼表示對MainActivity進行注冊,intent-filter里的兩行代碼表示MainActivity是這個專案的主Activity
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
打開 MainActivity, 首先MainActivity是繼承自AppCompatActivity (AndroidX中提供的一種向下兼容的Activity),MainActivity中有一個onCreate()方法,里面呼叫了setContentView()方法,給當前的Activity引入了一個activity_main布局
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
打開 activity_main.xml,在 TextView中看到了“Hello World”的字樣,因為Android程式的設計講究邏輯和視圖分離,不推薦在Activity中直接撰寫界面,而是在布局檔案中撰寫界面
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" />
</androidx.constraintlayout.widget.ConstraintLayout>
3.3 res目錄下的結構

以“drawable”開頭的目錄:用來放圖片的
以“mipmap”開頭的目錄:用來放應用圖示的
以“values”開頭的目錄:放字串、樣式、顏色等配置的
以“layout”開頭的目錄:放布局檔案
我們應該如何使用這些資源呢,以字串為例,這里定義了一個應用程式名的字串,我們有以下兩種方式來參考它

- 在代碼中通過R.string.app_name可以獲得該字串的參考,
- 在XML中通過@string/app_name可以獲得該字串的參考
4. 一些error解決方法
ERROR: SSL peer shut down incorrectly錯誤解決(Android Studio)
錯誤資訊:ERROR: SSL peer shut down incorrectly
錯誤原因:是studio工具不支持https請求
方法一:右上角 SDK Manager 進入到視窗里面 → 選擇 SDK Update Sites 這個選項 → 勾選下方的 Force https// sources to be fetched using http// 選項 → 重啟Android Studio → 點擊右上大象圖示重新下載

方法二:
將 gradle-wrapper.properties 檔案里面的 distributionUrl=https 中的 https 改成 http,然后重新點擊上方的按鈕大象重新下載gradle檔案

二、探究Activity
Activity是一種可以包含用戶界面的組件,主要用于和用戶進行互動
1. 活動的基本用法
1.1 創建活動

Generate Layout File:會自動創建一個對應的布局檔案
Launcher Activity:會自動將這個Activity設定為當前專案的主Activity
專案中的任何Activity都應該重寫onCreate()方法,呼叫setContentView()方法來給當前的Activity加載一個布局,我們一般會傳入一個布局檔案的id
public class SecondActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
}
}
1.2 Toast
在程式中可以使用它將一些短小的資訊通知給用戶,一段時間后自動消失
在activity_main中添加一個button,并賦予id button_1
<Button
android:id="@+id/button_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="click"/>
在 onCreate() 方法中添加如下代碼:
通過 findViewById() 獲取在布局檔案中定義的button_1,該方法回傳的是一個繼承自View的泛型物件,因此需要向下轉型成Button物件
通過呼叫 setOnClickListener() 方法為按鈕注冊一個監聽器,點擊按鈕時就會執行監聽器中的 onClick() 方法,Toast的功能在 onClick() 方法中撰寫了
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn = (Button) findViewById(R.id.button_1);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(MainActivity.this,"you clicked btn1",
Toast.LENGTH_SHORT).show();
}
});
}
Toast的用法:
通過靜態方法 makeText() 創建出一個Toast物件,然后呼叫 show() 將Toast顯示出來
第一個引數是Context,就是Toast要求的背景關系,Activity本身就是一個Context物件,因此這里直接傳入this,第二個引數是Toast顯示的文本內容,第三個引數是Toast顯示的時長,有兩個內置常量可以選擇:Toast.LENGTH_SHORT 和 Toast.LENGTH_LONG
1.3 Menu
在res目錄下新建一個menu檔案夾,在menu檔案夾下新建一個選單檔案 main.xml,代碼如下,我們用 創建了兩個選單項
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/add_item"
android:title="add"></item>
<item
android:id="@+id/remove_item"
android:title="remove"></item>
</menu>
接著回到 MainActivity 來重寫 onCreateOptionsMenu() 方法,getMenuInflater() 方法能夠得到一 個MenuInflater 物件,再呼叫它的 inflate() 方法,就可以給當前Activity創建選單了
inflate() 兩個引數:第一個引數指定我們通過哪一個資源檔案來創建選單,第二個引數指定選單項將添加到哪一個Menu物件當中,這里直接使用 onCreateOptionsMenu() 方法中傳入的menu引數
回傳 true,表示允許創建的選單顯示出來
@Override
public boolean onCreateOptionsMenu(Menu menu){
getMenuInflater().inflate(R.menu.main,menu);
return true;
}
我們繼續給選單定義回應事件
在 MainActivity中重寫 onOptionsItemSelected() 方法,呼叫item.itemId來判斷點擊的是哪一個選單項
@Override
public boolean onOptionsItemSelected(MenuItem item){
switch (item.getItemId()) {
case R.id.add_item:
Toast.makeText(this, "You clicked Add",
Toast.LENGTH_SHORT).show();
break;
case R.id.remove_item:
Toast.makeText(this, "You clicked Remove",
Toast.LENGTH_SHORT).show();
break;
default:
}
return true;
}
效果圖如下

1.4 銷毀一個活動
按一下Back鍵,或者z在代碼里使用 finish() 方法
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finishi();
}
});
2. Intent 在活動之間穿梭
由一個Activity跳轉到另一個Activity
2.1 Intent簡介
Intent是Android程式中各組件之間進行互動的一種方式,不僅可以指明當前組件想要執行的動作,還可以在不同組件之間傳遞資料,一般可用于啟動Activity、啟動Service以及發送廣播等場景
2.2 顯式Intent
新建 SecondActivity.java 和 acitvity_second.xml,在布局檔案里加上按鈕id button_2
通過 Intent() 建構式就可以構建出 Intent 物件的“意圖”,第一個引數傳入 MainActivity.this 作為背景關系,第二個引數傳入 SecondActivity.class 作為目標 Activity
Activity類中提供了一個 startActivity() 方法,接收一個Intent引數,專門用于啟動Activity
Button btn = (Button) findViewById(R.id.button_1);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this,SecondActivity.class);
startActivity(intent);
}
});
2.3 隱式Intent
指定了一系列的action和category等資訊,交由系統去分析這個Intent,找出合適的Activity去啟動
打開 AndroidManifest.xml,通過在標簽 下配置 的內容,可以指定 SecondActivity 能夠回應的 action 和 category
<activity android:name=".SecondActivity">
<intent-filter>
<action android:name="com.example.chapter2.ACTION_START" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
修改MainActivity中按鈕的點擊事件,只有 和 中的內容同時匹配Intent建構式中指定的action和category時,這個Activity才能回應該Intent
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent("com.example.chapter2.ACTION_START");
startActivity(intent);
}
});
這里沒有指定 category 是因為 DEFAULT 是一種默認的 category,呼叫函式時會自動添加進去
每個Intent中只能指定一個action,但能指定多個 category,在 MainActivity.java 里面呼叫 intent.addCategory(),再在SecondActivity的 加上一個新的 ,否則會報錯
Intent intent = new Intent(MainActivity.this,SecondActivity.class);
intent.addCategory("com.example.chapter2.MY_CATEGORY");
startActivity(intent);
<action android:name="com.example.chapter2.ACTION_START" />
<category android:name="com.example.chapter2.MY_CATEGORY"/>
<category android:name="android.intent.category.DEFAULT" />
2.4 更多隱式Intent的用法
不僅可以啟動自己程式內的Activity,還可以啟動其他程式的Activity
-
Intent.ACTION_VIEW
首先指定了Intent的action是Intent.ACTION_VIEW,然后通過==Uri.parse()==方法將一個網址字串決議成一個Uri物件,再呼叫Intent的 setData() 方法將這個Uri物件傳遞進去
btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse("https://www.baidu.com")); startActivity(intent); } }); -
Intent.ACTION_DIAL
btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(Intent.ACTION_DIAL); intent.setData(Uri.parse("tel:10086")); startActivity(intent); } });點擊按鈕效果如圖

2.5 向下一個activity傳遞資料
Intent中提供了一系列 putExtra() 方法的多載,可以把我們想要傳遞的資料暫存在Intent中,在啟動另一個Activity后,只需要把這些資料從Intent中取出就可以了
例如要把MainActivity中的字串傳遞到SecondActivity中:
使用顯式Intent的方式來啟動SecondActivity,并通過 putExtra() 方法傳遞了一個字串,第一個引數是鍵,用于之后從 Intent 中取值,第二個引數才是真正要傳遞的資料
btn1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String data = "this is from MainActivity";
Intent intent = new Intent(MainActivity.this,SecondActivity.class);
intent.putExtra("extra_data",data);
startActivity(intent);
}
});
在 SecondActivity中,呼叫父類的 getIntent() 方法,獲取用于啟動 SecondActivity的Intent,然后呼叫 getStringExtra() 方法傳入相應的鍵值
傳遞字串:getStringExtra()
傳遞整型資料:getIntExtra()
傳遞布林值:getBooleanExtra()
public class SecondActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
Intent intent = getIntent();
String data = intent.getStringExtra("extra_data");
Log.d("SecondActivity",data);
}
}
2.6 回傳資料給上一個活動
Activity有一個用于啟動Activity的 startActivityForResult() 方法,它期望在Activity銷毀的時候能夠回傳一個結果給上一個Activity
① 修改MainActivity代碼
用 startActivityForResult() 來啟動活動,第一個引數還是Intent,第二個引數是請求碼,用于在之后的回呼中判斷資料的來源
btn1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this,SecondActivity.class);
startActivityForResult(intent,1);
}
});
在 SecondActivity被銷毀之后會回呼上一個Activity的 onActivityResult() 方法,第一個引數是在啟動 Activity 時傳入的請求碼,第二個引數是在回傳資料時傳入的處理結果;第三個引數即攜帶著回傳資料的Intent
@Override
protected void onActivityResult(int rqCode, int resCode, Intent data) {
switch (rqCode) {
case 1:
if(resCode == RESULT_OK) {
String returnData = data.getStringExtra("data_return");
Log.d("MainActivity",returnData);
}
}
}
② 修改SecondActivity代碼:
構建一個Intent物件,僅用來傳遞資料,不指定任何意圖
后呼叫了==setResult()==方法,專門用于向上一個Activity回傳資料,第一個引數用于向上一個Activity回傳處理結果(RESULT_OK 或 RESULT_CANCELED),第二個引數把帶有資料的Intent傳遞回去
Button btn2 = (Button) findViewById(R.id.button_2);
btn2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent();
intent.putExtra("data_return","this is from SecondActivity");
setResult(RESULT_OK,intent);
finish();
}
});
如果用戶在SecondActivity中并不是通過點擊按鈕,而是通過按下Back鍵回到 FirstActivity,通過在SecondActivity中重寫 onBackPressed() 方法來解決
@Override
public void onBackPressed(){
Intent intent = new Intent();
intent.putExtra("data_return","this is from SecondActivity");
setResult(RESULT_OK,intent);
finish();
}
3. 活動的生命周期
3.1 回傳堆疊
Android中的Activity是可以層疊的,新活動覆寫在舊活動上
Android是使用任務(task)來管理Activity的,一個任務就是一組存放在堆疊里的Activity 的集合,這個堆疊稱作回傳堆疊(back stack)

3.2 Activity狀態
- 運行:位于回傳堆疊的頂部,系統最不愿意回收
- 暫停:不在堆疊頂,但仍可見(例如對話框的背后),暫停狀態仍是完全存活的,系統不愿意回收
- 停止:不在堆疊頂,完全不可見,系統仍保為這個活動保存狀態和成員變數,但在記憶體緊張會被回收
- 銷毀:從回傳堆疊移除,系統傾向回收,節約記憶體
3.3 Activity生存期
完整生存期 ,onCreate —— onDestroy,初始化 —— 釋放記憶體
可見生存期,onStart —— onStop,不可見 —— 可見時呼叫
前臺展示生存期,onResume —— onPause
-
onCreate,初始化,比如加載布局、系結事件
-
onStart,不可見到可見時呼叫
-
onResume,和用戶互動前進行呼叫,此時一定位于堆疊頂,處于運行狀態
-
onPause,在系統切換到另一個ACT時呼叫
-
onStop,完全不可見時呼叫
-
onDestroy,在銷毀前被呼叫
-
onRestart,從停止變為運行時呼叫,也就是Activity 被重新啟動了

3.4 活動被回收了怎么辦
Activity被回收前,系統會呼叫一個方法==onSaveInstanceState()==來保存用戶的資料,在 onPause 和onStop 之間,解決活動被回收臨時資料得不到保留的問題
在 MainActivity 中寫入函式
@Override
protected void onSaveInstanceState(Bundle outState){
super.onSaveInstanceState(outState);
String temp = "something you just typed";
outState.putString("data_kay",temp);
}
我們一直使用的onCreate()方法也有一個Bundle引數,如果在Activity被系統回收之前,通過onSaveInstanceState()方法保存資料,這個引數就會帶有之前保存的全部資料,只需要將資料取出即可
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(savedInstanceState != null){
String temp = savedInstanceState.getString("data_key");
log.d(TAG,temp);
}
}
4. 活動的啟動模式
在實際專案中我們應該根據特定的需求為每個Activity指定恰當的啟動模式,可以在AndroidManifest.xml中通過給標簽指定 android:launchMode 屬性來選擇啟動模式
-
standard,默認的啟動模式,每次創建都會產生一個新的,放在堆疊頂,不在乎以前是否創建過(單體可回圈,默認情況)
-
singleTop,每次創建時,如果發現堆疊頂是本身,就不再創建,否則就創建(交替可回圈)
android:launchMode="singleTop" -
singleTask,每次啟動,系統首先會在回傳堆疊中檢查是否存在該Activity,如果已經存在則直接使用該實體, 并把在這個Activity之上的所有其他Activity統統出堆疊
-
singleInstance,真正單態模式,自身擁有一個回傳堆疊
三、UI開發的點滴
1. 常用控制元件的使用方法
1.1 TextView
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="This is TextView"/>
android:id 定義唯一識別符號
android:text 文本內容
android:textColor 文字的顏色
android:textSize 文字的大小,文字大小使用sp作為單位
android:layout_width 控制元件的寬度
android:layout_height 控制元件的高度(match_parent、wrap_content、固定值,單位一般用dp)
android:gravity 文字的對齊方式(top、bottom、start、 end、center、center_vertical、center_horizontal)
1.2 Button
<Button
android:id="@+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Button" />
android:textAllCaps=“false” 系統就會保留你指定的原始文字內容
在MainActivity中為Button的點擊事件注冊一個監聽器
Button btn1 = (Button) findViewById(R.id.button_1);
btn1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//在此處添加邏輯
}
});
如果不喜歡匿名注冊,也可以使用實作介面的方式來進行注冊
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn1 = (Button) findViewById(R.id.button_1);
btn1.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button_1:
//在此處添加邏輯
break;
default:
break;
}
}
1.3 EditText
允許用戶在控制元件里輸入和編輯內容,并可以在程式中對這些內容進行處理
<EditText
android:id="@+id/editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Type something here"
android:maxLines="2"
/>
android:hint 指定一段提示性的文本
android:maxLines 指定了EditText的最大行數
通過點擊按鈕獲取EditText中輸入的內容:
呼叫EditText的 getText() 方法獲取輸入的內容,再呼叫toString() 方法將內容轉換成字串
private EditText editText;
private Button btn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText = (EditText) findViewById(R.id.edit_Text);
btn = (Button) findViewById(R.id.button_1);
btn.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button_1:
String input = editText.getText().toString();
Toast.makeText(MainActivity.this,input,Toast.LENGTH_SHORT).show();
break;
default:
break;
}
}
1.4 ImageView
<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/img_1"
/>
寬和高都設定為wrap_content,保證了不管圖片的尺寸是多少,都可以完整地展示出來
還可以在程式中通過代碼動態地更改ImageView中的圖片
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/294003.html
標籤:其他
上一篇:解決去年寫的代碼AS打開標紅問題
