认识安卓四大组件

Activity

创建一个新的界面的步骤

1、通过Intent启动

Intent intent = new Intent(MainActivity.this,SubActivity02.class)

2、新的界面绑定.xml

setContentView(R.layout.activity_sub02)

3、清单文件注册新的Activity

<activity android:name=".SubActivity02"> <activity>

4、新的Activity要继承Activity

public class SubActivity02 extends Activity

Activity界面切换

1、老方法(通过复写onActivityResult函数来接受返回结果),部分代码

@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
if(data == null)
{
return;
}
if(resultCode == requestCode && requestCode == 234)
{
String ret = data.getStringExtra("key1");
Log.i("This is ret",ret);
}
}
protected void onCreate(Bundle savedInstanceState)
{
btn_start = findViewById(R.id.btn_startActivity);
btn_start.setOnClickListener(new View.onClickListener(){
@Override
public void onClick(View view)
{
Intent intent = new Intent(MainActivity.this, SubActivity02.class);
stratActivity(intent);
}
});
@Override
public void onClick(View view)
{
Intent intent = new Intent(MainActivity.this, SubActivity03.class);
startActivityForResult(intent, 234);//234是请求码
}
}

2、新方法接受返回结果(通过ActivityResultLauncher),部分代码

ActivityReustltLauncher launcher = registerForActivity(new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<Activity>()
{
@Override
public void onActivityResult(ActivityResult result)
{
Log.i(lotTag, result.getData().getStringExtra("key1"));
}
btn_startForResult = findViewById(R.id.btn_startActivityGetResult);
btn_saartForResult.setOnClickListener(new View.OnClickListerer(){
Intent intent = new Intent(MainActivity.this, SubActivity03);
launcher.launch(intent);
});
});
/*ActivityResultLauncher 和 registerForActivityResult:

ActivityResultLauncher 是一个接口,用于启动目标活动并接收其结果。
registerForActivityResult 是一个新的方法,用于注册一个能够处理特定结果的 ActivityResultLauncher 实例。它接受两个参数:
第一个参数是一个 ActivityResultContract 的实例,用于指定要执行的操作类型。在这里使用的是 ActivityResultContracts.StartActivityForResult(),表示注册一个能够处理 startActivityForResult 操作的 launcher。
第二个参数是一个 ActivityResultCallback<ActivityResult> 的实例,用于处理从目标活动返回的结果。
onActivityResult 方法:
这是注册的 ActivityResultCallback 的实现部分。
当目标活动返回结果时,系统将调用 onActivityResult 方法,并传递一个 ActivityResult 对象作为参数。
在这里,通过 result.getData().getStringExtra("key1") 获取从目标活动返回的数据中名为 "key1" 的字符串数据,并将其记录到日志中。*/

SubActivity03.java,部分代码

public class SubActivity03 extends Activity
{
TestView tv;
@Override
super.onCreate(savadInstanceState);
setContentView(R.layout.activity_03);
tv.setOnClickListener(new View.OnClickerListener(){
@Override
public void onClick(View view)
{
Intent intent = new Intent();
intent.setClass(SubActivity03.this, MainActivity.class);
intent.putExtra("key1","这是结果1,来自SubActivity03");
setResult(234, intent);
SunActivity03.this.finish();
}
});
}

Service

1、通过startService、stopService,部分代码

在清单文件中注册Service

<service android:name=".service.MyService01"></service>
btn_startService = findViewById(R.id.btn_startService);
btn_startService.setOnClickeListener(new View.OnClickListener()
{
@Override
public void onClick(View view)
{
Intent intent = new Intent(MainActivity.this, MyService01.class);
startService(intent);
}
});
btn_stopService = findViewById(R.id.btn_stopService);
btn_stopService.setOnClickListener(new View.OnClickLintener()
{
@Override
public void onClick(View view)
{
Intent intent = new Intent(MainActivity.this, MyService01.class);
stopService(intent);
}
})

2、通过bindService和unbindService,部分代码

在清单文件中注册Service

