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

这是我参与「第四届青训营 」笔记创作活动的第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);
}

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

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

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

1.1.2 基本方法

注册->布局->绑定

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

  • 显示调用:Intent(当前.this,跳转.class);
  • 隐式调用中所查找的Activity,默认都自带一个Category:<category android:name="android.intent.category.DEFAULT"/>,所以如果不指定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);
}

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

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

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

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

<service
    android:name=".MyService"
    android:enabled="true"
    android:exported="true"></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);//停止

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();
    }
}
//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)//解绑

3 广播组件

Broadcast

3.1 基本用法

3.1.2 动态注册

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

3.1.3 静态注册

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

//1.注册,在AndroidManifest.xml中使用<receiver.../><intent-filter.../>
<receiver
    android:name=".MyTimeReceiver"
    android:enabled="true"
    android:exported="true">
    <intent-filter>
        <action android:name="com.example.testmeaage.MY_BROADCAST"></action>
    </intent-filter>
</receiver>
//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),指定这条广播是发送给哪个应用程序,从而让它变成一条显示广播。

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;
 

4 数据组件

4.1 ContentProvider

详细介绍

4.2 Intent

context.startActivity(Intent)
context.startService(Intent)
context.sendBroadCast(Intent)
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);
        })


    }


}

搭配着原理图看看就懂了

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

5.2 Binder

原理分析

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值