一、Activity
- 組件的概念
- Android 中的主要組件包括活動(dòng)(
Activity)、服務(wù)(Service)、廣播接收器(Broadcast Receiver)和內(nèi)容提供者(Content Provider);
- Android 中的主要組件包括活動(dòng)(
1、繼承關(guān)系
java.lang.Object
? android.content.Context
? android.content.ContextWrapper
? android.view.ContextThemeWrapper
? android.app.Activity
- 通過(guò)這種繼承,
Activity就集成了Context的能力,可以訪問(wèn)資源、數(shù)據(jù)庫(kù)、SharedPreferences等; - 同時(shí)作為
Context的子類,Activity也可以作為Context參數(shù)被傳遞使用; - 這種繼承關(guān)系讓
Activity既是一個(gè)UI組件,也是一個(gè)Context,很好地結(jié)合了兩者的功能。
2、簡(jiǎn)介
-
Activity代表應(yīng)用程序的單個(gè)屏幕,用戶可以使用該屏幕執(zhí)行單一、集中的任務(wù),Activity 通常以全屏窗口的形式呈現(xiàn)給用戶; -
Activity是一個(gè)應(yīng)用程序組件,單個(gè)用戶任務(wù)的單個(gè)屏幕; - 每個(gè)
Activity都有自己的布局文件; - 可以為
Activity分配父子關(guān)系,以在應(yīng)用程序中啟用向上導(dǎo)航; - 一個(gè)應(yīng)用程序通常由多個(gè)彼此松散的屏幕組成;每個(gè)屏幕都是一個(gè) Activity;
- 應(yīng)用程序中有一個(gè)
主Activity(MainActivity.java),在應(yīng)用程序啟動(dòng)時(shí)呈現(xiàn)給用戶;通過(guò)主Activity可以啟動(dòng)其他 Activity來(lái)執(zhí)行不同的操作; - 每次啟動(dòng)
新 Activity,前一個(gè) Activity 都會(huì)停止,但系統(tǒng)會(huì)將該 Activity 保留在堆棧中;當(dāng)新 Activity 啟動(dòng)時(shí),該新 Activity 被推入后臺(tái)堆棧并獲取用戶焦點(diǎn);當(dāng)用戶完成當(dāng)前 Activity 并按下后退按鈕時(shí),該 Activity 將從堆棧中彈出并銷毀,并恢復(fù)上一個(gè) Activity; -
Intent是一條異步消息,可以在 Activity 中使用它來(lái)請(qǐng)求來(lái)自另一個(gè) Activity 或某個(gè)其他應(yīng)用程序組件的操作;可以使用 Intent 從一個(gè) Activity 啟動(dòng)另一個(gè) Activity,并在 Activity 之前傳遞數(shù)據(jù);
二、Intent
1、簡(jiǎn)介
- 允許從應(yīng)用程序中的另一個(gè)組件請(qǐng)求操作。例如,從另一個(gè)組件啟動(dòng)一個(gè)
Activity; - 顯示
Intent:可以指示接收數(shù)據(jù)的特定目標(biāo)組件; -
Intent附加信息是Bundle(鍵值對(duì));
2、知識(shí)點(diǎn)
- 是什么
-
Intent是一種用于在應(yīng)用程序的不同組件之間進(jìn)行通信的機(jī)制;
-
- 作用
- 允許應(yīng)用程序中的一個(gè)組件向另一個(gè)組件發(fā)送請(qǐng)求,以便執(zhí)行某種操作或進(jìn)行交換;
- 通過(guò)使用
Intent,不同組件可以進(jìn)行解耦,實(shí)現(xiàn)模塊化和靈活的交互;
- 用途
- 啟動(dòng)
Activity:通過(guò)指定目標(biāo) Activity 的類名或其它標(biāo)識(shí),可以告訴系統(tǒng)啟動(dòng)相應(yīng)的 Activity,并傳遞數(shù)據(jù)或參數(shù); - 啟動(dòng)服務(wù)
Service:以用于啟動(dòng)服務(wù),以在后臺(tái)執(zhí)行某些任務(wù)或處理長(zhǎng)時(shí)間運(yùn)行的操作; - 發(fā)送廣播
Broadcast- 通過(guò)發(fā)送
Intent廣播,可以通知其他組件或應(yīng)用程序發(fā)生了某個(gè)事件,以便它們采取相應(yīng)的操作;
- 通過(guò)發(fā)送
- 傳遞數(shù)據(jù)
-
Intent可以承載數(shù)據(jù),可以通過(guò)extra數(shù)據(jù)來(lái)傳遞附加信息給目標(biāo)組件。數(shù)據(jù)可以為基本數(shù)據(jù)類型也可以為對(duì)象類型;
-
- 啟動(dòng)
3、實(shí)現(xiàn)
1)兩個(gè)頁(yè)面之間傳遞數(shù)據(jù)
- 場(chǎng)景:將一個(gè)
Activity的數(shù)據(jù)傳送給另一個(gè)Activity;- 實(shí)現(xiàn)思路 :將要傳遞的數(shù)據(jù)掛到
Intent里面,通過(guò)Intent將數(shù)據(jù)進(jìn)行傳遞; - 實(shí)現(xiàn)方式
- 分散傳遞
Intent intent = new Intent(this, Activity2.class); //' 當(dāng)前的頁(yè)面?zhèn)鞯紸ctivity2 // 可以分別傳遞多條不同類型的數(shù)據(jù) Intent.putExtra("userName", "Yjx"); // 鍵值對(duì) Intent.putExtra("age", 18); Intent.putExtra("isLogin", false); startActivity(intent); ``` * 打包傳遞——`Bundle` * Bundle 類來(lái)打包數(shù)據(jù)來(lái)進(jìn)行傳遞; * 打多個(gè)包傳遞——給 Bundle 起個(gè)名字; * 傳遞對(duì)象類型的數(shù)據(jù) * 場(chǎng)景:傳遞一個(gè)自定義的對(duì)象(`JavaBean`),將數(shù)據(jù)和函數(shù)封裝成一個(gè)對(duì)象,一下子全部傳遞過(guò)去; * 傳遞過(guò)程中,對(duì)象與基本類型數(shù)據(jù)的區(qū)別,就是多了 `序列化`; * 序列化:可以簡(jiǎn)單理解為使得對(duì)象在數(shù)據(jù)流中方便地進(jìn)行傳遞;即將對(duì)象可以變成可以傳遞的數(shù)據(jù),反序列化就是傳遞過(guò)去之后可以將對(duì)象解析出來(lái); * 對(duì)象序列化的方式(強(qiáng)制類型轉(zhuǎn)換為 `Serializable` 和 `Parcelable`)``` // 傳遞對(duì)象(在 Activity A) // 寫在控件監(jiān)聽事件中 Intent intent = new Intent(this, Activity.class); User user = new User(); intent.putExtra("user", (Serializable) user); startActivity(intent); ``` ``` // 接收對(duì)象(在 Activity B) // 寫在 onCreate() 函數(shù)中 Intent intent = getIntent(); if (intent != null) { User user = (User) intent.getSerializableExtra("user"); } ```
- 實(shí)現(xiàn)思路 :將要傳遞的數(shù)據(jù)掛到
2)回傳數(shù)據(jù)
- 應(yīng)用場(chǎng)景:在個(gè)人信息頁(yè)面修改完個(gè)人信息回退到上一個(gè)頁(yè)面;
- 一個(gè)
Activity跳轉(zhuǎn)到Activity1,并希望從Activity1回到Activity的時(shí)候,收到Activity1帶回來(lái)的數(shù)據(jù);
4、顯示跳轉(zhuǎn)和隱式跳轉(zhuǎn)
- 應(yīng)用場(chǎng)景
- 顯示跳轉(zhuǎn):跳轉(zhuǎn)當(dāng)前應(yīng)用
app內(nèi)的頁(yè)面用顯示跳轉(zhuǎn)方式即可; - 隱式跳轉(zhuǎn):主要用于往其它應(yīng)用
app的頁(yè)面進(jìn)行跳轉(zhuǎn);
- 顯示跳轉(zhuǎn):跳轉(zhuǎn)當(dāng)前應(yīng)用
- 隱式的理解
- 從一個(gè)頁(yè)面跳轉(zhuǎn)到另一個(gè)頁(yè)面,不需要明確的指明要跳轉(zhuǎn)到哪個(gè)頁(yè)面,而是通過(guò)條件篩選確定目的頁(yè)面;
- 隱式跳轉(zhuǎn)的流程
- 目的:從一個(gè)源
Activity跳轉(zhuǎn)到目標(biāo)Activity; - 通過(guò)
intent設(shè)置條件- 顯示啟動(dòng)
- 通過(guò)設(shè)置好源和目的地,明確地告訴它從某個(gè)地方跳轉(zhuǎn)到某個(gè)地方;
- 隱式啟動(dòng)
- Intent 設(shè)置條件;
- 系統(tǒng)會(huì)遍歷 Manifest 文件,查詢找到符合條件的 Activity
- 查詢:通過(guò) Activity 標(biāo)簽下的 (過(guò)濾器)篩選符合條件的 Activity;
- 如果匹配(符合條件),就可以認(rèn)為 Intent 打開這個(gè) 目標(biāo) Activity ;
- 如果符合條件的有多個(gè) Activity,系統(tǒng)就會(huì)將符合條件的給你列出來(lái),讓用戶去選擇;
- 顯示啟動(dòng)
- 目的:從一個(gè)源
5、步驟
- 1)在 Intent 代碼中設(shè)置條件
- 2)在 Mainfest 條件中設(shè)置過(guò)濾條件 想要此 Acitivty 被其它頁(yè)面跳轉(zhuǎn)過(guò)來(lái)時(shí)才需要寫過(guò)濾條件
- 一種是自定義的條件:用來(lái)跳轉(zhuǎn)到自己寫的頁(yè)面
- 一種是系統(tǒng)提供的條件:用來(lái)跳轉(zhuǎn)到系統(tǒng)其他 app 的頁(yè)面(常用);
三、Context
- 是什么
- 可以理解為:
“從哪里來(lái)”;告訴我們當(dāng)前代碼是從哪里來(lái)的,是隸屬于誰(shuí)的;
- 可以理解為:
class MainActivity extends AppCompatActivity {
btnToastShort.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 這個(gè)this的類型是context,表明:因?yàn)?Toast 是在 MainActivity 這個(gè)類中
// context 傳入this,表明當(dāng)前產(chǎn)生 Toast 是MainActivity我讓你做的,是從我這里來(lái)的
Toast.makeText(MainActivity.this, "你點(diǎn)擊了", Toast.LENGTH_SHORT).show();
}
});
}
因?yàn)?
onClick方法被匿名內(nèi)部類包裹著,處于匿名內(nèi)部類中,則這里的this表示的當(dāng)前匿名內(nèi)部類的對(duì)象;這里不能用this,這里的this表示的是匿名內(nèi)部類的對(duì)象;作用:用來(lái)訪問(wèn)全局信息(應(yīng)用程序的資源,圖片資源、字符串資源),一些常用的組件(Activity、Service)繼承自 Context(繼承后具有訪問(wèn)全局資源的能力),目的是通過(guò) Context 方便地訪問(wèn)資源;
-
getContext():獲取相關(guān)的 Context 對(duì)象,getResource():獲取資源管理器,getText(id):返回資源 id 的字符串;// 訪問(wèn)字符串資源 public class MainActivity extends AppCompatActivity { private TextView tv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); tv = new TextView(this); // this:MainActivity的實(shí)例,將this傳給context,在內(nèi)部對(duì)context有一個(gè)引用 tv.setText(R.string.hello_world); setContentView(tv); // 指定一個(gè)視圖 } }// 訪問(wèn)圖片資源 public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ImageView iv = new ImageView(this); iv.setImageResource(R.mipmap.ic_launcher); } }
四、實(shí)踐 Lab
1、需求
- 創(chuàng)建并構(gòu)建兩個(gè) Activity(
Activity1和Activity2); -
Activity1作為主 Activity,主要包含一個(gè) “發(fā)送” 按鈕,當(dāng)用戶點(diǎn)擊此按鈕將使用Intent來(lái)啟動(dòng)Activity2;
- 主 Activity 中添加 EditText,用戶輸入消息,并點(diǎn)擊發(fā)送按鈕,主 Activity 使用 Intent 來(lái)啟動(dòng)第二個(gè) Activity 并將用戶的消息發(fā)送到第二個(gè) Activity,第二個(gè) Activity 顯示它接收到的消息
- 第二個(gè) Activity 添加 EditText 和回復(fù)按鈕;用戶鍵入回復(fù)消息并點(diǎn)擊回復(fù)按鈕,使用 Intent 將回復(fù)消息從第二個(gè) Activity 傳遞給主 Activity,并顯示;
2、代碼實(shí)現(xiàn)
- 創(chuàng)建第一個(gè)Activity 布局
// activity_main.xml(主Activity)
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/button_main"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:layout_marginRight="16dp"
android:textColor="@android:color/background_dark"
android:layout_marginBottom="16dp"
android:onClick="launchSecondActivity"
android:text="@string/button_main" />
<EditText
android:id="@+id/editText_main"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
android:layout_alignParentBottom="true"
android:layout_marginStart="32dp"
android:layout_marginLeft="32dp"
android:layout_marginBottom="19dp"
android:ems="10"
android:inputType="text"
android:text="Name" />
</RelativeLayout>
- 創(chuàng)建第二個(gè)Activity 布局
// 第二個(gè)Activity
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".SecondActivity">
<TextView
android:id="@+id/text_header"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="16dp"
android:text="@string/text_header"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/text_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="60dp"
android:layout_marginTop="40dp"
android:text=""
android:textAppearance="AppCompat.Medium"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/text_header" />
</androidx.constraintlayout.widget.ConstraintLayout>
- 主 Activity 添加 Intent
public void launchSecondActivity(View view) {
// 將顯示Intent添加到主Activity,Intent用于單擊發(fā)送按鈕時(shí)激活第二個(gè)Activity
// 參數(shù):第一個(gè)參數(shù),應(yīng)用程序Context;第二個(gè)參數(shù):將接收該Intent的特定組件
// 當(dāng)點(diǎn)擊發(fā)送按鈕時(shí),MainActivity發(fā)送Intent并啟動(dòng)第二個(gè)Activity 出現(xiàn)在屏幕
Intent intent = new Intent(this, SecondActivity.class);
startActivity(intent);
}
}
-
從主 Activity 發(fā)送數(shù)據(jù)到第二個(gè) Activity
- 使用 Intent 將數(shù)據(jù)從一個(gè) Activity 發(fā)送到另一個(gè) Activity
- Intent 傳遞數(shù)據(jù)到目標(biāo) Activity 的方式
- 1)數(shù)據(jù)字段:Intent 數(shù)據(jù)指要操作的特定數(shù)據(jù)的 URl
- 2)Intent 附加信息,如果傳遞的數(shù)據(jù)不是 URl 或想要發(fā)送多條信息,可以將附加信息放入
extras中。 - Intent 附加信息內(nèi)容是
Bundle。Bundle 是數(shù)據(jù)集合,存儲(chǔ)形式為鍵值對(duì); - 從一個(gè) Activity 傳遞信息到另一個(gè) Activity,可以將鍵和值放入發(fā)送 Activity 的 Intent extra 中,然后在接收 Activity 中將它們?nèi)〕觯?/li>
Bundle 中包含其他數(shù)據(jù),本需求中為用戶輸入的字符串
public class MainActivity extends AppCompatActivity {
private static final String LOG_TAG = MainActivity.class.getSimpleName();
public static final String EXTRA_MESSAGE = "com.example.myapplication.extra.MESSAGE";
private EditText mMessageEditText;
public static final int TEXT_REQUEST = 1; // 第二個(gè)Activity回復(fù)響應(yīng)的鍵
private TextView mReplyHeadTextView; // 回復(fù)標(biāo)頭Textview
private TextView mReplyTextView; // 回復(fù)TextView元素
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); // 指定一個(gè)視圖
mMessageEditText = findViewById(R.id.editText_main); // 使用findViewById()獲取對(duì) EditText 的引用
mReplyHeadTextView = findViewById(R.id.text_header_reply);
mReplyTextView = findViewById(R.id.text_message_reply);
}
public void launchSecondActivity(View view) {
// 將顯示Intent添加到主Activity,Intent用于單擊發(fā)送按鈕時(shí)激活第二個(gè)Activity
// 參數(shù)1:應(yīng)用程序Context和將接收該Intent的特定組件
// 當(dāng)點(diǎn)擊發(fā)送按鈕時(shí),MainActivity發(fā)送Intent并啟動(dòng)第二個(gè)Activity 出現(xiàn)在屏幕
Intent intent = new Intent(this, SecondActivity.class);
String message = mMessageEditText.getText().toString();
intent.putExtra(EXTRA_MESSAGE, message);
startActivityForResult(intent, TEXT_REQUEST);
}
@Override
// 回調(diào)方法
// requestCode:請(qǐng)求
public void onActivityResult(int requestCode, int resultCode, Intent data) {
// 處理返回?cái)?shù)據(jù)
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == TEXT_REQUEST) {
if (requestCode == RESULT_OK) {
String reply =
data.getStringExtra(SecondActivity.EXTRA_REPLY);
mReplyHeadTextView.setVisibility(View.VISIBLE);
mReplyTextView.setText(reply);
mReplyTextView.setVisibility(View.VISIBLE);
}
}
}
}
- 將數(shù)據(jù)從第二個(gè) Activity 返回給主 Activity startActivity():使用顯式 Intent 啟動(dòng)另一個(gè) Activity 時(shí),不會(huì)期望返回任何數(shù)據(jù),只是激活該 Activity; 如果想從激活的 Activity 中獲取數(shù)據(jù),則需要以 startActivityForResult() 啟動(dòng)它
public class SecondActivity extends AppCompatActivity {
public static final String EXTRA_REPLY = "com.example.myapplication.extra.REPLY";
private EditText mReply;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
mReply = findViewById(R.id.editText_second);
// 獲取激活此Activit的Intent
Intent intent = getIntent();
// 獲取Intent extra中包含的字符串
String message = intent.getStringExtra(MainActivity.EXTRA_MESSAGE);
// 獲取要顯示的控件的引用
TextView textView = findViewById(R.id.text_message);
// 通過(guò)引用在此控件上顯示獲取Intent extra中包含的字符串
textView.setText(message);
}
public void returnReply(View view) {
String reply = mReply.getText().toString();
Intent replyIntent = new Intent();
replyIntent.putExtra(EXTRA_REPLY, reply);
setResult(RESULT_OK, replyIntent);
finish();
}
}