<service android:name=".service.MyBindService"></service>
ServiceConnection conn = new ServiceConnection()
{
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder)
{
if(iBinder instanceof MyBindService.MyBinder)
{
myBinder = (MyBinderService.MyBinder)iBinder;
}
}
@Override
public void onServiceDisconnected(ComponentName componentName)
{
Log.i(logTag,"onServiceDisconnected");
}
//componentName 参数表示成功绑定的服务的组件名称
};


btn_bindService = findViewBtId(R.id.btn_bindService);
btn_binService.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view)
{
Intent intent = new Intent(MainActivity.this, MyBindService.class);
bindService(intent, conn, Context.BIND_AUTO_CREATE);
//Context.BIND_AUTO_CREATE 是一个标志位,表示如果Service还未创建,则在绑定时会自动创建它。
}
});
btn_unBindService = findViewById(R.id.btn_unbindService);
btn_unBindService.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view)
{
try
{
unbindService(conn);
}catch(Exception e)
{
e.printStackTrace();
}
}
//在Android开发中,绑定Service和解绑Service通常需要成对使用,确保在不需要与Service通信时及时解绑,避免资源浪费或内存泄漏。
//如果未绑定Service就调用 unbindService(conn),会引发异常,因此通常在执行解绑操作之前需要先确认是否已经绑定了Service
});

MyBindService,部分代码

public class MyBindService extends Service
{
String logTag = "qqqqqqqq";
private MyBinder binder = new MyBinder();
public class MyBinder extends Binder
{
public MyBinder()
{
Log.i(logTag,"in MyBinder");
}
public MyBinderService getServiceBinder()
{
return MyBinderService.this;
}
@Override
public void onCreate()
{
super.onCreate;
}
@Override
public void onDestroy()
{
super.onDertroy;
}
@Nullable
@Override
public IBinder onBind(Intent intent)
{
return binder;
}
@Override
public boolean onUnbind(Intent intent)
{
Log.i(logTag, "onUnbind");
return super.onUnbind(intent);
}
}
}

BroadcastReceiver介绍

静态注册

无序广播

<receiver android:name=".MyReceiver.MyReceiver"
android:exported="false">
<!--android:exported="false" 指定了该接收器是否能被其他应用组件调用或者是从外部调用。false 表示这个接收器仅对自己的应用可见,其他应用无法直接调用它。-->
<intent-filter>
<action android:name="golvRuleaa"></action>
</intent-filter>
<!--<intent-filter> 标签定义了接收器可以处理的广播意图(Intent)过滤器。<action> 标签用于指定接收器要处理的广播动作(Action)。在这个例子中,动作名称是 "golvRuleaaa"。这表示接收器只会对发送这个特定动作的广播进行处理。-->
</receiver>

有序广播(设置优先级)

<receiver android:name=".MyReceiver.OrderReceiver01"
android:exported="false">
<intent-filter android:priority="1000">
<action android:name="guolvRuleaaa"></action>
</intent-filter>
</receiver>
<receiver android:name=".MyReceiver.OrderReceiver02"
android:exprted="false">
<intent-filter android:priority="500">
<action android:name="guolvRuleaaa"></action>
</intent-filter>
</receiver>
<receiver android:name=".MyReceiver.OrderReceiver02"
android:exported="false">
<intent-filter android:priority="100">
<action android:name="guolvRuleaaa"></action>
</intent-filter>
</receiver>

动态注册(在MainActivity中)

OrderReceiver01 orderReceiver01 = new OrderReceive01();
OrderReceiver02 orderReceiver02 = new OrderReceive02();
OrderReceiver03 orderReceiver03 = new OrderReceiver03();
IntentFileter intentFileter = new IntentFilter();
intentFliter.addAction("guolvRuleaaa");
registerReceiver(orderReceiver01, intentFilter);
registerReceiver(orderReceiver02, intentFilter);
registerReceiver(orderReceiver03, intentFilter);

有序广播和无序广播,部分代码

