• 字节青训营|安卓基础知识笔记,快速入门!


    这是我参与「第四届青训营 」笔记创作活动的第1天

    安卓开发基础知识要掌握俩大板块:基础组件、通信组件。

    • 基础组件:界面组件、服务组件、广播组件和数据组件。
    • 通信组件:Handler、Binder

    1.界面组件

    1.1 Activity

    Activity:界面容器。

    1.1.1 生命周期

    在这里插入图片描述

    • 当一个Activity启动的时候:会调用onCreate->onStart->onResume。
    • 当一个Activity销毁的时候:会调用onPause->onStop->onDestroy(有时候调用不到,如系统杀死)。
    • 其中onStart和onStop是和界面是否可见相关的。
    • 以及onResume和onPause是和界面是否操作相关的。

    测试题 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后调用。
    们知道在重写onSaveInstanceStateonRestoreInstanceState的时候,默认代码是这样的:

    @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);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    当然也可以在AndroidManifest.xml通过配置对应Activity中的configChange属性使得在当前Activity运行时候发生以下情况不用销毁重建Activity。

    configChange:local(语言改变)、fontScale(字体大小改变)、orientation(方向改变)、keyboardHidden(键盘隐藏)。

    配置改变的回调函数:onConfigurationChanged()

    1.1.2 基本方法

    注册->布局->绑定

    Intent的调用:显式调用和隐式调用。

    • 显示调用:Intent(当前.this,跳转.class);
    • 隐式调用中所查找的Activity,默认都自带一个Category:,所以如果不指定Category的话,需要在AndroidManifest.xml中检查该Category是否已经添加在Intent-filter中。

    1.1.3 启动模式

    android:lanuchMode

    • Standard:正常模式,允许Activity重复

    • SingleTop:栈顶复用,不允许栈顶有连续重复的Activity

    • SingleTask:栈内复用,不允许栈内有连续重复的Activity

    • SingleInstance:全局复用,不允许系统全局内有连续重复的Activity

    1.2 Fragment

    Fragment:页面容器,解决碎片化。

    1.2.1 生命周期

    在这里插入图片描述

    1.2.2 基本用法

    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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    step 3.加载:静态加载和动态加载。

    • 静态加载:直接在所需要的Activity布局文件里面声明片段就可以了。在android:name中输入Fragment所在子类路径。切记,一定要写android:id
      通过这种方式,Activity可以直接通过findViewById()调用到Fragment。Fragment也可以通过getActivity()获得所绑定容器的Activity,也可以继续套娃,获得所绑定容器的其他Fragment。
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 动态加载:类似于JDBC的事务管理。
    FragmentManager supportFragmentManager = getSupportFragmentManager();
    FragmentTransaction fragmentTransaction = supportFragmentManager.beginTransaction();
    fragmentTransaction.replace(R.id.framelayout1,fragment); //我这里是有个业务,通过FrameLayout切换Fragment
    fragmentTransaction.addToBackStack(null);
    fragmentTransaction.commit();
    
    • 1
    • 2
    • 3
    • 4
    • 5

    1.2.3 与Activity交互

    学习参考链接

    • 组件获取

    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);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    //在onCreateView()中获取Bundle,解析数据
    Bundle arguments = getArguments();
    String msg= arguments.getString("messqge");
    
    • 1
    • 2
    • 3

    2.Fragment数据传给Activity:

    a.通过对象直接传递

    b.通过viewmodle/eventbus/handler/broadcast等通信

    2 服务组件

    Service :Android实现程序后台运行的解决方案。

    • startService:启动不关心
    • bindService:启动需交互

    2.1 生命周期

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j8J6YqWJ-1659195952934)(https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/a1bf7358c6414a82b3e1860c91890958~tplv-k3u1fbpfcp-watermark.image?)]

    • onCreate():Service第一次创建的时候调用。
    • onStartCommand():Service每一次创建的时候调用。
    • onDestroy():Service销毁的时候调用。

    2.2 基本用法

    2.2.1:注册Service

    
    
    • 1
    • 2
    • 3
    • 4

    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")
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    2.2.3:通过Intent启动Service

    val intent=Intent(this,MyService::class.java);
    startService(intent);//启动
    //stopService(intent);//停止
    
    • 1
    • 2
    • 3

    2.3 与Activity的交互通信

    为什么需要通信?让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();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    //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不会执行该回调
    
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    //4.Activity中调用bindService方法,并传递步骤3的ServiceConnection对象,将流程跑起来
    val intent=Intent(this,MyService::class.java);
    bindService(intent,conn, BIND_AUTO_CREATE);//绑定
    //unbindService(conn)//解绑
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    3 广播组件

    Broadcast

    3.1 基本用法

    3.1.2 动态注册

    val intentFilter=IntentFilter()
    intentFilter.addAction("xxx")
    //myReceiver是实现了BroadcastReceiver类并重写onReceive()的对象
    context.registerReceiver(myReceiver,intentFilter)
    
    • 1
    • 2
    • 3
    • 4

    3.1.3 静态注册

    可以在程序未启动的时候也能接受广播。

    //1.注册,在AndroidManifest.xml中使用
    
        
            
        
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    //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();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    val intent=Intent("com.example.testmeaage.MY_BROADCAST");
    
    intent.setPackage(packageName)
    //发送广播
    sendBroadcast(intent);
    
    • 1
    • 2
    • 3
    • 4
    • 5

    需要注意的静态注册的BroadcastReceiver是无法接收隐式广播的,默认情况下我们发出的自定义广播恰恰都是隐式广播。因此一定要调用setPackage(packageName),指定这条广播是发送给哪个应用程序,从而让它变成一条显示广播。

    3.2 常用系统广播

    //充电状态,或者电池的电量发生变化。电池的充电状态、电荷级别改变,不能通过组建声明接收这个广播,只有通过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;
     
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    4 数据组件

    4.1 ContentProvider

    详细介绍

    4.2 Intent

    context.startActivity(Intent)
    context.startService(Intent)
    context.sendBroadCast(Intent)
    
    • 1
    • 2
    • 3

    4.2.1 基本用法:Activity中有具体使用方法,显式+隐式。

    隐式需要注意的是:每个隐式Intent,都有一个默认的Category。

    4.2.2 系统能力:

    电话、短信、网页、邮件、地图、拍照、设置、市场

    使用:StartActivity(Intent);

    5 通信组件

    5.1 Handler

    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);
            })
    
    
        }
    
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    搭配着原理图看看就懂了

    Note:一个线程只能有一个Looper对象

    5.2 Binder

    原理分析

  • 相关阅读:
    【深入浅出Spring原理及实战】「夯实基础系列」360全方位渗透和探究Spring配置开发实战详解
    windows的软件修改图标
    小黑子的SSM整合
    应用软件安全保证措施方案书
    【JS笔记】JS中的DOM对象以及通过JS获取DOM结点,操作DOM属性
    数字孪生赋能实景三维中国建设分论坛成功举办
    小程序商城框架源码 小程序源码带前端+后台+数据库
    AI绘画Stable Diffusion XL 可商用模型!写实艺术时尚摄影级真实感大模型推荐(附模型下载)
    一文速学-时间序列分析算法之指数平滑法详解+Python代码实现
    如何在PostgreSQL中使用CTE(公共表表达式)来简化复杂的查询逻辑?
  • 原文地址:https://blog.csdn.net/alph258/article/details/126079540