一、Activity
在 Android 应用中,Activity 是一个非常核心的组件,用于表示应用的一个单一屏幕,是用户与应用交互的主界面。每个 Activity 提供一个窗口,用于绘制界面和接收与用户的交互事件。理解 Activity 的创建、生命周期和其基本用法对于开发 Android 应用至关重要。
一个 Android 应用通常由多个 Activity
组成,每个 Activity
都是一个独立的界面。当你打开一个应用,如邮箱应用,你看到的邮箱列表、邮件详情、写邮件等各个界面,通常都是不同的 Activity
。
Activity 的生命周期是其最重要的特征之一。Android 提供了一系列的回调方法来管理 Activity 的状态,包括用户开始使用 Activity、Activity 进入前台或后台,以及 Activity 被系统销毁的时刻。
下面是 Activity 生命周期的主要方法:
- onCreate(Bundle savedInstanceState): 当 Activity 被创建时调用。这是初始化界面、成员变量等的地方。
- onStart(): 当 Activity 对用户可见时调用。
- onResume(): 当 Activity 准备好与用户交互时调用,此时 Activity 位于前台。
- onPause(): 当系统即将启动或恢复另一个 Activity 时调用。用于保存数据或释放资源。
- onStop(): 当 Activity 不再对用户可见时调用。
- onDestroy(): 当 Activity 即将被销毁时调用。
上面是关于activity 这个控件的demo代码
二、Service
在 Android 开发中,Service
是一种用于在后台执行长时间运行的任务而不提供用户界面的应用组件。Service
可以在应用的前台或者后台执行任务,即使用户离开了应用。服务是用来处理不需要与用户交互而需要长期运行的操作,例如在后台播放音乐、执行文件下载等。
Service 主要有两种形式:
- 前台服务(Foreground Service):前台服务显示一个持续的通知,这意味着用户清楚地知道正在运行的服务。这种服务用于用户积极参与的任务(如播放音乐)或对用户很重要的任务(如文件下载)。
- 后台服务(Background Service):在应用不在屏幕上显示时执行的服务。从 Android Oreo(8.0)开始,后台服务的运行受到了严格限制以优化应用对设备电池生命的影响。
个人想法:前后台服务其实本质上没什么区别,唯一的区别就是前台会展示在页面上,但是后台不会。除此之外没有其他的区别。
Service 有自己的生命周期方法,用于管理其创建、启动、绑定和销毁过程:
- onCreate(): 服务创建时调用。
- onStartCommand(Intent intent, int flags, int startId): 每次通过 startService() 方法启动服务时调用。
- onBind(Intent intent): 当其他组件想要与服务绑定时调用,需要返回一个 IBinder 对象,通过该对象组件可以与服务进行通信。
- onUnbind(Intent intent): 当所有组件都与服务解除绑定时调用。
- onDestroy(): 服务销毁之前调用。
前台和后台本质上没有什么区别,就只写了一个后台的。
三、Broadcast Receiver
在 Android 中,Broadcast Receiver
(简称广播接收器)是一个用来处理来自系统或应用发出的广播通知的组件。它可以对诸如设备启动完成、电池电量变化、短信接收等系统事件做出响应,也可以接收应用自定义的广播消息。
广播接收器主要用于监听和响应广播消息。广播可以是系统广播(比如网络状态改变、屏幕关闭等),也可以是应用程序发送的广播。广播接收器本身没有用户界面,但它可以启动一个活动或服务来响应接收到的信息。
广播接收器不像 Activity 或 Service 那样拥有完整的生命周期。它只有一个回调方法 onReceive(Context context, Intent intent),当接收到广播时被调用。广播接收器的类型分为两种:
- 静态注册:在 AndroidManifest.xml 中注册。即使应用没有运行,只要事件发生,系统就会创建广播接收器的实例并调用它。
- 动态注册:在代码中注册,通常在 Activity 或 Service 中注册。它只在其宿主组件(如 Activity)存在时活跃。
这是动态的广播
这是静态的广播
在 AndroidManifest.xml 中注册
四、Content Provider
在 Android 中,Content Provider 是四大组件之一,用于在不同应用程序之间共享数据。它提供了一种封装数据的方式,并通过一套标准的 API 在应用之间进行数据访问。通过使用 Content Provider,一个应用可以允许其他应用访问其数据,而不需要直接访问底层数据库或文件系统。
Content Provider 管理对一个或多个数据源(如 SQLite 数据库)的访问,通过 URI(统一资源标识符)来暴露数据。每个 URI 可以指代 Content Provider 中的数据表或表内的特定数据行。通过这种方式,Content Provider 为数据访问提供了封装,并确保了数据访问的安全性。
核心组件
- URI: 每个 Content Provider 都通过一个唯一的 authority 来标识,该 authority 与 URI 结合使用,用来找到对应的 Content Provider。
- ContentResolver: 提供了一组 API,允许应用查询或修改由 Content Provider 管理的数据。应用通过调用 ContentResolver 的方法,如 query(), insert(), delete(), 和 update() 来执行操作。
package com.example.fourmajorcomponents; import android.content.ContentValues; import android.content.Intent; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; public class ContentProviderActivity extends AppCompatActivity { private static final String TAG = "ContentProviderActivity"; private static final Uri CONTENT_URI = Uri.parse("content://com.example.personprovider/person"); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.content_provider_activity); Log.d(TAG, "Activity onCreate"); Intent intent = new Intent(this, ContentProviderService.class); startService(intent); Log.d(TAG, "ContentProviderService started"); Button insertButton = findViewById(R.id.insert_button); Button queryButton = findViewById(R.id.query_button); insertButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { insertData(); } }); queryButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { queryData(); } }); } private void insertData() { ContentValues values = new ContentValues(); values.put("name", "Alice Johnson"); values.put("age", 28); Uri newPersonUri = getContentResolver().insert(CONTENT_URI, values); if (newPersonUri != null) { Log.d(TAG, "Inserted new person with URI: " + newPersonUri); Toast.makeText(this, "Inserted new person with URI: " + newPersonUri, Toast.LENGTH_LONG).show(); } else { Log.d(TAG, "Failed to insert data."); Toast.makeText(this, "Failed to insert data.", Toast.LENGTH_LONG).show(); } } private void queryData() { Cursor cursor = getContentResolver().query(CONTENT_URI, null, null, null, null); if (cursor != null) { String[] columnNames = cursor.getColumnNames(); Log.d(TAG, "Column names: " + String.join(", ", columnNames)); int nameIndex = cursor.getColumnIndex("name"); int ageIndex = cursor.getColumnIndex("age"); if (nameIndex == -1 || ageIndex == -1) { Log.e(TAG, "Columns 'name' or 'age' not found in cursor."); Toast.makeText(this, "No data found.", Toast.LENGTH_LONG).show(); cursor.close(); return; } StringBuilder sb = new StringBuilder(); while (cursor.moveToNext()) { String name = cursor.getString(nameIndex); int age = cursor.getInt(ageIndex); String personInfo = "Person - Name: " + name + ", Age: " + age; Log.d(TAG, personInfo); sb.append(personInfo).append("\n"); } cursor.close(); Toast.makeText(this, sb.toString(), Toast.LENGTH_LONG).show(); } else { Log.d(TAG, "No data found."); Toast.makeText(this, "No data found.", Toast.LENGTH_LONG).show(); } } }
package com.example.fourmajorcomponents; import android.app.Service; import android.content.Intent; import android.database.sqlite.SQLiteDatabase; import android.os.Binder; import android.os.IBinder; import android.util.Log; import androidx.annotation.Nullable; public class ContentProviderService extends Service { private static final String TAG = "ContentProviderService"; private SQLiteDatabase database; private final IBinder binder = new LocalBinder(); public class LocalBinder extends Binder { ContentProviderService getService() { return ContentProviderService.this; } } @Override public void onCreate() { super.onCreate(); Log.d(TAG, "Service onCreate"); DBHelper dbHelper = new DBHelper(this); database = dbHelper.getWritableDatabase(); Log.d(TAG, "Database initialized"); } @Nullable @Override public IBinder onBind(Intent intent) { Log.d(TAG, "Service onBind"); return binder; } public SQLiteDatabase getDatabase() { return database; } @Override public void onDestroy() { super.onDestroy(); if (database != null && database.isOpen()) { database.close(); Log.d(TAG, "Database closed"); } Log.d(TAG, "Service onDestroy"); } }
package com.example.fourmajorcomponents; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.util.Log; public class DBHelper extends SQLiteOpenHelper { private static final String TAG = "DBHelper"; private static final String DATABASE_NAME = "people.db"; private static final int DATABASE_VERSION = 1; public DBHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); Log.d(TAG, "DBHelper initialized"); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL("CREATE TABLE person (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, age INTEGER);"); Log.d(TAG, "Database table created"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL("DROP TABLE IF EXISTS person"); onCreate(db); Log.d(TAG, "Database upgraded"); } }
能实现app内资源共享
参考网站:
- https://zhuanlan.zhihu.com/p/529746684
- https://blog.csdn.net/wsyx768/article/details/138511342