btn_sendBroadcast = findViewById(R.id.btn_broadcast);
btn_sendBroadcast = setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view)
{
Intent intent = new Intent(MainActivity.this, MyReceiver.class);
intent.setAction("guolvRuleaaa");
intent.putRxtra("key2","这是无序广播的内容1");
sendBroadcast(intent);
}
});
OrderReceiver01 orderReceiver01 = new OrderReceiver01();
OrderReceiver02 orderReceiver02 = new OrderReceiver02();
OrderReceiver03 orderReceiver03 = new OrderReceiver03();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("guolvRuleaaa");
registerReceiver(orderReceiver01, intentFilter);
registerReceiver(orderReceiver02, intentFilter);
registerReceiver(orderReceiver03, intentFilter);
btn_orderBroadcast = findViewById(R.id.btn_orderBroadcast);
btn_orderBroadcast.setOnClickListener(new View.OnCLickListener)
{
@Override
public void onClick(View view)
{
Intent intent = new Intent();
intent.setAction = "guolvRuleaaa";
String data = "这是原始数据";
Bundle extData = new Bundle();
sendOrderedBroadcast(intent, null, new MyReceiver(),null,0,data,extData);
}
}
//sendOrderedBroadcast共有8个参数
/*1、Intent intent:
表示要发送的广播的意图(Intent)。这个意图描述了广播的动作(Action)、数据(Data)、类别(Category)等信息。

2、String receiverPermission:
这是一个可选的参数,用于指定接收者(Broadcast Receiver)的权限。如果指定了权限,则只有持有相同权限的接收者才能接收到这个广播。

3、BroadcastReceiver resultReceiver:
这是一个可选的参数,表示最终接收广播结果的 BroadcastReceiver。如果为 null,则系统会忽略这个参数。

4、Handler scheduler:
这是一个可选的参数,用于指定接收者接收广播的消息队列。如果为 null,则系统会使用当前线程的消息队列来处理广播接收者。

5、int initialCode:
这是一个整型参数,用于指定初始的广播接收者接收到的初始代码值。

6、String initialData:
这是一个可选的参数,表示初始广播接收者接收到的初始数据。

7、Bundle initialExtras:
这是一个可选的参数,用于指定初始广播接收者接收到的初始扩展数据(Extras)。

8、String[] initialPermissions:
这是一个可选的参数,用于指定初始广播接收者接收到的初始权限。*/

OrderReceiver01.java

public class OrderReceiver01 extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
if(action.equals("guolvRuleaaa"))
{
String data = getResultData();
Log.i("OrderReceiver01,","接收到内容"+data);
setResultData("内容已经被OrderReceive01修改");
}
}
}

OrderReceiver02.java

public class OrderReceiver02 extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
String action = "guolvRuleaaa";
if(action.equals("guolvRuleaaa"))
{
Log.i("OrderReceiver02","接收到内容,"+data);
setResultData("内容已经被OrderReceiver02修改")
}
}
}

OrderReceiver03.java

public class OrderReceiver03 extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
if(action.equals("guolvRuleaaa"))
{
Log.i("OrderReceiver03","接收到内容,"+data);
setResultData("内容已经被OrderReceiver03修改");
}
}
}

Content Provider

在数据库的清单中申请创建权限

<permisson android:name="myDB.permisson" android:protectionLevel="normal"></permisson>

在要使用该数据库的Moudle的清单文件中申请使用权限

<uses-permission android:name="myDB.permission"></uses-permission>

MainActivity.java,部分代码

