本文整理了 Android 课程期末复习题,覆盖 Intent、四大组件、广播、数据存储、ContentProvider、Fragment、SQLite、Service 等核心知识点,并给出完整参考答案。
一、论述题
1. 论述 Intent 的两种类型:显式 Intent 和隐式 Intent 的定义,并说明它们分别应用于哪些场合
显式 Intent(Explicit Intent): 通过直接指定目标组件的类名(Component)来启动组件。需要明确知道目标 Activity / Service 的具体类。
Intent intent = new Intent(MainActivity.this, SecondActivity.class);startActivity(intent);应用场合:用于同一个应用内部组件之间的跳转,开发者明确知道要启动哪个组件。
隐式 Intent(Implicit Intent): 不指定具体组件名,而是通过 Action、Category、Data 等信息描述要执行的操作,由系统根据 IntentFilter 匹配合适的组件。
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.baidu.com"));startActivity(intent);应用场合:用于跨应用调用,例如调用系统的拨号、浏览器、相机、地图、发送短信等功能,或者调用第三方应用提供的能力。
2. Android 采用分层结构,从高到低分为几层,用途分别是什么?
Android 系统从高到低分为 4 层:
| 层级 | 名称 | 用途 |
|---|---|---|
| 第 1 层 | 应用程序层(Applications) | 系统自带和第三方安装的应用,如电话、短信、浏览器、相机等 |
| 第 2 层 | 应用程序框架层(Application Framework) | 为开发者提供构建应用的各种 API,如 Activity Manager、Window Manager、Content Provider、View System 等 |
| 第 3 层 | 系统运行库层(Libraries + Android Runtime) | C/C++ 库(如 SQLite、OpenGL、WebKit、SSL)及 Android 运行时(核心库 + Dalvik/ART 虚拟机) |
| 第 4 层 | Linux 内核层(Linux Kernel) | 提供系统底层服务:进程管理、内存管理、驱动程序(显示、相机、Wi-Fi、音频等)、安全机制 |
3. 论述广播在 Android 中的作用,说明广播的两种注册方式有什么不同,应用场合分别是哪些?
广播的作用: 广播(Broadcast)是 Android 中实现组件间、应用间通信的一种机制。系统或应用可以发出广播消息,其他注册了对应广播接收器(BroadcastReceiver)的组件可以接收并处理这些消息,从而实现解耦的事件通知(如开机完成、电量变化、网络变化、来电等)。
两种注册方式:
| 比较项 | 静态注册(清单注册) | 动态注册(代码注册) |
|---|---|---|
| 注册位置 | AndroidManifest.xml 中 <receiver> 标签 | 在代码中调用 registerReceiver() |
| 生命周期 | 应用未启动也能接收(常驻) | 跟随注册组件的生命周期,需要 unregisterReceiver() 注销 |
| 应用场合 | 接收系统级、长期性的广播,如开机启动、网络变化(注:Android 8.0 之后大多数隐式广播被禁止静态注册) | 接收特定时段、特定页面关心的广播,如 Activity 运行期间监听电量、自定义业务事件 |
4. 论述 Android 中常见的数据存储有哪些?分别有什么特点
Android 提供 5 种主要的数据存储方式:
-
SharedPreferences(轻量级键值存储)
- 特点:基于 XML 文件,以 key-value 方式保存,只能存储基本数据类型(boolean、int、float、long、String)。适合保存用户设置、配置参数等少量数据。
-
文件存储(Internal / External Storage)
- 特点:以 IO 流的形式将数据存储到内部或外部存储。内部存储是私有的,外部存储(SD 卡)可被其他应用读取。适合存储较大的文本、二进制文件。
-
SQLite 数据库
- 特点:轻量级关系型数据库,支持标准 SQL 语法,事务、索引。适合存储结构化、数据量较大的数据,如联系人、聊天记录。
-
ContentProvider(内容提供者)
- 特点:为不同应用之间共享数据提供统一接口,通过 URI 访问。适合跨应用共享数据,如系统通讯录、媒体库。
-
网络存储(Network Storage)
- 特点:将数据存储到远程服务器(云端),通过 HTTP / WebService 等方式访问。适合需要多端同步的数据。
5. ContentProvider 和 ContentResolver 应用程序间实现共享数据是如何实现的?
实现原理:
-
ContentProvider(内容提供者):数据提供方应用继承
ContentProvider类,重写onCreate()、query()、insert()、update()、delete()、getType()六个方法,将自己内部的数据(通常是 SQLite)通过统一的 URI 暴露出来,并在AndroidManifest.xml中通过<provider>标签注册,指定authorities。 -
ContentResolver(内容解析者):数据使用方应用通过
Context.getContentResolver()获取 ContentResolver 实例,调用其query()、insert()、update()、delete()方法,传入对应的 URI(格式为content://authorities/path)。
工作流程:
- 提供方在 ContentProvider 中实现数据的增删改查逻辑。
- 使用方通过 ContentResolver + URI 发起请求。
- 系统根据 URI 的 authorities 找到对应的 ContentProvider。
- 调用 ContentProvider 中对应的方法,返回结果(如 Cursor)给使用方。
这样就在两个独立应用进程之间实现了安全、统一的数据共享。
6. 分析 Fragment 与 Activity 的联系
联系:
-
依附关系:Fragment 必须依附于 Activity 才能存在和显示,不能独立运行。一个 Activity 可以包含多个 Fragment,一个 Fragment 也可以在多个 Activity 中复用。
-
生命周期关联:Fragment 的生命周期受所依附 Activity 的生命周期影响。Activity 暂停,Fragment 也暂停;Activity 销毁,Fragment 也销毁。但 Fragment 比 Activity 多了几个生命周期方法(如
onAttach()、onCreateView()、onActivityCreated()、onDetach())。 -
通信方式:
- Activity 调用 Fragment:通过
FragmentManager.findFragmentById()找到 Fragment 实例,然后调用其公开方法。 - Fragment 调用 Activity:通过
getActivity()获取宿主 Activity 引用。 - Fragment 之间:通常通过宿主 Activity 中转,或使用接口回调、ViewModel、EventBus 等方式通信。
- Activity 调用 Fragment:通过
-
UI 构成:Fragment 拥有自己的布局和 UI,可被动态添加、移除、替换到 Activity 的视图容器中,实现灵活的界面组合(特别适合平板等大屏设备)。
-
管理:Fragment 由 Activity 中的
FragmentManager管理,通过FragmentTransaction进行添加(add)、移除(remove)、替换(replace)等操作。
二、程序设计题
1. MainActivity 与 SecondActivity 数据传递
MainActivity.java
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
Button btn1 = findViewById(R.id.btn1); Button btn2 = findViewById(R.id.btn2);
btn1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(MainActivity.this, "欢迎进入考试系统", Toast.LENGTH_SHORT).show(); } });
btn2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(MainActivity.this, SecondActivity.class); intent.putExtra("number", "20230001"); intent.putExtra("name", "张三"); intent.putExtra("age", 20); startActivity(intent); } }); }}SecondActivity.java
public class SecondActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_second);
TextView tvShow = findViewById(R.id.tv_show);
Intent intent = getIntent(); String number = intent.getStringExtra("number"); String name = intent.getStringExtra("name"); int age = intent.getIntExtra("age", 0);
tvShow.setText("学号:" + number + "\n姓名:" + name + "\n年龄:" + age); }}2. 两数相乘并显示结果
MainActivity.java
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.ss); // 布局文件 ss.xml
final EditText ed1 = findViewById(R.id.ed_number1); final EditText ed2 = findViewById(R.id.ed_number2); final TextView tv = findViewById(R.id.tv); Button btn = findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String s1 = ed1.getText().toString(); String s2 = ed2.getText().toString(); if (s1.isEmpty() || s2.isEmpty()) { tv.setText("请输入两个数字"); return; } double num1 = Double.parseDouble(s1); double num2 = Double.parseDouble(s2); double result = num1 * num2; tv.setText("结果:" + result); } }); }}3. SQLite 帮助类 MyHelper
public class MyHelper extends SQLiteOpenHelper {
public MyHelper(Context context) { super(context, "library.db", null, 1); }
@Override public void onCreate(SQLiteDatabase db) { String createTable = "create table book(" + "id integer primary key," + "name text," + "price real)"; db.execSQL(createTable);
// 插入两条记录 db.execSQL("insert into book(id, name, price) values(?, ?, ?)", new Object[]{1, "钢铁是怎样炼成的", 38.5}); db.execSQL("insert into book(id, name, price) values(?, ?, ?)", new Object[]{2, "告别内耗", 59.8}); }
@Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // 升级时的处理 }}使用:在 Activity 中
MyHelper helper = new MyHelper(this);SQLiteDatabase db = helper.getWritableDatabase(); // 触发 onCreate三、界面设计题(参考 XML 布局)
题目原图未提供,给出一个典型登录界面 XML 模板供参考。
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="20dp">
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="用户登录" android:textSize="24sp" android:gravity="center" android:layout_marginBottom="30dp"/>
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:layout_marginBottom="10dp">
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="用户名:" android:textSize="16sp"/>
<EditText android:id="@+id/et_username" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="请输入用户名"/> </LinearLayout>
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:layout_marginBottom="20dp">
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="密 码:" android:textSize="16sp"/>
<EditText android:id="@+id/et_password" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="textPassword" android:hint="请输入密码"/> </LinearLayout>
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:gravity="center">
<Button android:id="@+id/btn_login" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="登录" android:layout_marginRight="20dp"/>
<Button android:id="@+id/btn_cancel" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="取消"/> </LinearLayout></LinearLayout>四、程序分析题
1. 广播注册与发送的代码补全
public class MainActivity extends Activity { private MyReceiver receiver;
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); receiver = new MyReceiver(); IntentFilter filter = new IntentFilter("YourAction"); registerReceiver(receiver, filter); // 注册广播监听 }
public void myRegist(View view) { Intent intent = new Intent("YourAction"); Bundle bundle = new Bundle(); bundle.putString("way", "我的注册方式"); // 放入 String bundle.putDouble("number", 10.8); // 放入 double intent.putExtras(bundle); sendBroadcast(intent); // 发送广播 }
protected void onDestroy() { super.onDestroy(); unregisterReceiver(receiver); // 注销广播 }}2. MyReceiver 程序注释
public class MyReceiver extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { if (intent.getAction().equals("YourAction")) // 注释1:判断接收到的广播 Action 是否为 "YourAction",过滤目标广播 { String data = intent.getStringExtra("class"); // 注释2:从 intent 中取出键为 "class" 的 String 数据
Log.d("MyReceiver", "我的班级是:" + data); // 注释3:在 Logcat 中以 debug 级别打印取出的数据,便于调试
Bundle bundle = new Bundle(); bundle.putString("order", "尽快报到"); // 注释4:创建 Bundle 并放入键 "order"、值 "尽快报到" 的字符串数据
setResultExtras(bundle); // 注释5:将 bundle 作为有序广播的结果数据回传给下一个接收者或发送者 } }}3. Intent 传值代码补全
public class MainActivity extends Activity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
findViewById(R.id.button1).setOnClickListener(new OnClickListener() { // 1. 添加动作监听 public void onClick(View arg0) { Intent intent = new Intent(MainActivity.this, SecondActivity.class); // 2. 跳转 intent.putExtra("id", 110); // 3. 添加 int 类型数据 intent.putExtra("scores", 98.5); // 4. 添加 double 类型数据 startActivity(intent); // 5. 传递并启动 Activity } }); }}4. MyHelper 三个方法的功能
public class MyHelper extends SQLiteOpenHelper {
public MyHelper(Context context) { super(context, "courseSelect.db", null, 1); } // 方法1:构造方法。调用父类 SQLiteOpenHelper 的构造,指定数据库名为 // "courseSelect.db",使用默认游标工厂(null),数据库版本号为 1。
@Override public void onCreate(SQLiteDatabase db) { String createTable = "create table student" + "(id integer primary key autoincrement,name text,number text,gender text,age integer)"; db.execSQL(createTable); } // 方法2:当数据库**首次创建**时被调用。 // 通过 SQL 语句创建 student 表,包含 id(主键自增)、name、number、gender、age 五个字段。
@Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // TODO Auto-generated method stub } // 方法3:当数据库**版本升级**(构造方法中传入的版本号高于旧版本)时被调用, // 用于对旧表进行结构升级(如删除旧表、新建表、添加字段等迁移操作)。}5. Service 程序阅读题
public class MyService extends Service { public IBinder onBind(Intent arg0) { return null; }
public void onCreate() { super.onCreate(); Log.d("Service", "onCreate: 服务已创建"); }
public int onStartCommand(Intent intent, int flags, int startId) { Log.d("Service", "onStartCommand: 服务正在运行"); return START_STICKY; }
public void onDestroy() { super.onDestroy(); Log.d("Service", "onDestroy: 服务已停止"); }}(1)使用 startService() 启动后 LogCat 显示的内容
第一次启动时(服务还未创建)显示:
onCreate: 服务已创建onStartCommand: 服务正在运行如果再次调用 startService(),由于服务实例已存在,不会再调用 onCreate,只会调用 onStartCommand,输出:
onStartCommand: 服务正在运行(2)继承 Service 后必须重写的方法
必须重写 onBind(Intent intent) 方法(这是 Service 类中唯一的抽象方法)。
(3)onDestroy 方法何时执行?
在以下情况下被调用:
- 通过
stopService()显式停止服务; - 服务内部调用
stopSelf()自己停止; - 系统因内存紧张被强制回收时;
- 应用进程被结束时。
(4)Service 可以执行耗时操作吗?为什么?
不可以直接在 Service 中执行耗时操作。 因为 Service 默认运行在主线程(UI 线程)中,长时间耗时操作会阻塞主线程,导致 ANR(Application Not Responding)。 如果需要执行耗时操作,应当在 Service 内部开启子线程(new Thread 或 HandlerThread),或者使用 IntentService(已内置工作线程)。
(5)MyService 类需要在 AndroidManifest.xml 中注册吗?为什么?
需要注册。 Service 是 Android 四大组件之一,所有四大组件(Activity、Service、BroadcastReceiver、ContentProvider)都必须在清单文件中声明,否则系统无法识别和启动该组件,运行时会抛出异常。注册示例:
<service android:name=".MyService" />复习要点速记
- 四大组件:Activity、Service、BroadcastReceiver、ContentProvider,都需要在清单文件注册。
- Intent 传值:基本类型用
putExtra,复杂数据用Bundle+putExtras。 - 广播注册:静态(清单)/ 动态(代码 + 必须注销)。
- SQLite:继承
SQLiteOpenHelper,重写onCreate、onUpgrade。 - Service:默认主线程,耗时操作要开子线程;必须重写
onBind。 - Fragment:必须依附 Activity,通过 FragmentManager 管理。
考试加油 💪