这是我参与「第四届青训营 」笔记创作活动的第1天
安卓开发基础知识要掌握俩大板块:基础组件、通信组件。
Activity:界面容器。

测试题 1:Activity A跳转Activity B的时候会发生什么事情?
A:onCreate->onStart->onResume->onPause
B:onCreate->onStart->onResume
A:onStop
测试题 2:Activity B销毁掉跳转回A的时候会发生什么事情?
B:onPause
A:onRestart->onStart->onResume
B:onStop->onDestroy
为什么要再Paused后去创建另外一个Activity呢,是因为这样可以提高另外一个组件的加载时间,再创建加载后才销毁自己才是最好的方案。所以我们再该组件Stop中去操作自己的事情是最好的,这样不影响创建另一个组件的效率。
异常声明周期的情况:
在发生异常情况的时候,需要通过以下回调函数进行数据的保存恢复处理。
onSaveInstanceState(Bundle outState):在Buddle中存储相关信息,该函数在onResume前调用。
onRestoreInstanceState(Bundle savedInstanceState):从Buddle中提取相关信息,该函数在onStart后调用。
们知道在重写onSaveInstanceState和onRestoreInstanceState的时候,默认代码是这样的:
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
//ousState.setXXX(k,v);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
//savedInstanceState.getXXX(k,v);
}
当然也可以在AndroidManifest.xml通过配置对应Activity中的configChange属性使得在当前Activity运行时候发生以下情况不用销毁重建Activity。
configChange:local(语言改变)、fontScale(字体大小改变)、orientation(方向改变)、keyboardHidden(键盘隐藏)。
配置改变的回调函数:onConfigurationChanged()
注册->布局->绑定
Intent的调用:显式调用和隐式调用。
Intent(当前.this,跳转.class);,所以如果不指定Category的话,需要在AndroidManifest.xml中检查该Category是否已经添加在Intent-filter中。android:lanuchMode
Standard:正常模式,允许Activity重复
SingleTop:栈顶复用,不允许栈顶有连续重复的Activity
SingleTask:栈内复用,不允许栈内有连续重复的Activity
SingleInstance:全局复用,不允许系统全局内有连续重复的Activity
Fragment:页面容器,解决碎片化。