int uid = 40;
static final Uri uri = Uri.parse("content://a.b.c.db.authority/user");
//Uri.parse() 是 Uri 类的静态方法,用于将字符串表示的 URI 解析为 Uri 对象
btn_add = findViewById(R.id.btn_add);
btn_add.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view)
{
ContentValues values = new ContentValues();
values.put("uid",uid++);
valuse.put("name","hyq");
valuse.put("age","20");
values.put("score",78);
ContentResolver contentResolver = getContentResolver();
contentResolver.insert(uri,values);
}
});
btn_del = findViewById(R.id.btn_del);
btn_del.setOnClickListener(new View.OnclickListener()
{
@Override
public void onClick(View view)
{
ContentResolver contentResolver = getContentResolver();
int delCount = contentResolver.delete(uri,"uid>?",new String[]{"4"});
if(delCount > 0)
{
Log.i(logTag,"del Count:" + delCount);
}
}
//使用 getContentResolver() 获取到 ContentResolver 实例后,调用其 delete 方法时,它会根据提供的 Uri 找到匹配的 ContentProvider,然后调用该 ContentProvider 中定义的 delete 方法来执行删除操作。这个过程是通过 Android 系统内部的内容提供器机制来实现的。
});
btn_update = findViewById(R.id.btn_update);
btn_update.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view)
{
ContentValues values= new ContentValues();
vlaues.put("age","20");
ContentResolver contentResolver = getContentResolver();
ing updateCount = contentResolver.update(uri,values,"uid=?",new String[]{"3"});
if(updateCount>0)
{
Log.i("qqqqqqqq","update Count"+updateCount);
}
}
});
btn_search = findViewById(R.id.btn_search);
btn_search = setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view)
{
ContentResolver contetnResolver = getContentResolver();
Cursor cursr = contentResolver.query(uri,new String[]{"uid","name","age","score"},null,null,null);
if(cursor == null)
{
return;
}
while(cursor.moveToNext())
{
@SuppressLint("Range") int uid = cursor.getInt(cursor.getColumnIndex("uid"));
@SuppressLint("Range") String name = cursor.getString(cursor.getColumnIndex("name"));
@SuppressLint("Range") int age = cursor.getInt(cursor.getColumnIndex("age"));
@SuppressLint("Range") int score= cursor.getInt(cursor.getColumnIndex("score"));
Log.i(logtag,"uid="+uid+",name="+name+",age="+age+",score="+score);
}
}
/*contentResolver.query(uri, ...):
contentResolver 是通过 getContentResolver() 方法获取的 ContentResolver 实例,用于与应用程序中的内容提供器进行通信。

query(uri, ...) 是 ContentResolver 提供的方法,用于执行查询操作。
uri:
uri 是一个统一资源标识符(URI),用于指定要查询的数据集合的位置和结构。在 Android 中,每个内容提供器都有一个唯一的 URI,用于访问其数据。在你的代码中,uri 可能是你在 MainActivity 中定义的某个位置的 URI,用于访问特定的数据表或者特定的数据集合。

new String[]{"uid", "name", "age", "score"}:
这部分定义了要返回的列集合,即投影。在查询结果中,只会包含这些列的数据。

null, null, null:
这三个 null 分别代表查询的选择条件 (selection 参数,类似 SQL 中的 WHERE 子句),选择条件参数 (selectionArgs 参数),以及查询结果的排序方式 (sortOrder 参数)。
在这里,它们都是 null,表示查询将返回指定表格的所有数据,没有额外的筛选条件或排序要求。*/
});

DBHelper.java

public class DBHelper extends SQLiteOpenHelper
{
private static final String DBNAME = "myDbName.db";
private static final int VERSION = 1;
public static final String TABLE_USER = "user";
public DBHelper(@Nullable Contextt context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version)
{
super(context, DBNAME,factory, VERSION);
}
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase)
{
String sqlStr = "create table if not exits " + TABLE_USER +
"(uid INTERGER PRIMARY KEY AUTOINCREMENT,"+
"name VARCHAR(30),"+
"age INTERGER,"+
"score DOUBLE)";
//注意一定要加空格,否则会出错
sqLiteDatabase.execSQL(sqlStr);
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase,int i,int i1)
{

}
}

MyProvider.java

public class MyProvider extends ContentProvider
{
private static final UriMatcher uriMatcher;
private static final String AUTHORITY_PROVIDER = "a.b.c.db2.authority";//定义了内容 提供器的授权信息
private static final int CODE_PROVIDER_USER = 11;//用于标识用户表格的 Uri 匹配码
private DBHelper dbHelper;
private SqLiteDatabase db;
uriMatcher = new UriMatcher(UriMather.NO_MATCH);//UriMatcher.NO_MATCH 表示没有匹配时的返回值
uriMatcher.addURI(AUTHRITY_PROVIDER,DBHelper.TABLE_USER,CODE_PROVIDER_USER);
//addURI(AUTHRITY_PROVIDER, DBHelper.TABLE_USER, CODE_PROVIDER_USER) 将指定的授权和路径模式与匹配码关联起来。在这里,AUTHRITY_PROVIDER 是授权信息,DBHelper.TABLE_USER 是表格名,CODE_PROVIDER_USER 是匹配码。
@Override
public boolean onCreate()
{
dbHelper = new DBHelper(getContext(),"",null,1);
db = dbHelper.getWritableDatabase();
db.execSQL("insert into "+DBHelper.TABLE_USER+" values(1,'张三',19,87)" );
db.execSQL("insert into "+DBHelper.TABLE_USER+" values(2,'李四',18,87)" );
return true;//onCreate 方法在内容提供器创建时调用。返回 false,表示内容提供器的初始化失败。通常应该在这里进行初始化操作,并返回相应的结果。
}
public Cursor query(@NonNull Uri uri, @Nullable String[] strings, @Nullable String s, @Nullable String[] string1, @Nullable String s1)//@NonNull Uri uri 是一个在Java或Kotlin中常见的注解语法,用于表示参数 uri 不应为 null
{
return null;
/*Uri uri:表示要查询的数据的 URI(统一资源标识符)。
String[] strings:表示查询中的投影列(要返回的列)。
String s:表示查询中的选择条件(类似 SQL 中的 WHERE 子句)。
String[] strings1:表示查询中的选择条件参数(用于替换选择条件中的占位符)。
String s1:表示查询结果的排序方式(类似 SQL 中的 ORDER BY 子句)。*/
}
@Nullable
@Override
public String getType(@NonNull Uri uri)
{
return "";
}
public String getTableName(Uri uri)
{
String tableName = "";
if(uriMatcher.match(uri)==CODE_PROVIDER_USER)
{
tableName = DBHelper.TABLE_USER;
}
return tableName;
}
@Nullable
@Override
public Uri insert(@NonNull Uri uri, @Nullable ContentValues contentvalues)
{//@Nullable ContentValues contentValues:包含要插入的数据的键值对。
String tableName = getTableName(uri);
if(TextUtils.isEmpty(tablename))
{
return null;
}
long insetCount = db.insert(tableName,null,contentValues);
if(inserCount>0)
{
Log.i("qqqqqqqq","insert ok");
}
else
{
Log.i("qqqqqqqq","insert fail");
}
return uri;
}
@Override
public int delete(@NonNUll Uri uri, @Nullabe String s, @Nullable String[] strings)/*NonNull Uri uri:用于指定要操作的数据的 URI。
@Nullable String s:表示删除操作的选择条件(类似 SQL 中的 WHERE 子句)。
@Nullable String[] strings:表示删除操作的选择条件参数(用于替换选择条件中的占位符)*/
{
String tableName = getTableName(uri);
if(TextUtils.isEmpty(tableName))
{
return 0;
}
int deleteCount = db.delete(tableName,s,strings);
if(deleteCount>0)
{
Log.i("qqqqqqqq","delete ok");
}
else
{
Log.i("qqqqqqqq","delete fail");
}
return deleteCOunt;
}
@Override
public int update(@NonNull Uri uri, @Nullable ContentValues contentValues,@Nullabel String s,@Nullable String[] strings)
{
String tableName = getTableName(uri);
if(TextUtils.isEmpty)
{
return 0;
}
int updateCount = db.update(tableName,contentValues,s,strings);
if(updateCount>0)
{
Log.i("qqqqqqqq","update ok");
}
else
{
Log.i("qqqqqqqq","upadte fail");
}
return updateCount;
}
}