step 1.创建布局文件。
step 2.创建Fragment子类并绑定布局文件。
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_blank2, container, false);
}
step 3.加载:静态加载和动态加载。
android:name中输入Fragment所在子类路径。切记,一定要写android:id。findViewById()调用到Fragment。Fragment也可以通过getActivity()获得所绑定容器的Activity,也可以继续套娃,获得所绑定容器的其他Fragment。
FragmentManager supportFragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = supportFragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.framelayout1,fragment); //我这里是有个业务,通过FrameLayout切换Fragment
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
1.Fragment获取Activity中的组件:getActivity().findViewId(R.id.xxx)
2.Activity获取Fragment中的组件:getFragmentManager().findFragmentByid(R.id.Fagment_xxx)
1.Activity数据传给Fragment:
//Activity中创建Fragment前存入Bundle中
Bundle bundle=new Bundle();
bundle.putString("messqge","xinxi");
BlankFragment bf=new BlankFragment();
bf.setArguments(bundle);
//在onCreateView()中获取Bundle,解析数据
Bundle arguments = getArguments();
String msg= arguments.getString("messqge");
2.Fragment数据传给Activity:
a.通过对象直接传递
b.通过viewmodle/eventbus/handler/broadcast等通信
Service :Android实现程序后台运行的解决方案。
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j8J6YqWJ-1659195952934)(https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/a1bf7358c6414a82b3e1860c91890958~tplv-k3u1fbpfcp-watermark.image?)]](https://1000bd.com/contentImg/2022/08/03/073150878.png)
onCreate():Service第一次创建的时候调用。onStartCommand():Service每一次创建的时候调用。onDestroy():Service销毁的时候调用。2.2.1:注册Service
2.2.2:创建Service子类
class MyService : Service() {
val TAG="MyService";
override fun onCreate() {
super.onCreate()
Log.d(TAG, "onCreate: ")
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
return super.onStartCommand(intent, flags, startId)
Log.d(TAG, "StartCommand: ")
}
override fun onDestroy() {
super.onDestroy()
Log.d(TAG, "Destroyed: ")
}
override fun onBind(intent: Intent?): IBinder? {
TODO("Not yet implemented")
}
}
2.2.3:通过Intent启动Service
val intent=Intent(this,MyService::class.java);
startService(intent);//启动
//stopService(intent);//停止
为什么需要通信?让Service可控。而不是启动了Service之后就和Activity没有关系了。那这时候就需要使用onBind()方法了。
class MyService : Service() {
//1.定义Binder子类,并实现getService()方法,返回Service对象
class TestBinder:Binder(){
private val res:Int=0;
fun testMsg(){
Log.d("TestBinder", "testMsg: ")
}
fun getRes():Int{
return res;
}
}
//2.实现Service类onBind()方法,返回上述Binder对象
override fun onBind(intent: Intent?): IBinder? {
Log.d("MyService", "onBind: ")
return TestBinder();
}
}
//3.实例化ServiceConnection对象,实现onServiceConnected方法,从中获取到Service实例
var testBinder : MyService.TestBinder?=null;
val conn=object:ServiceConnection{
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
testBinder=service as MyService.TestBinder;
testBinder?.testMsg();
//println(testBinder?.getRes());
Log.d("MyService", "onServiceConnected: "+testBinder?.getRes())
}
override fun onServiceDisconnected(name: ComponentName?) {
//只有发生异常断开的时候才会执行这个回调,如果Service是正常Destroy不会执行该回调
}
}
//4.Activity中调用bindService方法,并传递步骤3的ServiceConnection对象,将流程跑起来
val intent=Intent(this,MyService::class.java);
bindService(intent,conn, BIND_AUTO_CREATE);//绑定
//unbindService(conn)//解绑
Broadcast
val intentFilter=IntentFilter()
intentFilter.addAction("xxx")
//myReceiver是实现了BroadcastReceiver类并重写onReceive()的对象
context.registerReceiver(myReceiver,intentFilter)
可以在程序未启动的时候也能接受广播。
//1.注册,在AndroidManifest.xml中使用
//2.创建,建立相应的BroadcastReceiver实现类
class MyTimeReceiver : BroadcastReceiver() {
//3.接收,在步骤2类中的onReceive中接收广播
override fun onReceive(context: Context, intent: Intent) {
// This method is called when the BroadcastReceiver is receiving an Intent broadcast.
Log.d("TimeReciver", "onReceive: ")
Toast.makeText(context,"Time changed",Toast.LENGTH_LONG).show();
}
}
val intent=Intent("com.example.testmeaage.MY_BROADCAST");
intent.setPackage(packageName)
//发送广播
sendBroadcast(intent);
需要注意的静态注册的BroadcastReceiver是无法接收隐式广播的,默认情况下我们发出的自定义广播恰恰都是隐式广播。因此一定要调用setPackage(packageName),指定这条广播是发送给哪个应用程序,从而让它变成一条显示广播。
//充电状态,或者电池的电量发生变化。电池的充电状态、电荷级别改变,不能通过组建声明接收这个广播,只有通过Context.registerReceiver()注册
Intent.ACTION_BATTERY_CHANGED;
//设备当前设置被改变时发出的广播(包括的改变:界面语言,设备方向,等,请参考Configuration.java)
Intent.ACTION_CONFIGURATION_CHANGED;
//在系统启动完成后,这个动作被广播一次(只有一次)。
Intent.ACTION_BOOT_COMPLETED;
//成功的安装APK之后//广播:设备上新安装了一个应用程序包。//一个新应用包已经安装在设备上,数据包括包名(最新安装的包程序不能接收到这个广播)
Intent.ACTION_PACKAGE_ADDED;
//一个已存在的应用程序包已经改变,包括包名
Intent.ACTION_PACKAGE_CHANGED;
//触发一个下载并且完成安装时发出的广播,比如在电子市场里下载应用
Intent.ACTION_PACKAGE_INSTALL;
//成功的删除某个APK之后发出的广播, 一个已存在的应用程序包已经从设备上移除,包括包名(正在被安装的包程序不能接收到这个广播)
Intent.ACTION_PACKAGE_REMOVED;
//替换一个现有的安装包时发出的广播(不管现在安装的APP比之前的新还是旧,都会发出此广播)
Intent.ACTION_PACKAGE_REPLACED;
//用户重新开始一个包,包的所有进程将被杀死,所有与其联系的运行时间状态应该被移除,包括包名(重新开始包程序不能接收到这个广播)
Intent.ACTION_PACKAGE_RESTARTED;
//屏幕被关闭之后的广播
Intent.ACTION_SCREEN_OFF;
//屏幕被打开之后的广播
Intent.ACTION_SCREEN_ON;
context.startActivity(Intent)
context.startService(Intent)
context.sendBroadCast(Intent)
隐式需要注意的是:每个隐式Intent,都有一个默认的Category。
电话、短信、网页、邮件、地图、拍照、设置、市场
使用:StartActivity(Intent);
class MainActivity : AppCompatActivity() {
val alterText=1;
//1.创建:新建handler,实现handleMessage()
val handler=object: Handler(Looper.getMainLooper()){
//4.处理:在handler的handleMessage中处理更新UI
override fun handleMessage(msg: Message) {
when(msg.what){
alterText->text1.text="Hello"
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn_1.setOnClickListener({
//2.构造Message,设置what
val msg=Message();
msg.what=alterText;
//3.发送:子线程调用sendMessage(Message)发送Message
handler.sendMessage(msg);
})
}
}
搭配着原理图看看就懂了
Note:一个线程只能有一个Looper对象